chore: seed chinese traditional (#42005)

Seeds the chinese traditional files manually so we can deploy to
staging.
This commit is contained in:
Nicholas Carrigan (he/him)
2021-05-05 10:13:49 -07:00
committed by GitHub
parent e46e80e08f
commit 3da4be21bb
1669 changed files with 153114 additions and 678 deletions

View File

@@ -0,0 +1,53 @@
---
id: bd7168d8c242eddfaeb5bd13
title: 用條形圖可視化數據
challengeType: 3
forumTopicId: 301464
dashedName: visualize-data-with-a-bar-chart
---
# --description--
**目標:** 在 [CodePen.io](https://codepen.io) 上實現一個功能類似 <https://codepen.io/freeCodeCamp/full/GrZVaM> 的 App。
在滿足以下[需求](https://en.wikipedia.org/wiki/User_story)並能通過所有測試的前提下, 你可以根據自己的喜好來美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基於 svg 的 D3 可視化庫來完成這個挑戰。 該任務需要使用 D3 的座標軸屬性生成座標軸,這個屬性會自動生成沿軸的刻度。 通過 D3 測試需要這些刻度,因爲它們的位置被用來確定繪製元素的對齊方式。 你可以在這裏 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 獲取關於生成座標軸的信息。 每次測試查詢的元素都必須是非虛擬 DOM。 如果你使用了前端框架(例如 Vue那麼對於動態的內容測試結果可能不準確。 我們希望最終能夠兼容這些框架,但 D3 項目目前還不支持它們。
**需求 #1** 圖表應該包含一個具有 `id="title"` 屬性的標題。
**需求 #2** 圖表應該包含一個 `g` 元素作爲 x 軸,並相應地具有 `id="x-axis"` 屬性。
**需求 #3** 圖表應該包含一個 `g` 元素作爲 y 軸,並相應地具有`id="y-axis"` 屬性。
**需求 #4** 兩個軸都應包含多個刻度標籤,每個標籤具有 `class="tick"` 屬性。
**需求 #5** 在圖表裏,每個數據點都應該有一個具有 `class="bar"` 屬性的 `rect` 元素來展示數據。
**需求 #6** 每個數據條應該具有值爲 `date``data-date` 屬性以及值爲 `GDP``data-gdp` 屬性。
**需求 #7** 數據條元素的 `data-date` 屬性應與提供的數據的順序相匹配。
**需求 #8** 數據條元素的 `data-gdp` 屬性應與提供的數據的順序相匹配。
**需求 #9** 每個數據條元素的高度應準確地表示其數據所對應的 `GDP` 值。
**需求 #10** `data-date` 屬性和它對應的數據條元素應與 x 軸上的相應的值對齊。
**需求 #11** `data-gdp` 屬性和它對應的數據條元素應與 y 軸上的相應的值對齊。
**需求 #12** 我可以將鼠標懸停在某個區域上,並查看具有 `id="tooltip"` 屬性的提示框,它會顯示有關該區域的更多信息。
**需求 #13** 提示框應該有 `data-date` 屬性,它對應了當前激活區域的 `data-date` 屬性。
以下是完成此項目所需的數據: `https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json`
你可以<a href='https://codepen.io/pen?template=MJjpwO' target='_blank' rel='nofollow'>使用 CodePen 模板</a>來創建你的項目,點擊 `Save` 即可創建你的項目。 或者你可以在任何你喜歡的環境中使用以下 CDN 鏈接來運行測試:`https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`.
當你完成了本項目,並且該項目所有測試運行通過,請提交項目的 URL。
# --solutions--
```js
// solution required
```

View File

@@ -0,0 +1,52 @@
---
id: 587d7fa6367417b2b2512bbf
title: 用等值區域圖可視化數據
challengeType: 3
forumTopicId: 301465
dashedName: visualize-data-with-a-choropleth-map
---
# --description--
**目標:** 在 [CodePen.io](https://codepen.io) 上實現一個功能類似 <https://codepen.io/freeCodeCamp/full/EZKqza> 的 App。
在滿足以下[需求](https://en.wikipedia.org/wiki/User_story)並能通過所有測試的前提下, 你可以根據自己的喜好來美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基於 svg 的 D3 可視化庫來完成這個挑戰。 每次測試查詢的元素都必須是非虛擬 DOM。 如果你使用了前端框架(例如 Vue那麼對於動態的內容測試結果可能不準確。 我們希望最終能夠兼容這些框架,但 D3 項目目前還不支持它們。
**需求 #1** 等值區域圖包含一個具有 `id="title"` 屬性的標題。
**需求 #2** 等值區域圖包含一個具有 `id="description"` 屬性的描述內容。
**需求 #3** 等值區域圖包含一些州縣來展示數據,這些州縣應該具有 `class="county"` 屬性。
**需求 #4** 這些州縣至少應該有 4 種不同的填充顏色。
**需求 #5** 每個州縣都應該具有 `data-fips``data-education` 屬性,分別包含相應的值 `fips``education`
**需求 #6** 在等值區域圖中,每一個提供的數據點都應該有一個對應的州縣。
**需求 #7** 各個州縣應該具有與樣本數據匹配的 `data-fips``data-education` 值。
**需求 #8** 等值區域圖包含一個具有 `id="legend"` 屬性的圖例。
**需求 #9** 圖例至少應該使用 4 種不同的填充顏色。
**需求 #10** 將鼠標懸停在某個區域上時,可以看到具有 `id="tooltip"` 屬性的提示框,它會顯示有關該區域的更多信息。
**需求 #11** 提示框應該有 `data-education` 屬性,它對應了當前激活區域的 `data-education` 屬性。
以下是完成此項目所需的數據集:
- **US Education Data:** `https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/for_user_education.json`
- **US County Data:** `https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/counties.json`
你可以<a href='https://codepen.io/pen?template=MJjpwO' target='_blank' rel='nofollow'>使用 CodePen 模板</a>來創建你的項目,點擊 `Save` 即可創建你的項目。 或者你可以在任何你喜歡的環境中使用以下 CDN 鏈接來運行測試:`https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`.
當你完成了本項目,並且該項目所有測試運行通過,請提交項目的 URL。
# --solutions--
```js
// solution required
```

View File

@@ -0,0 +1,61 @@
---
id: bd7188d8c242eddfaeb5bd13
title: 用熱圖可視化數據
challengeType: 3
forumTopicId: 301466
dashedName: visualize-data-with-a-heat-map
---
# --description--
**目標:** 在 [CodePen.io](https://codepen.io) 上實現一個功能類似 <https://codepen.io/freeCodeCamp/full/JEXgeY> 的 App。
在滿足以下[需求](https://en.wikipedia.org/wiki/User_story)並能通過所有測試的前提下, 你可以根據自己的喜好來美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基於 svg 的 D3 可視化庫來完成這個挑戰。 每次測試查詢的元素都必須是非虛擬 DOM。 如果你使用了前端框架(例如 Vue那麼對於動態的內容測試結果可能不準確。 我們希望最終能夠兼容這些框架,但 D3 項目目前還不支持它們。
**需求 #1** 熱度圖包含一個具有 `id="title"` 屬性的標題。
**需求 #2** 熱度圖包含一個具有 `id="description"` 屬性的描述內容。
**需求 #3** 熱度圖包含一個具有 `id="x-axis"` 屬性的 x 軸。
**需求 #4** 熱度圖包含一個具有 `id="y-axis"` 屬性的 y 軸。
**需求 #5** 熱度圖包含一些 `rect` 元素來展示數據,他們具有 `class="cell"` 屬性。
**需求 #6** 這些單元格元素至少應該有 4 種不同的填充顏色。
**需求 #7** 每個單元格都有這些屬性:`data-month``data-year``data-temp`,具有相應的屬性值 `month``year``temperature`
**需求 #8** 每個元素的 `data-month``data-year` 屬性應該在數據範圍內。
**需求 #9** 熱度圖包含與 y 軸上的相應月份對齊的單元格。
**需求 #10** 熱度圖包含與 x 軸上相應年份對齊的單元格。
**需求 #11** 熱度圖在 y 軸上有多個刻度標籤,並帶有完整的月份名稱。
**需求 #12** 熱度圖在 x 軸上有多個刻度標籤,年份在 1754 到 2015 之間。
**需求 #13** 熱度圖包含一個具有 `id="legend"` 屬性的圖例。
**需求 #14** 圖例包含一些 `rect` 元素。
**需求 #15** 圖例中的這些 `rect` 元素應該至少使用 4 種不同的填充顏色。
**需求 #16** 將鼠標懸停在某個區域上時,可以看到具有 `id="tooltip"` 屬性的提示框,它會顯示有關該區域的更多信息。
**需求 #17** 提示框應該有 `data-year` 屬性,它對應了當前激活區域的 `data-year` 屬性。
以下是完成此項目所需的數據:`https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json`
你可以<a href='https://codepen.io/pen?template=MJjpwO' target='_blank' rel='nofollow'>使用這個 CodePen 模板</a>來創建你的項目,點擊 `Save` 即可創建你的項目。 或者你可以在任何你喜歡的環境中使用以下 CDN 鏈接來運行測試:`https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`.
當你完成了本項目,並且該項目所有測試運行通過,請提交項目的 URL。
# --solutions--
```js
// solution required
```

View File

@@ -0,0 +1,57 @@
---
id: bd7178d8c242eddfaeb5bd13
title: 用散點圖可視化數據
challengeType: 3
forumTopicId: 301467
dashedName: visualize-data-with-a-scatterplot-graph
---
# --description--
**目標:** 在 [CodePen.io](https://codepen.io) 上實現一個功能類似 <https://codepen.io/freeCodeCamp/full/bgpXyK> 的 App。
在滿足以下[需求](https://en.wikipedia.org/wiki/User_story)並能通過所有測試的前提下, 你可以根據自己的喜好來美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基於 svg 的 D3 可視化庫來完成這個挑戰。 該任務需要使用 D3 的座標軸屬性生成座標軸,這個屬性會自動生成沿軸的刻度。 這些刻度是通過 D3 測試所必需的,因爲它們的位置是用來確定圖表元素的對齊方式。 你可以在這裏 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 獲取關於生成座標軸的信息。 每次測試查詢的元素都必須是非虛擬 DOM。 如果你使用了前端框架(例如 Vue因爲內容是動態渲染的試結果可能不準確。 我們希望最終能夠兼容這些框架,但 D3 框架目前還不支持它們。
**需求 #1** 散點圖包含一個具有 `id="title"` 屬性的標題元素。
**需求 #2** 散點圖包含一個具有 `id="x-axis"` 屬性的 x 軸。
**需求 #3** 散點圖包含一個具有 `id="y-axis"` 屬性的 y 軸。
**需求 #4** 散點圖包含一些點,每個點都有一個值爲 `dot` 的 class 屬性,它代表了被繪製的數據。
**需求 #5** 每個點都應具有 `data-xvalue` 屬性和 `data-yvalue` 屬性,具有相應的屬性值 `x``y`
**需求 #6** 每個點的 `data-xvalue` 屬性和 `data-yvalue` 屬性應該在實際數據的範圍內,並且數據格式應該正確無誤。 對於`data-xvalue` ,可以接受整數(全年)或 `Date` 對象進行測試評估。 對於 `data-yvalue`(分鐘),應使用 `Date` 對象。
**需求 #7** `data-xvalue` 屬性和它對應的點應該和 x 軸上的點或值對齊。
**需求 #8** `data-yvalue`屬性和它對應的點應該和 y 軸上的點或值對齊。
**需求 #9** 散點圖的 y 軸上有多個時間格式爲 `%M:%S` 的刻度標籤。
**需求 #10** 散點圖的 x 軸上有多個顯示年份的刻度標籤。
**需求 #11** 散點圖的 x 軸標籤的範圍在實際 x 軸數據的範圍內。
**需求 #12** 散點圖的 y 軸標籤的範圍在實際 y 軸數據的範圍內。
**需求 #13** 散點圖包含一個包含描述性文字的圖例,它具有 `id="legend"` 屬性。
**需求 #14** 將鼠標懸停在某個區域上時,可以看到具有 `id="tooltip"` 屬性的提示框,它會顯示有關該區域的更多信息。
**需求 #15** 提示框應該有 `data-year` 屬性,它對應了當前激活區域的 `data-xvalue` 屬性。
以下是完成此項目所需的數據:`https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json`
你可以<a href='https://codepen.io/pen?template=MJjpwO' target='_blank' rel='nofollow'>使用這個 CodePen 模板</a>來創建你的項目,點擊 `Save` 即可創建你的項目。 或者你可以在任何你喜歡的環境中使用以下 CDN 鏈接來運行測試:`https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`.
當你完成了本項目,並且項目通過所有測試,請提交項目的 URL。
# --solutions--
```js
// solution required
```

View File

@@ -0,0 +1,53 @@
---
id: 587d7fa6367417b2b2512bc0
title: 用樹形圖可視化數據
challengeType: 3
forumTopicId: 301468
dashedName: visualize-data-with-a-treemap-diagram
---
# --description--
**目標:** 在 [CodePen.io](https://codepen.io) 上實現一個功能類似 <https://codepen.io/freeCodeCamp/full/KaNGNR> 的 App。
在滿足以下[需求](https://en.wikipedia.org/wiki/User_story)並能通過所有測試的前提下, 你可以根據自己的喜好來美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基於 svg 的 D3 可視化庫來完成這個挑戰。 該任務需要使用 D3 的座標軸屬性生成座標軸,這個屬性會自動生成沿軸的刻度。 這些刻度是通過 D3 測試所必需的,因爲它們的位置是用來確定圖表元素的對齊方式。 你可以在這裏 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 獲取關於生成座標軸的信息。 每次測試查詢的元素都必須是非虛擬 DOM。 如果你使用了前端框架(例如 Vue那麼對於動態的內容測試結果可能不準確。 我們希望最終能夠兼容這些框架,但 D3 項目目前還不支持它們。
**需求 #1** 矩陣樹圖包含一個具有 `id="title"` 屬性的標題。
**需求 #2** 矩陣樹圖包含一個具有 `id="description"` 屬性的描述內容。
**需求 #3** 矩陣樹圖包含一些具有 `class="tile"` 屬性的 `rect` 元素來展示數據。
**需求 #4** 這些矩形塊元素至少應該有 2 種不同的填充顏色。
**需求 #5** 每一個矩形元素應該有 `data-name``data-category``data-value` 屬性,具有相應的 `name``category``value` 屬性值。
**需求 #6** 每個矩形塊的面積和它的 `data-value` 屬性值相對應:`data-value` 值越大的矩形塊面積越大。
**需求 #7** 矩陣樹圖包含一個具有 `id="legend"` 屬性的圖例。
**需求 #8** 圖例包含一些具有 `class="legend-item"` 屬性的 `rect` 元素。
**需求 #9** 圖例中的這些 `rect` 元素至少應該使用 2 種不同的填充顏色。
**需求 #10** 將鼠標懸停在某個區域上時,可以看到具有 `id="tooltip"` 屬性的提示框,它會顯示有關該區域的更多信息。
**需求 #11** 提示框應該有 `data-value` 屬性,它對應了當前激活區域的 `data-value` 屬性。
對於此項目,您可以使用以下任何數據集:
- **Kickstarter Pledges** `https://cdn.freecodecamp.org/testable-projects-fcc/data/tree_map/kickstarter-funding-data.json`
- **Movie Sales** `https://cdn.freecodecamp.org/testable-projects-fcc/data/tree_map/movie-data.json`
- **Video Game Sales** `https://cdn.freecodecamp.org/testable-projects-fcc/data/tree_map/video-game-sales-data.json`
你可以<a href='https://codepen.io/pen?template=MJjpwO' target='_blank' rel='nofollow'>使用 CodePen 模板</a>來創建你的項目,點擊 `Save` 即可創建你的項目。 或者你可以在任何你喜歡的環境中使用以下 CDN 鏈接來運行測試:`https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js`.
當你完成了本項目,並且該項目所有測試運行通過,請提交項目的 URL。
# --solutions--
```js
// solution required
```

View File

@@ -0,0 +1,118 @@
---
id: 587d7faa367417b2b2512bd4
title: 給 D3 元素添加懸停效果
challengeType: 6
forumTopicId: 301469
dashedName: add-a-hover-effect-to-a-d3-element
---
# --description--
我們可以爲用戶的鼠標懸停行爲添加高亮顯示的效果。 到目前爲止,矩形的樣式應用了內置的 D3 和 SVG 方法,但是你也可以使用 CSS 來實現。
你可以使用 `attr()` 方法在 SVG 元素上設置 CSS class。 然後用 `:hover` 僞類爲你新添加的 CSS 類設置鼠標懸停的效果。
# --instructions--
`attr()` 方法給所有的 `rect` 元素都添加 `bar` class。 當鼠標懸停在元素上時,它的 `fill` 將變爲棕色。
# --hints--
`rect` 元素應該有 `bar` class。
```js
assert($('rect').attr('class') == 'bar');
```
# --seed--
## --seed-contents--
```html
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy")
// Add your code below this line
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3);
</script>
</body>
```
# --solutions--
```html
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy")
// Add your code below this line
.attr('class', 'bar')
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3);
</script>
</body>
```

View File

@@ -0,0 +1,175 @@
---
id: 587d7faa367417b2b2512bd6
title: 給 D3 元素添加工具提示
challengeType: 6
forumTopicId: 301470
dashedName: add-a-tooltip-to-a-d3-element
---
# --description--
當用戶在一個對象上懸停時,提示框可以顯示關於這個對象更多的信息。 在可視化中有多種方法添加提示框,這個挑戰將使用 SVG 的 `title` 元素。
`title``text()` 方法一起給每組動態添加數據。
# --instructions--
在每個 `rect` 節點下附加 `title` 元素。 然後用回調函數調用 `text()` 方法使它的文本顯示數據值。
# --hints--
你應該有 9 個 `title` 元素。
```js
assert($('title').length == 9);
```
第一個 `title` 元素的提示框文本應爲 `12`
```js
assert($('title').eq(0).text() == '12');
```
第二個 `title` 元素的提示框文本應爲 `31`
```js
assert($('title').eq(1).text() == '31');
```
第三個 `title` 元素的提示框文本應爲 `22`
```js
assert($('title').eq(2).text() == '22');
```
第四個 `title` 元素的提示框文本應爲 `17`
```js
assert($('title').eq(3).text() == '17');
```
第五個 `title` 元素的提示框文本應爲 `25`
```js
assert($('title').eq(4).text() == '25');
```
第六個 `title` 元素的提示框文本應爲 `18`
```js
assert($('title').eq(5).text() == '18');
```
第七個 `title` 元素的提示框文本應爲 `29`
```js
assert($('title').eq(6).text() == '29');
```
第八個 `title` 元素的提示框文本應爲 `14`
```js
assert($('title').eq(7).text() == '14');
```
第九個 `title` 元素的提示框文本應爲 `9`
```js
assert($('title').eq(8).text() == '9');
```
# --seed--
## --seed-contents--
```html
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy")
.attr("class", "bar")
// Add your code below this line
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (d * 3 + 3))
</script>
</body>
```
# --solutions--
```html
<style>
.bar:hover {
fill: brown;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy")
.attr("class", "bar")
.append("title")
.text((d) => d)
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (d * 3 + 3))
</script>
</body>
```

View File

@@ -0,0 +1,211 @@
---
id: 587d7fab367417b2b2512bd8
title: 給 Circle 元素添加屬性
challengeType: 6
forumTopicId: 301471
dashedName: add-attributes-to-the-circle-elements
---
# --description--
上個挑戰爲 `dataset` 中的每個點都創建了 `circle` 元素,並將它們添加到 SVG 畫布上。 但是 D3 需要更多關於位置和 `circle` 大小的信息來正確地顯示它們。
在 SVG 中 `circle` 有三個主要的屬性。 `cx``cy` 屬性是座標。 它們告訴 D3 將圖形的*中心*放在 SVG 畫布的何處。 半徑( `r` 屬性)給出 `circle` 的大小。
`rect``y` 座標一樣,`circle``cy` 屬性是從 SVG 畫布的頂端開始測量的,而不是從底端。
所有的屬性都可以用回調函數來動態設值。 記住,所有串聯在 `data(dataset)` 後面的方法會爲 `dataset` 中的每個對象都運行一次。 回調函數中的 `d` 參數指在 `dataset` 中的當前對象,對每個點來說都是一個數組。 你可以使用方括號的方式,如 `d[0]`,來訪問數組中的值。
# --instructions--
`circle` 元素添加 `cx``cy``r` 屬性。 `cx` 的值應該是 `dataset` 中每個對象的數組的第一個數, `cy` 的值應該根據數組中的第二個值,但是要確保正向顯示圖表而不是倒轉。 所有 circle 的 `r` 值應爲 `5`
# --hints--
你應該有 10 個 `circle` 元素。
```js
assert($('circle').length == 10);
```
第一個 `circle` 元素的 `cx` 值應爲 `34``cy` 值應爲 `422``r` 值應爲 `5`
```js
assert(
$('circle').eq(0).attr('cx') == '34' &&
$('circle').eq(0).attr('cy') == '422' &&
$('circle').eq(0).attr('r') == '5'
);
```
第二個 `circle` 元素的 `cx` 值應爲 `109``cy` 值應爲 `220``r` 值應爲 `5`
```js
assert(
$('circle').eq(1).attr('cx') == '109' &&
$('circle').eq(1).attr('cy') == '220' &&
$('circle').eq(1).attr('r') == '5'
);
```
第三個 `circle` 元素的 `cx` 值應爲 `310``cy` 值應爲 `380` `r` 值應爲 `5`
```js
assert(
$('circle').eq(2).attr('cx') == '310' &&
$('circle').eq(2).attr('cy') == '380' &&
$('circle').eq(2).attr('r') == '5'
);
```
第四個 `circle` 元素的 `cx` 值應爲 `79``cy` 值應爲 `89``r` 值應爲 `5`
```js
assert(
$('circle').eq(3).attr('cx') == '79' &&
$('circle').eq(3).attr('cy') == '89' &&
$('circle').eq(3).attr('r') == '5'
);
```
第五個 `circle` 元素的 `cx` 值應爲 `420``cy` 值應爲 `280``r` 值應爲 `5`
```js
assert(
$('circle').eq(4).attr('cx') == '420' &&
$('circle').eq(4).attr('cy') == '280' &&
$('circle').eq(4).attr('r') == '5'
);
```
第六個 `circle` 元素的 `cx` 值應爲 `233``cy` 值應爲 `355``r` 值應爲 `5`
```js
assert(
$('circle').eq(5).attr('cx') == '233' &&
$('circle').eq(5).attr('cy') == '355' &&
$('circle').eq(5).attr('r') == '5'
);
```
第七個 `circle` 元素的 `cx` 值應爲 `333``cy` 值應爲 `404``r` 值應爲 `5`
```js
assert(
$('circle').eq(6).attr('cx') == '333' &&
$('circle').eq(6).attr('cy') == '404' &&
$('circle').eq(6).attr('r') == '5'
);
```
第八個 `circle` 元素的 `cx` 值應爲 `222``cy` 值應爲 `167` `r` 值應爲 `5`
```js
assert(
$('circle').eq(7).attr('cx') == '222' &&
$('circle').eq(7).attr('cy') == '167' &&
$('circle').eq(7).attr('r') == '5'
);
```
第九個 `circle` 元素的 `cx` 值應爲 `78``cy` 值應爲 `180``r` 值應爲 `5`
```js
assert(
$('circle').eq(8).attr('cx') == '78' &&
$('circle').eq(8).attr('cy') == '180' &&
$('circle').eq(8).attr('r') == '5'
);
```
第十個 `circle` 元素的 `cx` 值應爲 `21``cy` 值應爲 `377``r` 值應爲 `5`
```js
assert(
$('circle').eq(9).attr('cx') == '21' &&
$('circle').eq(9).attr('cy') == '377' &&
$('circle').eq(9).attr('r') == '5'
);
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => d[0])
.attr("cy", (d) => h - d[1])
.attr("r", 5)
</script>
</body>
```

View File

@@ -0,0 +1,198 @@
---
id: 587d7fad367417b2b2512bdf
title: 添加座標軸到視圖中
challengeType: 6
forumTopicId: 301472
dashedName: add-axes-to-a-visualization
---
# --description--
另一種改進散點圖的方法是添加 x 軸和 y 軸。
D3 有兩種方法來渲染 y 軸和 x 軸,分別是 `axisLeft()``axisBottom()`。 下面是一個基於上個挑戰中的 `xScale` 創建 x 軸的例子:
```js
const xAxis = d3.axisBottom(xScale);
```
下一步是在 SVG 畫布上渲染 x 軸。 爲此,你可以使用一個 SVG 組件, `g` 元素, `g` 是英文中組group的縮寫。 不同於 `rect``circle``text`,在渲染時,軸只是一條直線。 因爲它是一個簡單的圖形,所以可以用 `g` 。 最後一步是使用 `transform` 屬性將軸放置在 SVG 畫布的正確位置上。 否則,軸將會沿着 SVG 畫布的邊緣渲染,從而不可見。 SVG 支持多種 `transforms`,但是定位軸需要使用 `translate` 屬性。 當它應用在 `g` 元素上時,它根據給出的總量移動整組。 下面是一個例子:
```js
const xAxis = d3.axisBottom(xScale);
svg.append("g")
.attr("transform", "translate(0, " + (h - padding) + ")")
.call(xAxis);
```
上部分代碼將 x 軸放置在 SVG 畫布的底端。 然後 x 軸作爲參數被傳遞給 `call()` 方法。 y 軸的定位也是這樣,只是 `translate` 參數的形式是 `(x, 0)`。 因爲 `translate``attr()` 方法中的一個字符串,你可以在參數中使用字符串的連接將變量值包括進去。
# --instructions--
現在散點圖有 x 軸了。 用 `axisLeft()` 方法創建 y 軸並賦值給 `yAxis` 變量, 然後通過 `g` 元素渲染 y 軸。 使用 `transform` 屬性將 y 軸向右平移(平移的單位等於 paading 的值),向下平移 `0` 個單位。 記得對 y 軸調用 `call()` 方法。
# --hints--
你應該使用 `axisLeft()` 方法,並傳入 `yScale` 作爲參數。
```js
assert(code.match(/\.axisLeft\(yScale\)/g));
```
y 軸 `g` 元素應有一個 `transform` 屬性,將 y 軸平移 `(60, 0)`
```js
assert(
$('g')
.eq(10)
.attr('transform')
.match(/translate\(60\s*?,\s*?0\)/g)
);
```
你應該調用(call) `yAxis`
```js
assert(code.match(/\.call\(\s*yAxis\s*\)/g));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d[0]))
.attr("cy",(d) => yScale(d[1]))
.attr("r", (d) => 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + "," + d[1]))
.attr("x", (d) => xScale(d[0] + 10))
.attr("y", (d) => yScale(d[1]))
const xAxis = d3.axisBottom(xScale);
// Add your code below this line
const yAxis = undefined;
// Add your code above this line
svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d[0]))
.attr("cy",(d) => yScale(d[1]))
.attr("r", (d) => 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + "," + d[1]))
.attr("x", (d) => xScale(d[0] + 10))
.attr("y", (d) => yScale(d[1]))
const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
svg.append("g")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis)
</script>
</body>
```

View File

@@ -0,0 +1,93 @@
---
id: 587d7fa7367417b2b2512bc8
title: 用 D3 添加 Class
challengeType: 6
forumTopicId: 301473
dashedName: add-classes-with-d3
---
# --description--
即使對小型 app 來說,在 HTML 元素中大量使用內聯樣式也十分難以管理。 給元素添加類,並使用 CSS 規則給類添加樣式會更加方便。 D3 中的 `attr()` 方法可以給元素添加任何 HTML 屬性,包括 class 名稱。
`attr()` 方法和 `style()` 的使用方法一樣。 它使用逗號分隔值,並且可以使用回調函數。 下面是給選中元素添加 `container` class 的例子:
```js
selection.attr("class", "container");
```
請注意,當你需要添加 class 時,`class` 參數保持不變,只有 `container` 參數會發生變化。
# --instructions--
`attr()` 方法添加到編輯器中的代碼中,並在 `div` 元素上添加一個 `bar` 類。
# --hints--
`div` 元素應該一個 `bar` class。
```js
assert($('div').attr('class') == 'bar');
```
應該使用 `attr()` 方法。
```js
assert(code.match(/\.attr/g));
```
# --seed--
## --seed-contents--
```html
<style>
.bar {
width: 25px;
height: 100px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<style>
.bar {
width: 25px;
height: 100px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
// Add your code below this line
.attr("class","bar");
// Add your code above this line
</script>
</body>
```

View File

@@ -0,0 +1,105 @@
---
id: 587d7fa6367417b2b2512bc2
title: 用 D3 給文檔添加元素
challengeType: 6
forumTopicId: 301474
dashedName: add-document-elements-with-d3
---
# --description--
D3 有多種方法可以用來在文檔中增加元素、修改元素。
`select()` 方法從文檔中選擇一個元素。 它接受你想要選擇的元素的名字作爲參數,並返回文檔中第一個與名字匹配的 HTML 節點。 以下是一個例子:
```js
const anchor = d3.select("a");
```
上面這個例子找到頁面上的第一個錨點標籤,將它作爲一個 HTML 節點保存在變量 `anchor` 中。 你可以使用其他方法進行選擇。 示例中的 `d3` 部分是對 D3 對象的引用,通過它訪問 D3 方法。
另外兩個有用的方法是 `append()``text()`
`append()` 方法接收你希望添加到文檔中的元素作爲參數。 它將 HTML 節點附加到選定項目,並返回該節點的句柄。
`text()` 方法可以設置所選節點的文本,也可以獲取當前文本。 要設置該值,請在方法的括號內傳遞一個字符串作爲參數。
下面的例子是選擇一個無序列表,添加列表項和添加文本:
```js
d3.select("ul")
.append("li")
.text("Very important item");
```
在 D3 中可以串聯多個方法,連續執行一系列操作。
# --instructions--
使用 `select` 方法選擇文檔中的 `body` 標籤。 然後給它 `append` 一個 `h1` 標籤,並給 `h1` 元素添加文本 `Learning D3`
# --hints--
`body` 元素應該包含一個 `h1` 元素。
```js
assert($('body').children('h1').length == 1);
```
`h1` 元素應包含文本 `Learning D3`
```js
assert($('h1').text() == 'Learning D3');
```
你應該能訪問 `d3` 對象。
```js
assert(code.match(/d3/g));
```
你應該使用 `select` 方法。
```js
assert(code.match(/\.select/g));
```
你應該使用 `append` 方法。
```js
assert(code.match(/\.append/g));
```
你應該使用 `text` 方法。
```js
assert(code.match(/\.text/g));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
d3.select("body")
.append("h1")
.text("Learning D3")
</script>
</body>
```

View File

@@ -0,0 +1,76 @@
---
id: 587d7fa7367417b2b2512bc6
title: 給元素添加內聯樣式
challengeType: 6
forumTopicId: 301475
dashedName: add-inline-styling-to-elements
---
# --description--
D3允許你使用 `style()` 方法在動態元素上添加內聯 CSS 樣式。
`style()` 方法以用逗號分隔的鍵值對作爲參數。 這裏是一個將選中文本的顏色設爲藍色的例子:
```js
selection.style("color","blue");
```
# --instructions--
`style()` 方法添加到編輯器中的代碼中,使所有顯示的文本都具有 `verdana``font-family`
# --hints--
`h2` 元素的 `font-family` 應爲 `verdana`
```js
assert($('h2').css('font-family') == 'verdana');
```
你應該使用 `style()` 方法。
```js
assert(code.match(/\.style/g));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
.text((d) => (d + " USD"))
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
.text((d) => (d + " USD"))
.style("font-family", "verdana")
</script>
</body>
```

View File

@@ -0,0 +1,153 @@
---
id: 587d7faa367417b2b2512bd2
title: 給 D3 元素添加標籤
challengeType: 6
forumTopicId: 301476
dashedName: add-labels-to-d3-elements
---
# --description--
D3 允許你使用 SVG 的 `text` 元素給圖形元素,如條形圖,添加標籤。
`rect` 元素類似,`text` 元素也需要 `x``y` 屬性來指定其放置在 SVG 畫布上的位置, 它也需要能夠獲取數據來顯示數據值。
D3 給了你很高的權限給圖形添加標籤。
# --instructions--
編輯器中的代碼已經將數據綁定到每個新的 `text` 元素。 首先,在 `svg` 中添加 `text` 節點。 然後,添加 `x``y` 座標屬性, 它們的計算方法應該和 `rect` 中計算方法相同,除了 `text``y` 值應該使標籤比條形圖的高 3 個單位。 最後,用 D3 的 `text()` 方法將標籤設置爲和數據點相等的值。
**注意:** 對於標籤比條形圖高的情況,應決定 `text``y` 值應比條形圖的 `y` 值大還是小 3 個單位。
# --hints--
第一個 `text` 元素應有一個值爲 `12` 的標籤,且 `y` 值爲 `61`
```js
assert($('text').eq(0).text() == '12' && $('text').eq(0).attr('y') == '61');
```
第二個 `text` 元素應有一個值爲 `31` 的標籤,且 `y` 值爲 `4`
```js
assert($('text').eq(1).text() == '31' && $('text').eq(1).attr('y') == '4');
```
第三個 `text` 元素應有一個值爲 `22` 的標籤,且 `y` 值爲 `31`
```js
assert($('text').eq(2).text() == '22' && $('text').eq(2).attr('y') == '31');
```
第四個 `text` 元素應有一個值爲 `17` 的標籤,且 `y` 值爲 `46`
```js
assert($('text').eq(3).text() == '17' && $('text').eq(3).attr('y') == '46');
```
第五個 `text` 元素應有一個值爲 `25` 的標籤,且 `y` 值爲 `22`
```js
assert($('text').eq(4).text() == '25' && $('text').eq(4).attr('y') == '22');
```
第六個 `text` 元素應有一個值爲 `18` 的標籤,且 `y` 值爲 `43`
```js
assert($('text').eq(5).text() == '18' && $('text').eq(5).attr('y') == '43');
```
第七個 `text` 元素應有一個值爲 `29` 的標籤,且 `y` 值爲 `10`
```js
assert($('text').eq(6).text() == '29' && $('text').eq(6).attr('y') == '10');
```
第八個 `text` 元素應有一個值爲 `14` 的標籤,其 `y` 值爲 `55`
```js
assert($('text').eq(7).text() == '14' && $('text').eq(7).attr('y') == '55');
```
第九個 `text` 元素應有一個值爲 `9` 的標籤,且 `y` 值爲 `70`
```js
assert($('text').eq(8).text() == '9' && $('text').eq(8).attr('y') == '70');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
// Add your code below this line
// Add your code above this line
</script>
<body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3)
.text((d) => d)
</script>
<body>
```

View File

@@ -0,0 +1,224 @@
---
id: 587d7fab367417b2b2512bd9
title: 向散點圖的 Circles 添加標籤
challengeType: 6
forumTopicId: 301477
dashedName: add-labels-to-scatter-plot-circles
---
# --description--
你可以爲散點圖中的點添加文本來創建標籤。
目標是顯示 `dataset` 中每個對象的第一個(`x`)和第二個(`y`)字段中通過逗號分隔的值。
`text` 節點需要 `x``y` 屬性來指定放置在 SVG 畫布中的位置。 在這個挑戰中,`y` 值(決定高度)可以用和 `circle``cy` 屬性相同的值, `x` 值可以比 `circle``cx` 值稍微大一些,這樣標籤纔可見, 並且被放置在散點的右邊。
# --instructions--
使用 `text` 元素標記散點圖上的每個點。 標籤的文本應該是用逗號和空格分隔的兩個值。 例如,第一個點的標籤是 `34, 78`。 設置 `x` 屬性,使其比 `circle` 上的 `cx` 屬性的值多 `5` 個單位。 設置 `y` 屬性的方式與 `circle` 上的 `cy` 值相同。
# --hints--
應該有 10 個 `text` 元素。
```js
assert($('text').length == 10);
```
第一個標籤的文本應爲 `34, 78` `x` 值應爲 `39``y` 應爲 `422`
```js
assert(
$('text').eq(0).text() == '34, 78' &&
$('text').eq(0).attr('x') == '39' &&
$('text').eq(0).attr('y') == '422'
);
```
第二個標籤的文本應爲 `109, 280``x` 值應爲`114``y` 值應爲 `220`
```js
assert(
$('text').eq(1).text() == '109, 280' &&
$('text').eq(1).attr('x') == '114' &&
$('text').eq(1).attr('y') == '220'
);
```
第三個標籤的文本應爲 `310, 120``x` 值應爲 `315``y` 值應爲 `380`
```js
assert(
$('text').eq(2).text() == '310, 120' &&
$('text').eq(2).attr('x') == '315' &&
$('text').eq(2).attr('y') == '380'
);
```
第四個標籤的文本應爲 `79, 411``x` 值應爲 `84``y` 值應爲 `89`
```js
assert(
$('text').eq(3).text() == '79, 411' &&
$('text').eq(3).attr('x') == '84' &&
$('text').eq(3).attr('y') == '89'
);
```
第五個標籤的文本應爲 `420, 220``x` 值應爲 `425``y` 值應爲 `280`
```js
assert(
$('text').eq(4).text() == '420, 220' &&
$('text').eq(4).attr('x') == '425' &&
$('text').eq(4).attr('y') == '280'
);
```
第六個標籤的文本應爲 `233, 145``x` 值應爲 `238``y` 值應爲 `355`
```js
assert(
$('text').eq(5).text() == '233, 145' &&
$('text').eq(5).attr('x') == '238' &&
$('text').eq(5).attr('y') == '355'
);
```
第七個標籤的文本應爲 `333, 96``x` 值應爲 `338``y` 值應爲 `404`
```js
assert(
$('text').eq(6).text() == '333, 96' &&
$('text').eq(6).attr('x') == '338' &&
$('text').eq(6).attr('y') == '404'
);
```
第八個標籤的文本應爲 `222, 333``x` 值應爲 `227``y` 值應爲 `167`
```js
assert(
$('text').eq(7).text() == '222, 333' &&
$('text').eq(7).attr('x') == '227' &&
$('text').eq(7).attr('y') == '167'
);
```
第九個標籤的文本應爲 `78, 320``x` 值應爲 `83``y` 值應爲 `180`
```js
assert(
$('text').eq(8).text() == '78, 320' &&
$('text').eq(8).attr('x') == '83' &&
$('text').eq(8).attr('y') == '180'
);
```
第十個標籤的文本應爲 `21, 123``x` 值應爲 `26``y` 值應爲 `377`
```js
assert(
$('text').eq(9).text() == '21, 123' &&
$('text').eq(9).attr('x') == '26' &&
$('text').eq(9).attr('y') == '377'
);
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d, i) => d[0])
.attr("cy", (d, i) => h - d[1])
.attr("r", 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d, i) => d[0])
.attr("cy", (d, i) => h - d[1])
.attr("r", 5);
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("x", (d) => d[0] + 5)
.attr("y", (d) => h - d[1])
.text((d) => (d[0] + ", " + d[1]))
</script>
</body>
```

View File

@@ -0,0 +1,123 @@
---
id: 587d7fa7367417b2b2512bc7
title: 根據數據更改樣式
challengeType: 6
forumTopicId: 301479
dashedName: change-styles-based-on-data
---
# --description--
D3 是關於可視化和展示數據的。 如果你想基於數據來改變元素的樣式, 你可以在 `style()` 方法中使用回調函數來修改不同元素的樣式。
例如,你想將值小於 20 的數據點設置爲藍色,其餘設置爲紅色。 你可以在 `style()` 方法中使用包含條件邏輯的回調函數。 回調函數以 `d` 作爲參數來表示一個數據點:
```js
selection.style("color", (d) => {
});
```
`style()` 方法不僅僅可以設置 `color`——它也適用於其他 CSS 屬性。
# --instructions--
在編輯器中添加 `style()` 方法,根據條件設置 `h2` 元素的 `color` 屬性。 寫一個回調函數,如果數據值小於 20則返回紅色red否則返回綠色green
**注意:** 你可以使用 if-else 邏輯或者三元操作符。
# --hints--
第一個 `h2``color` 應該爲 red。
```js
assert($('h2').eq(0).css('color') == 'rgb(255, 0, 0)');
```
第二個 `h2``color` 應該爲 green。
```js
assert($('h2').eq(1).css('color') == 'rgb(0, 128, 0)');
```
第三個 `h2``color` 應該爲 green。
```js
assert($('h2').eq(2).css('color') == 'rgb(0, 128, 0)');
```
第四個 `h2``color` 應該爲 red。
```js
assert($('h2').eq(3).css('color') == 'rgb(255, 0, 0)');
```
第五個 `h2``color` 應該爲 green。
```js
assert($('h2').eq(4).css('color') == 'rgb(0, 128, 0)');
```
第六個 `h2``color` 應該爲 red。
```js
assert($('h2').eq(5).css('color') == 'rgb(255, 0, 0)');
```
第七個 `h2``color` 應該爲 green。
```js
assert($('h2').eq(6).css('color') == 'rgb(0, 128, 0)');
```
第八個 `h2``color` 應該爲 red。
```js
assert($('h2').eq(7).css('color') == 'rgb(255, 0, 0)');
```
第九個 `h2``color` 應該爲 red。
```js
assert($('h2').eq(8).css('color') == 'rgb(255, 0, 0)');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
.text((d) => (d + " USD"))
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
.text((d) => (d + " USD"))
.style("color", (d) => d < 20 ? "red" : "green")
</script>
</body>
```

View File

@@ -0,0 +1,88 @@
---
id: 587d7fa9367417b2b2512bd1
title: 更改 SVG 元素的顏色
challengeType: 6
forumTopicId: 301480
dashedName: change-the-color-of-an-svg-element
---
# --description--
所有條形圖的位置都是正確的,但是它們都是一樣的黑色。 SVG 可以改變條形圖的顏色。
在 SVG 中, `rect` 圖形用 `fill` 屬性着色。 它支持十六進制代碼、顏色名稱、rgb 值以及更復雜的選項,比如漸變和透明。
# --instructions--
添加 `attr()` 方法,將所有條形圖的 `fill` 設置爲海軍藍。
# --hints--
所有條形圖的 `fill` 顏色都應該是 navy海軍藍
```js
assert($('rect').css('fill') == 'rgb(0, 0, 128)');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d)
.attr("fill", "navy");
</script>
</body>
```

View File

@@ -0,0 +1,161 @@
---
id: 587d7fa8367417b2b2512bca
title: 更改條形圖的顯示方式
challengeType: 6
forumTopicId: 301481
dashedName: change-the-presentation-of-a-bar-chart
---
# --description--
上一個挑戰創建了一個條形圖,可以通過下面的格式調整來美化它:
1) 通過在 CSS 中爲 `bar` class 添加 margin 屬性,給每一個條形圖之間添加空格,把它們分開。
2) 通過給每個值乘以一個數來縮放高度,增加高度,以更好地顯示值的差異。
# --instructions--
首先,在 `style` 標籤中給 `bar` class 增加值爲 `2px``margin`。 然後,更改 `style()` 方法中的回調函數,使其返回原始數據值的 `10` 倍(加上 `px`)。
**注意:**每一個數值點乘以*相同的*常量值,僅僅改變比例。 這就像放大,它不會改變底層數據的含義。
# --hints--
第一個 `div` 應有一個 `120` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(0).css('height') == '120px' &&
$('div').eq(0).css('margin-right') == '2px'
);
```
第二個 `div` 應有一個 `310` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(1).css('height') == '310px' &&
$('div').eq(1).css('margin-right') == '2px'
);
```
第三個 `div` 應有一個 `220` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(2).css('height') == '220px' &&
$('div').eq(2).css('margin-right') == '2px'
);
```
第四個 `div` 應有一個 `170` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(3).css('height') == '170px' &&
$('div').eq(3).css('margin-right') == '2px'
);
```
第五個 `div` 應有一個 `250` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(4).css('height') == '250px' &&
$('div').eq(4).css('margin-right') == '2px'
);
```
第六個 `div` 應有一個 `180` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(5).css('height') == '180px' &&
$('div').eq(5).css('margin-right') == '2px'
);
```
第七個 `div` 應有一個 `290` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(6).css('height') == '290px' &&
$('div').eq(6).css('margin-right') == '2px'
);
```
第八個 `div` 應有一個 `140` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(7).css('height') == '140px' &&
$('div').eq(7).css('margin-right') == '2px'
);
```
第九個 `div` 應有一個 `90` 像素的 `height` 和一個 `2` 像素的 `margin`
```js
assert(
$('div').eq(8).css('height') == '90px' &&
$('div').eq(8).css('margin-right') == '2px'
);
```
# --seed--
## --seed-contents--
```html
<style>
.bar {
width: 25px;
height: 100px;
/* Add your code below this line */
/* Add your code above this line */
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", (d) => (d + "px")) // Change this line
</script>
</body>
```
# --solutions--
```html
<style>
.bar {
width: 25px;
height: 100px;
margin: 2px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style("height", (d) => (d * 10 + "px"))
</script>
</body>
```

View File

@@ -0,0 +1,110 @@
---
id: 587d7fa8367417b2b2512bcd
title: 爲集合中的每個數據點創建一個數據條
challengeType: 6
forumTopicId: 301482
dashedName: create-a-bar-for-each-data-point-in-the-set
---
# --description--
上個挑戰在 `svg` 中只添加了一個矩形來表示數據條。 接下來你將結合到目前爲止所學的關於 `data()``enter()` 和 SVG 圖形的知識,爲 `dataset` 中的每一個數據點創建並且添加一個矩形。
之前的挑戰展示瞭如何爲 `dataset` 中的每個對象創建並添加一個 `div`
```js
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
```
操作 `rect` 元素和 `divs` 有一些不同。 `rects` 必須添加在 `svg` 元素內,而不能直接添加在 `body` 內。 同時,你需要告訴 D3 將 `rect` 放在 `svg` 區域的哪個位置。 條形的放置會在下一個挑戰中講到。
# --instructions--
`data()``enter()``append()` 方法爲 `dataset` 中的每一個對象創建並添加一個 `rect` 。 每個數據條都將直接顯示在上一個數據條的上面,這一點將在下一個挑戰中實現。
# --hints--
應該包含 9 個 `rect` 元素。
```js
assert($('rect').length == 9);
```
應該使用 `data()` 方法。
```js
assert(code.match(/\.data/g));
```
應該使用 `enter()` 方法。
```js
assert(code.match(/\.enter/g));
```
應該使用 `append()` 方法。
```js
assert(code.match(/\.append/g));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
// Add your code below this line
// Add your code above this line
.attr("x", 0)
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
```

View File

@@ -0,0 +1,88 @@
---
id: 587d7fab367417b2b2512bda
title: 用 D3 創建線性比例
challengeType: 6
forumTopicId: 301483
dashedName: create-a-linear-scale-with-d3
---
# --description--
條形圖和散點圖都直接在 SVG 畫布上繪製數據。 但是,如果一組的高或者其中一個數據點比 SVG 的高或寬更大,它將跑到 SVG 區域外。
D3 中,比例尺可幫助佈局數據。 `scales` 是函數,它告訴程序如何將一組原始數據點映射到 SVG 畫布上。
例如,假設你有一個 100x500 大小的 SVG 畫布你想爲許多國家繪製國內生產總值GDP的圖表。 這組數據將在十億美元或萬億美元的範圍內。 你給 D3 提供一種縮放方法,告訴它如何將大的 GDP 值放置在 100x500 大小的區域。
你不太可能按數據原本的大小來繪製圖表。 在繪製之前,將整個數據集縮放,讓 `x``y` 值適合畫布的寬高。
D3 有幾種縮放類型。 對於線性縮放(通常使用於定量數據),使用 D3 的 `scaleLinear()` 方法:
```js
const scale = d3.scaleLinear()
```
默認情況下比例尺使用一對一關係identity relationship。 輸入的值和輸出的值相同。 後面的挑戰將涉及如何改變默認比例。
# --instructions--
更改 `scale` 變量,以創建線性比例。 然後將 `output` 變量設置爲 scale 函數,調用函數時傳入參數 `50`
# --hints--
`h2` 的文本應爲 `50`
```js
assert($('h2').text() == '50');
```
應使用 `scaleLinear()` 方法。
```js
assert(code.match(/\.scaleLinear/g));
```
`output` 變量應調用 `scale`,傳入參數 `50`
```js
assert(output == 50 && code.match(/scale\(\s*?50\s*?\)/g));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
// Add your code below this line
const scale = undefined; // Create the scale here
const output = scale(); // Call scale with an argument here
// Add your code above this line
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const scale = d3.scaleLinear();
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
```

View File

@@ -0,0 +1,103 @@
---
id: 587d7fab367417b2b2512bd7
title: 使用 SVG Circles 創建散點圖
challengeType: 6
forumTopicId: 301484
dashedName: create-a-scatterplot-with-svg-circles
---
# --description--
散點圖是另一種形式的可視化。 它用圓圈來映射數據點,每個數據點有兩個值。 這兩個值和 `x``y` 軸相關聯,在可視化中用來給圓圈定位。
SVG 用 `circle` 標籤來創建圓形。 它和之前用來構建條形圖的 `rect` 非常相像。
# --instructions--
使用 `data()``enter()``append()` 方法將 `dataset` 和新添加到 SVG 畫布上的 `circle` 元素綁定起來。
**注意:** 圓形並不可見,因爲我們還沒有設置它們的屬性。 我們會在下一個挑戰中設置屬性。
# --hints--
應該有 10 個 `circle` 元素。
```js
assert($('circle').length == 10);
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
</script>
</body>
```

View File

@@ -0,0 +1,103 @@
---
id: 587d7fa8367417b2b2512bcc
title: 用 SVG 顯示形狀
challengeType: 6
forumTopicId: 301485
dashedName: display-shapes-with-svg
---
# --description--
上個挑戰用給定的寬和高創建了一個 `svg` 元素,因爲在它的 `style` 標籤中有 `background-color`,所以它是可見的。 這一段代碼爲給定的寬和高騰出空間。
下一步是在 `svg` 區域中創建圖形。 SVG 支持多種圖形,比如矩形和圓形, 並用它們來顯示數據。 例如,在條形圖中一個矩形(`<rect>`SVG 圖形可以創建一個組。
當把圖形放入 `svg` 區域中時,你可以用 `x``y` 座標來指定它的位置。 起始點 (0,0) 是在左上角。 `x` 正值將圖形右移,`y` 正值將圖形從原點下移
若要把一個圖形放在上個挑戰的 500x 100`svg` 中心,可將 `x` 座標設置爲 250`y` 座標設置爲 50。
SVG 的 `rect` 有四個屬性。 `x``y` 座標指定圖形放在 `svg` 區域的位置, `height``width` 指定圖形大小。
# --instructions--
`append()``svg` 添加一個 `width``25``height``100``rect` 形狀。 同時,將 `rect``x``y` 都設置爲 `0`
# --hints--
文檔應該有 1 個 `rect` 元素。
```js
assert($('rect').length == 1);
```
`rect` 元素的 `width` 應爲 `25`
```js
assert($('rect').attr('width') == '25');
```
`rect` 元素的 `height` 應爲 `100`
```js
assert($('rect').attr('height') == '100');
```
`rect` 元素的 `x` 值應爲 `0`
```js
assert($('rect').attr('x') == '0');
```
`rect` 元素的 `y` 值應爲 `0`
```js
assert($('rect').attr('y') == '0');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
.append("rect")
.attr("width", 25)
.attr("height", 100)
.attr("x", 0)
.attr("y", 0);
</script>
</body>
```

View File

@@ -0,0 +1,145 @@
---
id: 587d7fa9367417b2b2512bcf
title: 動態更改每個條形的高度
challengeType: 6
forumTopicId: 301486
dashedName: dynamically-change-the-height-of-each-bar
---
# --description--
和動態設置 `x` 值一樣,也可以把每個條形的高度設置成數組中數據點的值。
```js
selection.attr("property", (d, i) => {
})
```
`d` 是數據點值,`i` 是數組中數據點的索引。
# --instructions--
改變 `height` 屬性的回調函數,讓它返回數據值乘以 3 的值。
**注意:** 記住,把所有數據點乘以相同的常數來對數據進行縮放(就像放大), 這有利於看清例子中條形數值之間的差異。
# --hints--
第一個 `rect``height` 應爲 `36`
```js
assert($('rect').eq(0).attr('height') == '36');
```
第二個 `rect``height` 應爲 `93`
```js
assert($('rect').eq(1).attr('height') == '93');
```
第三個 `rect``height` 應爲 `66`
```js
assert($('rect').eq(2).attr('height') == '66');
```
第四個 `rect``height` 應爲 `51`
```js
assert($('rect').eq(3).attr('height') == '51');
```
第五個 `rect``height` 應爲 `75`
```js
assert($('rect').eq(4).attr('height') == '75');
```
第六個 `rect``height` 應爲 `54`
```js
assert($('rect').eq(5).attr('height') == '54');
```
第七個 `rect``height` 應爲 `87`
```js
assert($('rect').eq(6).attr('height') == '87');
```
第八個 `rect``height` 應爲 `42`
```js
assert($('rect').eq(7).attr('height') == '42');
```
第九個 `rect``height` 應爲 `27`
```js
assert($('rect').eq(8).attr('height') == '27');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", 0)
.attr("width", 25)
.attr("height", (d, i) => {
// Add your code below this line
// Add your code above this line
});
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", 0)
.attr("width", 25)
.attr("height", (d, i) => {
return d * 3
});
</script>
</body>
```

View File

@@ -0,0 +1,151 @@
---
id: 587d7fa9367417b2b2512bce
title: 動態設置每個 Bar 的座標
challengeType: 6
forumTopicId: 301487
dashedName: dynamically-set-the-coordinates-for-each-bar
---
# --description--
上個挑戰在 `svg` 元素中爲 `dataset` 的每一個數據點創建並且添加了一個矩形,其中一個矩形表示一組, 但是它們相互重疊。
矩形的位置是由 `x``y` 屬性決定的。 它們告訴 D3 在 `svg` 區域的哪個位置開始繪製圖形。 上個挑戰將它們都設置爲 0因此所有條形都在左上角。
對於條形圖,所有條形應該處於相同的垂直線上,也就是說所有條形的 `y` 值相同(爲 0 但是 `x` 值需要隨着增添新的條形而變化。 注意 `x` 值越大,圖形就越靠近右邊。 所以當遍歷 `dataset` 中的數組元素時,`x` 的值應該遞增。
D3 的 `attr()` 方法可接收一個回調函數來動態設置屬性。 這個回調函數有兩個參數,一個是數據點本身(通常是 `d`),另一個是該數據點在數組中的下標, 這個參數是可選的。 下面是其格式:
```js
selection.attr("property", (d, i) => {
})
```
值得注意的是,你不需要寫 `for` 循環或者用 `forEach()` 迭代數據集中的對象。 `data()` 方法會解析數據集,任何鏈接在 `data()` 後面的方法都會爲數據集中的每個對象運行一次。
# --instructions--
改變 `x` 屬性的回調函數,讓它返回下標乘以 30 的值。
**注意:**每組的寬爲 25所以每次 `x` 增加 30可在每組之間留出一些空隙。 在這個例子中任何比 25 大的數也同樣適用。
# --hints--
第一個 `rect``x` 值應該爲 `0`
```js
assert($('rect').eq(0).attr('x') == '0');
```
第二個 `rect``x` 值應該爲 `30`
```js
assert($('rect').eq(1).attr('x') == '30');
```
第三個 `rect``x` 值應該爲 `60`
```js
assert($('rect').eq(2).attr('x') == '60');
```
第四個 `rect``x` 值應該爲 `90`
```js
assert($('rect').eq(3).attr('x') == '90');
```
第五個 `rect``x` 值應該爲 `120`
```js
assert($('rect').eq(4).attr('x') == '120');
```
第六個 `rect``x` 值應該爲 `150`
```js
assert($('rect').eq(5).attr('x') == '150');
```
第七個 `rect``x` 值應該爲 `180`
```js
assert($('rect').eq(6).attr('x') == '180');
```
第八個 `rect``x` 值應該爲 `210`
```js
assert($('rect').eq(7).attr('x') == '210');
```
第九個 `rect``x` 值應該爲 `240`
```js
assert($('rect').eq(8).attr('x') == '240');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => {
// Add your code below this line
// Add your code above this line
})
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => {
return i * 30
})
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
```

View File

@@ -0,0 +1,143 @@
---
id: 587d7fa9367417b2b2512bd0
title: 反轉 SVG 元素
challengeType: 6
forumTopicId: 301488
dashedName: invert-svg-elements
---
# --description--
你可能已經注意到了常見的條形圖像是把這個翻轉或者顛倒過來。 這是因爲 SVG 的 (x, y) 座標有些特別。
在 SVG 中,座標軸的原點在左上角。 `x` 座標爲 0 將圖形放在 SVG 區域的左邊緣, `y` 座標爲 0 將圖形放在 SVG 區域的上邊緣。 `x` 值增大矩形將向右移動, `y` 值增大矩形將向下移動。
爲了使條形圖向上,需要改變 `y` 座標計算的方式。 這需要計算條形的高度和 SVG 區域的總高度。
SVG 區域的高度爲 100。 如果在集合中一個數據點的值爲 0那麼條形將從 SVG 區域的最底端開始(而不是頂端)。 爲此,`y` 座標的值應爲 100。 如果數據點的值爲 1你將從 `y` 座標爲 100 開始來將這個條形設置在底端, 然後需要考慮該條形的高度爲 1所以最終的 `y` 座標將是 99。
`y` 座標爲 `y = heightOfSVG - heightOfBar` 會將條形圖向上放置。
# --instructions--
改變 `y` 屬性的回調函數,讓條形圖向上放置。 `height` 的值是 3 倍 `d` 的值。
**注意:**通常,關係是 `y = h - m * d`,其中 `m` 是縮放數據點的常數。
# --hints--
第一個 `rect``y` 值應該爲 `64`
```js
assert($('rect').eq(0).attr('y') == h - dataset[0] * 3);
```
第二個 `rect``y` 值應該爲 `7`
```js
assert($('rect').eq(1).attr('y') == h - dataset[1] * 3);
```
第三個 `rect``y` 值應該爲 `34`
```js
assert($('rect').eq(2).attr('y') == h - dataset[2] * 3);
```
第四個 `rect``y` 值應該爲 `49`
```js
assert($('rect').eq(3).attr('y') == h - dataset[3] * 3);
```
第五個 `rect``y` 值應該爲 `25`
```js
assert($('rect').eq(4).attr('y') == h - dataset[4] * 3);
```
第六個 `rect``y` 值應該爲 `46`
```js
assert($('rect').eq(5).attr('y') == h - dataset[5] * 3);
```
第七個 `rect``y` 值應該爲 `13`
```js
assert($('rect').eq(6).attr('y') == h - dataset[6] * 3);
```
第八個 `rect``y` 值應該爲 `58`
```js
assert($('rect').eq(7).attr('y') == h - dataset[7] * 3);
```
第九個 `rect``y` 值應該爲 `73`
```js
assert($('rect').eq(8).attr('y') == h - dataset[8] * 3);
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => {
// Add your code below this line
// Add your code above this line
})
.attr("width", 25)
.attr("height", (d, i) => 3 * d);
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => 3 * d);
</script>
</body>
```

View File

@@ -0,0 +1,93 @@
---
id: 587d7fa8367417b2b2512bcb
title: 瞭解 D3 中的 SVG
challengeType: 6
forumTopicId: 301489
dashedName: learn-about-svg-in-d3
---
# --description--
<dfn>SVG</dfn><dfn>Scalable Vector Graphics</dfn> 的縮寫。
“scalable” 的意思是如果放大或縮小一個對象,它不會像素化。 不管是在小的移動手機屏幕上還是在大的電視顯示器上,它都會隨着顯示系統縮放。
SVG 用於製作常見的幾何圖形。 由於 D3 將數據映射成可視化表達,它用 SVG 來創建可視化的圖形。 網頁上的 SVG 圖形必須在 HTML 的 `svg` 標籤中。
當使用相對單位(例如 `vh``vw` 或者百分比CSS 是可伸縮的。 但是在實現數據可視化的時候 SVG 更加的靈活。
# --instructions--
`append()``body` 加一個 `svg` 節點。 使用 `attr()``style()` 方法給它設置一個 `width` 屬性和一個 `height` 屬性,並分別將它們設置爲給定的常量 `w` 和給定的常量 `h`。 你可以在輸出中看見它,因爲在 `style` 標籤中它的 `background-color` 設置爲 pink。
**注意:**width 和 height `attr()` 沒有單位。 它們是用來定義縮放的——但無論怎麼縮放,元素的寬高比永遠是 5:1 。
# --hints--
文檔應該有 1 個 `svg` 元素。
```js
assert($('svg').length == 1);
```
`svg` 元素應有一個 `width` 屬性,值爲 `500`,或者在樣式中 width 值爲 `500px`
```js
assert($('svg').attr('width') == '500' || $('svg').css('width') == '500px');
```
`svg` 元素應有一個 `height` 屬性,值爲 `100`,或者在樣式中 height 值爲 `100px`
```js
assert($('svg').attr('height') == '100' || $('svg').css('height') == '100px');
```
# --seed--
## --seed-contents--
```html
<style>
svg {
background-color: pink;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<style>
svg {
background-color: pink;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h)
</script>
</body>
```

View File

@@ -0,0 +1,82 @@
---
id: 587d7fa6367417b2b2512bc3
title: 用 D3 選擇一組元素
challengeType: 6
forumTopicId: 301490
dashedName: select-a-group-of-elements-with-d3
---
# --description--
`selectAll()` 方法選擇一組元素。 它以 HTML 節點數組的形式返回該文本中所有匹配所輸入字符串的對象。 以下是一個選擇文本中所有錨標籤的例子:
```js
const anchors = d3.selectAll("a");
```
`select()` 方法一樣,`selectAll()` 也支持鏈式調用,你可以在它之後調用其他方法。
# --instructions--
選擇所有的 `li` 標籤,通過 `.text()` 方法將它們的文本改爲 `list item`
# --hints--
頁面上應該有 3 個 `li` 元素,每個元素的文本內容應爲 `list item`。 大寫和間距應完全匹配。
```js
assert(
$('li')
.text()
.match(/list item/g).length == 3
);
```
應該能訪問 `d3` 的對象。
```js
assert(code.match(/d3/g));
```
應該使用 `selectAll` 方法。
```js
assert(code.match(/\.selectAll/g));
```
# --seed--
## --seed-contents--
```html
<body>
<ul>
<li>Example</li>
<li>Example</li>
<li>Example</li>
</ul>
<script>
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<ul>
<li>Example</li>
<li>Example</li>
<li>Example</li>
</ul>
<script>
d3.selectAll("li")
.text("list item")
</script>
</body>
```

View File

@@ -0,0 +1,106 @@
---
id: 587d7fac367417b2b2512bdb
title: 按比例設置域和範圍
challengeType: 6
forumTopicId: 301491
dashedName: set-a-domain-and-a-range-on-a-scale
---
# --description--
默認情況下比例尺使用一對一關係identity relationship 即輸入值直接映射爲輸出值。 但是比例尺可以更靈活更有趣。
假設有一個數據集範圍爲 50 到 480 這是縮放的輸入信息,也被稱爲<dfn></dfn>
你想沿着 `x` 軸將這些點映射到 SVG 畫布上,位置介於 10 個單位到 500 個單位之間。 這是輸出信息,也被稱爲<dfn>範圍</dfn>
`domain()``range()` 方法設置比例尺的值, 它們都接受一個至少有兩個元素的數組作爲參數。 下面是一個例子:
```js
scale.domain([50, 480]);
scale.range([10, 500]);
scale(50)
scale(480)
scale(325)
scale(750)
d3.scaleLinear()
```
按順序,將在控制檯中顯示以下值:`10``500``323.37``807.67`
注意,比例尺使用了域和範圍之間的線性關係來找出給定數字的輸出值。 域中的最小值50映射爲範圍中的最小值10
# --instructions--
創建一個比例尺,將它的域設置爲 `[250, 500]`,範圍設置爲 `[10, 150]`
**注意:**你可以將 `domain()``range()` 方法串聯在 `scale` 變量後。
# --hints--
應使用 `domain()` 方法。
```js
assert(code.match(/\.domain/g));
```
`scale``domain()` 應爲 `[250, 500]`
```js
assert(JSON.stringify(scale.domain()) == JSON.stringify([250, 500]));
```
應使用 `range()` 方法。
```js
assert(code.match(/\.range/g));
```
`scale``range()` 應爲 `[10, 150]`
```js
assert(JSON.stringify(scale.range()) == JSON.stringify([10, 150]));
```
`h2` 的文本應爲 `-102`
```js
assert($('h2').text() == '-102');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
// Add your code below this line
const scale = d3.scaleLinear();
// Add your code above this line
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const scale = d3.scaleLinear();
scale.domain([250, 500])
scale.range([10, 150])
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
```

View File

@@ -0,0 +1,110 @@
---
id: 587d7faa367417b2b2512bd3
title: 給 D3 標籤添加樣式
challengeType: 6
forumTopicId: 301492
dashedName: style-d3-labels
---
# --description--
D3 可以將樣式添加到條形標籤中。 `fill` 屬性爲 `text` 節點設置文本顏色, `style()` 方法設置其它樣式的 CSS 規則,例如 `font-family``font-size`
# --instructions--
`text` 元素的 `font-size` 設置爲 `25px`文本顏色設置爲紅色red
# --hints--
所有標籤的 `fill` 顏色應該是 red。
```js
assert($('text').css('fill') == 'rgb(255, 0, 0)');
```
所有標籤的 `font-size` 應爲 `25` 像素。
```js
assert($('text').css('font-size') == '25px');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3)
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
const w = 500;
const h = 100;
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - 3 * d)
.attr("width", 25)
.attr("height", (d, i) => d * 3)
.attr("fill", "navy");
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => d)
.attr("x", (d, i) => i * 30)
.attr("y", (d, i) => h - (3 * d) - 3)
.style("font-size", 25)
.attr("fill", "red")
</script>
</body>
```

View File

@@ -0,0 +1,137 @@
---
id: 587d7fa8367417b2b2512bc9
title: 動態更新元素的高度
challengeType: 6
forumTopicId: 301493
dashedName: update-the-height-of-an-element-dynamically
---
# --description--
之前的挑戰包括如何從數組中顯示數據和如何添加 CSS 類。 將這些課程的內容結合起來,你就能創建出一個簡單的條形圖, 只需兩步:
1) 爲每一個數組中的數據點都創建一個 `div`
2) 爲每個 `div` 動態分配高度值,在 `style()` 方法中使用回調函數將高度值設置爲數據大小
回想使用回調函數設置樣式的格式:
```js
selection.style("cssProperty", (d) => d)
```
# --instructions--
`style()` 方法添加到編輯器中的代碼中,以設置每個元素的 `height` 屬性。 使用回調函數返回數據點的值,加上字符串 `px`
# --hints--
第一個 `div``height` 值應爲 `12` 像素。
```js
assert($('div').eq(0)[0].style.height === '12px');
```
第二個 `div``height` 值應爲 `31` 像素。
```js
assert($('div').eq(1)[0].style.height === '31px');
```
第三個 `div``height` 值應爲 `22` 像素。
```js
assert($('div').eq(2)[0].style.height === '22px');
```
第四個 `div``height` 值應爲 `17` 像素。
```js
assert($('div').eq(3)[0].style.height === '17px');
```
第五個 `div``height` 值應爲 `25` 像素。
```js
assert($('div').eq(4)[0].style.height === '25px');
```
第六個 `div``height` 值應爲 `18` 像素。
```js
assert($('div').eq(5)[0].style.height === '18px');
```
第七個 `div``height` 值應爲 `29` 像素。
```js
assert($('div').eq(6)[0].style.height === '29px');
```
第八個 `div``height` 值應爲 `14` 像素。
```js
assert($('div').eq(7)[0].style.height === '14px');
```
第九個 `div``height` 值應爲 `9` 像素。
```js
assert($('div').eq(8)[0].style.height === '9px');
```
# --seed--
## --seed-contents--
```html
<style>
.bar {
width: 25px;
height: 100px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<style>
.bar {
width: 25px;
height: 100px;
display: inline-block;
background-color: blue;
}
</style>
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
.attr("class", "bar")
.style('height', d => `${d}px`)
</script>
</body>
```

View File

@@ -0,0 +1,347 @@
---
id: 587d7fac367417b2b2512bde
title: 使用預定義的比例放置元素
challengeType: 6
forumTopicId: 301494
dashedName: use-a-pre-defined-scale-to-place-elements
---
# --description--
當比例尺建立好後,是時候重新映射散點圖了。 比例尺就像操作函數一樣,將 `x``y` 的原數據值變爲適合並可在 SVG 畫布上正確渲染的值。 它們使數據在屏幕的佈局區域內部。
用比例尺函數爲 SVG 圖形設置座標屬性值。 這包括 `rect` 或者 `text` 元素的 `x``y` 屬性,或者 `circles``cx``cy`。 以下是一個例子:
```js
shape
.attr("x", (d) => xScale(d[0]))
```
比例尺設置圖形座標屬性來將數據點放置在 SVG 畫布上。 當你顯示實際數據值時,不用使用比例尺,例如,在提示框或標籤中的 `text()` 方法。
# --instructions--
使用 `xScale``yScale``circle``text` 圖形放置在 SVG 畫布上。 對於 `circles`,使用比例尺設置 `cx``cy` 屬性, 半徑爲 `5` 個單位。
對於 `text` 元素,使用比例尺設置 `x``y` 屬性。 標籤應該標註在點的右邊, 爲此,在將 `x` 數據值傳遞給 `xScale` 之前,要給它加上 `10` 個單位。
# --hints--
應該有 10 個 `circle` 元素。
```js
assert($('circle').length == 10);
```
在使用比例尺後,第一個 `circle` 元素的 `cx` 值應該大約爲 `91``cy` 值應該大約爲 `368`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(0).attr('cx')) == '91' &&
Math.round($('circle').eq(0).attr('cy')) == '368' &&
$('circle').eq(0).attr('r') == '5'
);
```
在使用比例尺後,第二個 `circle` 元素的 `cx` 值應該大約爲 `159``cy` 值應該大約爲 `181`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(1).attr('cx')) == '159' &&
Math.round($('circle').eq(1).attr('cy')) == '181' &&
$('circle').eq(1).attr('r') == '5'
);
```
在使用比例尺後,第三個 `circle` 元素的 `cx` 值應該大約爲 `340``cy` 值應該大約爲 `329`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(2).attr('cx')) == '340' &&
Math.round($('circle').eq(2).attr('cy')) == '329' &&
$('circle').eq(2).attr('r') == '5'
);
```
在使用比例尺後,第四個 `circle` 元素的 `cx` 值應該大約爲 `131``cy` 值應該大約爲 `60`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(3).attr('cx')) == '131' &&
Math.round($('circle').eq(3).attr('cy')) == '60' &&
$('circle').eq(3).attr('r') == '5'
);
```
在使用比例尺後,第五個 `circle` 元素的 `cx` 值應該大約爲 `440``cy` 值應該大約爲 `237`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(4).attr('cx')) == '440' &&
Math.round($('circle').eq(4).attr('cy')) == '237' &&
$('circle').eq(4).attr('r') == '5'
);
```
在使用比例尺後,第六個 `circle` 元素的 `cx` 值應該大約爲 `271``cy` 值應該大約爲 `306`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(5).attr('cx')) == '271' &&
Math.round($('circle').eq(5).attr('cy')) == '306' &&
$('circle').eq(5).attr('r') == '5'
);
```
在使用比例尺後,第七個 `circle` 元素的 `cx` 值應該大約爲 `361``cy` 值應該大約爲 `351`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(6).attr('cx')) == '361' &&
Math.round($('circle').eq(6).attr('cy')) == '351' &&
$('circle').eq(6).attr('r') == '5'
);
```
在使用比例尺後,第八個 `circle` 元素的 `cx` 值應該大約爲 `261``cy` 值應該大約爲 `132`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(7).attr('cx')) == '261' &&
Math.round($('circle').eq(7).attr('cy')) == '132' &&
$('circle').eq(7).attr('r') == '5'
);
```
在使用比例尺後,第九個 `circle` 元素的 `cx` 值應該大約爲 `131``cy` 值應該大約爲 `144`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(8).attr('cx')) == '131' &&
Math.round($('circle').eq(8).attr('cy')) == '144' &&
$('circle').eq(8).attr('r') == '5'
);
```
在使用比例尺後,第十個 `circle` 元素的 `cx` 值應該大約爲 `79``cy` 值應該大約爲 `326`。 它的 `r` 值應爲 `5`
```js
assert(
Math.round($('circle').eq(9).attr('cx')) == '79' &&
Math.round($('circle').eq(9).attr('cy')) == '326' &&
$('circle').eq(9).attr('r') == '5'
);
```
應該有 10 個 `text` 元素。
```js
assert($('text').length == 10);
```
在使用比例尺後,第一個標籤的 `x` 值應該大約爲 `100``y` 值應該大約爲 `368`
```js
assert(
Math.round($('text').eq(0).attr('x')) == '100' &&
Math.round($('text').eq(0).attr('y')) == '368'
);
```
在使用比例尺後,第二個標籤的 `x` 值應該大約爲 `168``y` 值應該大約爲 `181`
```js
assert(
Math.round($('text').eq(1).attr('x')) == '168' &&
Math.round($('text').eq(1).attr('y')) == '181'
);
```
在使用比例尺後,第三個標籤的 `x` 值應該大約爲 `350``y` 值應該大約爲 `329`
```js
assert(
Math.round($('text').eq(2).attr('x')) == '350' &&
Math.round($('text').eq(2).attr('y')) == '329'
);
```
在使用比例尺後,第四個標籤的 `x` 值應該大約爲 `141``y` 值應該大約爲 `60`
```js
assert(
Math.round($('text').eq(3).attr('x')) == '141' &&
Math.round($('text').eq(3).attr('y')) == '60'
);
```
在使用比例尺後,第五個標籤的 `x` 值應該大約爲 `449``y` 值應該大約爲 `237`
```js
assert(
Math.round($('text').eq(4).attr('x')) == '449' &&
Math.round($('text').eq(4).attr('y')) == '237'
);
```
在使用比例尺後,第六個標籤的 `x` 值應該大約爲 `280``y` 值應該大約爲 `306`
```js
assert(
Math.round($('text').eq(5).attr('x')) == '280' &&
Math.round($('text').eq(5).attr('y')) == '306'
);
```
在使用比例尺後,第七個標籤的 `x` 值應該大約爲 `370``y` 值應該大約爲 `351`
```js
assert(
Math.round($('text').eq(6).attr('x')) == '370' &&
Math.round($('text').eq(6).attr('y')) == '351'
);
```
在使用比例尺後,第八個標籤的 `x` 值應該大約爲 `270``y` 值應該大約爲 `132`
```js
assert(
Math.round($('text').eq(7).attr('x')) == '270' &&
Math.round($('text').eq(7).attr('y')) == '132'
);
```
在使用比例尺後,第九個標籤的 `x` 值應該大約爲 `140``y` 值應該大約爲 `144`
```js
assert(
Math.round($('text').eq(8).attr('x')) == '140' &&
Math.round($('text').eq(8).attr('y')) == '144'
);
```
在使用比例尺後,第十個標籤的 `x` 值應該大約爲 `88``y` 值應該大約爲 `326`
```js
assert(
Math.round($('text').eq(9).attr('x')) == '88' &&
Math.round($('text').eq(9).attr('y')) == '326'
);
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
// Add your code below this line
// Add your code above this line
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + ", "
+ d[1]))
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 60;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d[0]))
.attr("cy", (d) => yScale(d[1]))
.attr("r", 5)
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + ", "
+ d[1]))
.attr("x", (d) => xScale(d[0] + 10))
.attr("y", (d) => yScale(d[1]))
</script>
</body>
```

View File

@@ -0,0 +1,156 @@
---
id: 587d7fac367417b2b2512bdd
title: 使用動態比例
challengeType: 6
forumTopicId: 301495
dashedName: use-dynamic-scales
---
# --description--
D3 的 `min()``max()` 方法在設置比例尺時十分有用。
對於一個複雜的數據集,首要是設置比例尺,這樣可視化才能適合 SVG 容器的寬和高。 所有數據都應佈局在 SVG 畫布內部,這樣它們在頁面上纔是可見的。
下面這個例子爲散點圖設置了 x 軸的比例尺。 `domain()` 方法給比例尺傳遞關於散點圖原數據值的信息, `range()` 方法給出在頁面上進行可視化的實際空間信息。
在這個例子中domain 是從 0 到數據集中的最大值, 它使用 `max()` 方法和基於數組中 x 值的回調函數。 Range 使用 SVG 畫布的寬(`w`),幷包含 padding 這將在散點圖和 SVG 畫布邊緣之間添加空隙。
```js
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 30;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
```
在一開始可能很難理解 padding。 想象 x 軸是一條從 0 到 500 SVG 畫布寬的值)的水平直線。 在 `range()` 方法中包含 padding 使散點圖沿着這條直線從 30 (而不是 0開始在 470 (而不是 500結束。
# --instructions--
使用 `yScale` 變量創建一個線性的 y 軸比例尺。 domain 應該從 0 開始到數據集中 `y` 的最大值, range 應該使用 SVG 的高(`h`),幷包含 padding。
**注意:**記得保持繪圖在右上角。 當你爲 y 座標設置 range 時大的值height 減去 padding是第一個參數小的值是第二個參數。
# --hints--
`h2` 的文本應爲 `30`
```js
assert(output == 30 && $('h2').text() == '30');
```
yScale 的 `domain()` 應該等於 `[0, 411]`
```js
assert(JSON.stringify(yScale.domain()) == JSON.stringify([0, 411]));
```
yScale 的 `range()` 應該等於 `[470, 30]`
```js
assert(JSON.stringify(yScale.range()) == JSON.stringify([470, 30]));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
// Padding between the SVG canvas boundary and the plot
const padding = 30;
// Create an x and y scale
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
// Add your code below this line
const yScale = undefined;
// Add your code above this line
const output = yScale(411); // Returns 30
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [
[ 34, 78 ],
[ 109, 280 ],
[ 310, 120 ],
[ 79, 411 ],
[ 420, 220 ],
[ 233, 145 ],
[ 333, 96 ],
[ 222, 333 ],
[ 78, 320 ],
[ 21, 123 ]
];
const w = 500;
const h = 500;
const padding = 30;
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
const yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[1])])
.range([h - padding, padding]);
const output = yScale(411);
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
```

View File

@@ -0,0 +1,90 @@
---
id: 587d7fac367417b2b2512bdc
title: >-
使用 d3.max 和 d3.min 函數在數據集中查找最小值和最大值
challengeType: 6
forumTopicId: 301496
dashedName: >-
use-the-d3-max-and-d3-min-functions-to-find-minimum-and-maximum-values-in-a-dataset
---
# --description--
D3 的 `domain()``range()` 方法根據數據設置比例尺的信息。 下面有幾種更簡單的方法。
通常當你設置域的時候,你會想用數據集中的最小值和最大值。 試圖手動的找到這些值,尤其是在很大的數據集中,可能會出錯。
D3 有兩個方法——`min()``max()` 來返回這些值。 下面是一個例子:
```js
const exampleData = [34, 234, 73, 90, 6, 52];
d3.min(exampleData)
d3.max(exampleData)
```
像在散點圖的例子中的 `[x, y]` 座標對一樣,數據集有可能嵌套數組。 在這種情況下,你需要告訴 D3 怎麼計算最大值和最小值。 幸運的是,`min()``max()` 都可以使用回調函數。 在下面這個例子中,回調函數的參數 `d` 是當前的內部數組。 回調函數需要從內數組中返回你想比較大小的元素(`x` 值或 `y` 值)。 下面是一個如何找到二維數組的最大值和最小值的例子:
```js
const locationData = [[1, 7],[6, 3],[8, 3]];
const minX = d3.min(locationData, (d) => d[0]);
```
`minX` 的值應爲 `1`
# --instructions--
`positionData` 數組的子數組元素爲 x、y 和 z 座標。 使用 D3 方法從數組中查找 z 座標(第三個值)的最大值,並將其保存在 `output` 變量中。
# --hints--
`h2` 文本應爲 `8`
```js
assert(output == 8 && $('h2').text() == '8');
```
應使用 `max()` 方法。
```js
assert(
code.match(/\.max/g),
'Your code should use the <code>max()</code> method.'
);
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const positionData = [[1, 7, -4],[6, 3, 8],[2, 9, 3]]
// Add your code below this line
const output = undefined; // Change this line
// Add your code above this line
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const positionData = [[1, 7, -4],[6, 3, 8],[2, 9, 3]]
const output = d3.max(positionData, (d) => d[2])
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
```

View File

@@ -0,0 +1,105 @@
---
id: 587d7fa7367417b2b2512bc4
title: 使用 D3 中的數據
challengeType: 6
forumTopicId: 301497
dashedName: work-with-data-in-d3
---
# --description--
D3 是數據驅動的庫。 可以使用 D3 的方法將數組形式的數據顯示在頁面上。 數據有多種格式,但這個挑戰使用了一組簡單的數字。
第一步是讓 D3 知道數據。 `data()` 方法選擇連接着數據的 DOM 元素, 數據集作爲參數傳遞給該方法。
常見的方法是在文檔中爲數據集中的每一個數據創建一個元素。 爲此,你可以使用 D3 的 `enter()` 方法。
`enter()``data()` 方法一起使用時,它把從頁面中選擇的元素和數據集中的元素作比較。 如果頁面中選擇的元素較少則創建缺少的元素。
以下是一個選擇 `ul` 元素並根據添加的數組創建新的列表項的例子。
```html
<body>
<ul></ul>
<script>
const dataset = ["a", "b", "c"];
d3.select("ul").selectAll("li")
.data(dataset)
.enter()
.append("li")
.text("New item");
</script>
</body>
```
選擇不存在的 li 元素似乎有些難以理解。 這段代碼告訴 D3 先選擇頁面上的 `ul` 元素, 再選擇所有的列表項,它將返回空。 然後 `data()` 方法接收數組作爲參數,並運行三次後面的代碼,每次對應數組中的一個對象。 `enter()` 方法發現頁面中沒有 `li` 元素,但是需要 3 個(每個對應 `dataset` 中的一個數據)。 新的 `li` 元素被追加到 `ul`,文本爲 `New item`
# --instructions--
選擇 `body` 節點,然後選擇所有的 `h2` 元素。 讓 D3 爲 `dataset` 數組中的每一個對象創建並添加 `h2` 標籤。 `h2` 標籤的文本爲 `New Title`。 你應該使用 `data()``enter()` 方法。
# --hints--
文檔應該有 9 個 `h2` 元素。
```js
assert($('h2').length == 9);
```
`h2` 元素的文本應爲 `New Title`。 大小寫和空格必須一致。
```js
assert(
$('h2')
.text()
.match(/New Title/g).length == 9
);
```
應該使用 `data()` 方法。
```js
assert(code.match(/\.data/g));
```
應該使用 `enter()` 方法。
```js
assert(code.match(/\.enter/g));
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
// Add your code below this line
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body")
.selectAll("h2")
.data(dataset)
.enter()
.append("h2")
.text("New Title")
</script>
</body>
```

View File

@@ -0,0 +1,122 @@
---
id: 587d7fa7367417b2b2512bc5
title: 使用 D3 中的動態數據
challengeType: 6
forumTopicId: 301498
dashedName: work-with-dynamic-data-in-d3
---
# --description--
最後兩個挑戰涉及到使用 D3 的 `data()``enter()` 方法來動態展示數據。 它們以數據集爲參數,和 `append()` 方法一起使用,爲數據集中的每一個元素對象創建一個 DOM 元素。
在之前的挑戰中,你爲 `dataset` 數組中的每一個對象創建了一個新的 `h2` 元素,但是它們的文本都是相同的 `New Title`。 這是因爲你還沒有使用和每個 `h2` 元素關聯的數據。
`text()` 方法以字符串或者回調函數作爲參數:
```js
selection.text((d) => d)
```
上面這個例子中的參數 `d` 指關聯數據集的一個對象。
使用當前示例作爲上下文,第一個 `h2` 元素綁定到 12第二個 `h2` 元素綁定到 31第三個 `h2` 元素綁定到 22依此類推。
# --instructions--
修改 `text()` 方法,使每個 `h2` 元素顯示 `dataset` 數組中的對應值,加上一個空格和字符串 `USD`。 例如,第一個標題應該爲 `12 USD`
# --hints--
第一個 `h2` 的文本爲 `12 USD`
```js
assert($('h2').eq(0).text() == '12 USD');
```
第二個 `h2` 的文本爲 `31 USD`
```js
assert($('h2').eq(1).text() == '31 USD');
```
第三個 `h2` 的文本爲 `22 USD`
```js
assert($('h2').eq(2).text() == '22 USD');
```
第四個 `h2` 的文本爲 `17 USD`
```js
assert($('h2').eq(3).text() == '17 USD');
```
第五個 `h2` 的文本爲 `25 USD`
```js
assert($('h2').eq(4).text() == '25 USD');
```
第六個 `h2` 的文本爲 `18 USD`
```js
assert($('h2').eq(5).text() == '18 USD');
```
第七個 `h2` 的文本爲 `29 USD`
```js
assert($('h2').eq(6).text() == '29 USD');
```
第八個 `h2` 的文本爲 `14 USD`
```js
assert($('h2').eq(7).text() == '14 USD');
```
第九個 `h2` 的文本爲 `9 USD`
```js
assert($('h2').eq(8).text() == '9 USD');
```
# --seed--
## --seed-contents--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
// Add your code below this line
.text("New Title");
// Add your code above this line
</script>
</body>
```
# --solutions--
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
d3.select("body").selectAll("h2")
.data(dataset)
.enter()
.append("h2")
.text((d) => `${d} USD`);
</script>
</body>
```

View File

@@ -0,0 +1,167 @@
---
id: 587d7fae367417b2b2512be4
title: 訪問來自 API 的 JSON 數據
challengeType: 6
forumTopicId: 301499
dashedName: access-the-json-data-from-an-api
---
# --description--
在前面的挑戰中,你瞭解瞭如何從 freeCodeCamp Cat Photo API 獲取 JSON 數據。
現在,你將進一步觀察返回的數據,以更好地瞭解 JSON 格式。 回憶一下 JavaScript 中的一些符號:
<blockquote>[ ] -> 方括號表示數組<br>{ } -> 大括號表示對象<br>" " -> 雙引號表示字符串, 它們還用於表示 JSON 中的鍵名</blockquote>
理解 API 返回數據的結構是必需的,它將影響你如何獲取你所需的值。
在右側,單擊 `Get Message` 按鈕,將 freeCodeCamp Cat Photo API JSON 加載到 HTML 中。
在 JSON 數據中的第一個和最後一個字符是中括號`[ ]` 這意味着返回的數據是一個數組。 JSON 數據中的第二個符號是一個大括號`{`,這意味着是一個對象。 再仔細看,你會發現有三個獨立的對象。 這個 JSON 數據是一個包含三個對象的數組,它們各自都包含了 cat photo 的信息。
你之前瞭解了對象包含了用逗號分隔的 "鍵值對"。 在 Cat Photo 示例中,第一個對象的 `"id":0``id` 是鍵,`0` 是對應的值。 類似地,`imageLink``altText``codeNames` 也有鍵。 每個 cat photo 對象具有相同的鍵,但具有不同的值。
在第一個對象中有一個有趣的 "鍵值對" 它是`"codeNames":["Juggernaut","Mrs. Wallace","ButterCup"]``codeNames` 是鍵,它的值是一個包含三個字符串的數組。 對象數組以及數組作爲鍵可以作爲值
記住如何訪問數組和對象中的數據。 數組使用括號表示法來訪問項目的特定索引, 對象使用括號或點表示法來訪問給定屬性的值。 這個例子打印第一張 cat photo 的 `altText` 屬性——請注意,編輯器中解析的 JSON 數據被保存在名爲 `json` 的變量中:
```js
console.log(json[0].altText);
```
控制檯將顯示字符串 `A white cat wearing a green helmet shaped melon on its head.`
# --instructions--
對於 `id` 爲 2 的 cat在控制檯打印 `codeNames` 數組中的第二個值。 你應該在對象(保存在變量 `json` 中)上使用括號或者點表示法來訪問該值。
# --hints--
應該使用括號和點表示法來讀取正確的代碼名稱,並將 `Loki` 打印到控制檯。
```js
assert(
code.match(
/console\s*\.\s*log\s*\(\s*json\s*\[2\]\s*(\.\s*codeNames|\[\s*('|`|")codeNames\2\s*\])\s*\[\s*1\s*\]\s*\)/g
)
);
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload=function(){
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
// Add your code below this line
// Add your code above this line
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload=function(){
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
// Add your code below this line
console.log(json[2].codeNames[1]);
// Add your code above this line
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,140 @@
---
id: 587d7fad367417b2b2512be2
title: 通過單擊事件更改文本
challengeType: 6
forumTopicId: 301500
dashedName: change-text-with-click-events
---
# --description--
當點擊事件發生時,你可以使用 JavaScript 更新 HTML 元素。
例如,當用戶點擊 `Get Message` 按鈕時,它將改變 class 爲 `message` 的元素的文本爲 `Here is the message`
通過在點擊事件內添加以下代碼實現:
```js
document.getElementsByClassName('message')[0].textContent="Here is the message";
```
# --instructions--
`onclick` 事件處理器中添加代碼,改變 `message` 元素內的文本爲 `Here is the message`
# --hints--
應該使用 `document.getElementsByClassName` 方法來選擇 class 爲 `message` 的元素,然後將其 `textContent` 改爲給定文字。
```js
assert(
code.match(
/document\s*\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\s*\.textContent\s*?=\s*?('|")Here is the message\2/g
)
);
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
// Add your code below this line
// Add your code above this line
}
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick = function(){
// Add your code below this line
document.getElementsByClassName('message')[0].textContent = "Here is the message";
// Add your code above this line
}
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,199 @@
---
id: 587d7fae367417b2b2512be5
title: 將 JSON 數據轉換爲 HTML
challengeType: 6
forumTopicId: 16807
dashedName: convert-json-data-to-html
---
# --description--
現在你從 JSON API 獲取了數據,可以在 HTML 中顯示它們了。
既然 cat photo 對象都保存在數組裏,你可以使用 `forEach` 方法來遍歷它們。 當你拿到每個對象時,你就可以修改 HTML 元素了。
首先,通過 `let html = "";` 聲明一個 html 變量。
接着,遍歷 JSON將用 `strong` 標籤包裹的鍵名和後面跟着值的 html 元素添加給變量。 當循環結束後渲染它。
這是執行此操作的代碼:
```js
let html = "";
json.forEach(function(val) {
const keys = Object.keys(val);
html += "<div class = 'cat'>";
keys.forEach(function(key) {
html += "<strong>" + key + "</strong>: " + val[key] + "<br>";
});
html += "</div><br>";
});
```
**注意:**在本挑戰中,你需要給頁面添加新的 HTML 元素,所以你不能使用 `textContent` 方法。 你可以用 `innerHTML` 來完成挑戰,這個方法使網站容易遭受跨站腳本攻擊。
# --instructions--
添加一個 `forEach` 循環來遍歷 JSON 數據,並創建 HTML 元素以顯示它。
下面是示例 JSON
```json
[
{
"id":0,
"imageLink":"https://s3.amazonaws.com/freecodecamp/funny-cat.jpg",
"altText":"A white cat wearing a green helmet shaped melon on its head. ",
"codeNames":[ "Juggernaut", "Mrs. Wallace", "Buttercup"
]
}
]
```
# --hints--
應該將數據保存在 `html` 變量中。
```js
assert(__helpers.removeWhiteSpace(code).match(/html(\+=|=html\+)/g))
```
應該使用 `forEach` 方法來遍歷 API 中的 JSON 數據。
```js
assert(code.match(/json\.forEach/g));
```
應該用 `strong` 標籤包裹鍵名。
```js
assert(code.match(/<strong>.+<\/strong>/g));
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
// Add your code below this line
// Add your code above this line
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
// Add your code below this line
json.forEach(function(val) {
var keys = Object.keys(val);
html += "<div class = 'cat'>";
keys.forEach(function(key) {
html += "<strong>" + key + "</strong>: " + val[key] + "<br>";
});
html += "</div><br>";
});
// Add your code above this line
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,98 @@
---
id: 587d7faf367417b2b2512be8
title: 根據地理位置數據找到用戶的 GPS 座標
challengeType: 6
forumTopicId: 18188
dashedName: get-geolocation-data-to-find-a-users-gps-coordinates
---
# --description--
你還能做一件很酷的事就是訪問你用戶當前的地理位置。 每個瀏覽器都有內置的導航器,可以爲你提供這些信息。
導航器會獲取用戶當前的經度和緯度。
您將看到允許或阻止此站點了解您當前位置的提示。 只要代碼正確,挑戰就可以以任何一種方式完成。
通過選擇允許,你將看到輸出手機上的文本更改爲你的緯度和經度
這是執行此操作的代碼:
```js
if (navigator.geolocation){
navigator.geolocation.getCurrentPosition(function(position) {
document.getElementById('data').innerHTML="latitude: " + position.coords.latitude + "<br>longitude: " + position.coords.longitude;
});
}
```
首先,它檢查`navigator.geolocation`對象是否存在。 如果是,`getCurrentPosition`則調用該對象上的方法,該方法啓動對用戶位置的異步請求。 如果請求成功,則運行方法中的回調函數。 此函數`position`使用點表示法訪問對象的緯度和經度值,並更新頁面。
# --instructions--
`script`標記內添加示例代碼以檢查用戶的當前位置並將其插入 HTML
# --hints--
應該使用 `navigator.geolocation` 訪問用戶的當前位置。
```js
assert(code.match(/navigator\.geolocation\.getCurrentPosition/g));
```
應該使用 `position.coords.latitude` 顯示用戶的緯度位置。
```js
assert(code.match(/position\.coords\.latitude/g));
```
應該使用 `position.coords.longitude` 顯示用戶的經度位置。
```js
assert(code.match(/position\.coords\.longitude/g));
```
應該在具有 `id="data"``div` 元素中顯示用戶的位置。
```js
assert(
code.match(/document\.getElementById\(\s*?('|")data\1\s*?\)\.innerHTML/g)
);
```
# --seed--
## --seed-contents--
```html
<script>
// Add your code below this line
// Add your code above this line
</script>
<h4>You are here:</h4>
<div id="data">
</div>
```
# --solutions--
```html
<script>
// Add your code below this line
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
document.getElementById('data').innerHTML = "latitude: " + position.coords.latitude + "<br>longitude: " + position.coords.longitude;
});
}
// Add your code above this line
</script>
<h4>You are here:</h4>
<div id="data">
</div>
</section>
```

View File

@@ -0,0 +1,174 @@
---
id: 5ccfad82bb2dc6c965a848e5
title: 使用 JavaScript 的 fetch 方法獲取 JSON
challengeType: 6
forumTopicId: 301501
dashedName: get-json-with-the-javascript-fetch-method
---
# --description--
請求外部數據的另一個方法是使用 JavaScript 的 `fetch()` 方法。 它的作用和 `XMLHttpRequest` 一樣,但是它的語法更容易理解。
下面是使用 GET 請求 `/json/cats.json` 數據的例子。
```js
fetch('/json/cats.json')
.then(response => response.json())
.then(data => {
document.getElementById('message').innerHTML = JSON.stringify(data);
})
```
逐行解釋一下代碼。
第一行是發起請求。 `fetch(URL)` 向指定的 URL 發起 `GET` 請求。 這個方法返回一個 Promise。
當 Promise 返回後,如果請求成功,會執行 `then` 方法,該方法把響應轉換爲 JSON 格式。
`then` 方法返回的也是 Promise會被下一個 `then` 方法捕獲。 第二個 `then` 方法傳入的參數就是最終的 JSON 對象。
接着,使用 `document.getElementById()` 選擇將要接收數據的元素。 然後插入請求返回的 JSON 對象創建的字符串修改元素的 HTML 代碼。
# --instructions--
更新代碼,創建並向 freeCodeCamp Cat Photo API 發送 `GET` 請求。 這次使用 `fetch` 方法而不是 `XMLHttpRequest`
# --hints--
應該使用 `fetch` 發起 `GET` 請求。
```js
assert(code.match(/fetch\s*\(\s*('|")\/json\/cats\.json\1\s*\)/g));
```
應該在 `then` 裏面將響應轉換爲 JSON。
```js
assert(
code.match(
/\.then\s*\(\s*\(?(?<var>\w+)\)?\s*=>\s*\k<var>\s*\.json\s*\(\s*\)\s*\)/g
)
);
```
應該使用另一個 `then` 接收 `then` 轉換的 JSON。
```js
assert(__helpers.removeWhiteSpace(code).match(/\.then\(\(?\w+\)?=>{[^}]*}\)/g));
```
代碼應該選擇 id 爲 `message` 的元素然後把它的內部 HTML 改成 JSON data 的字符串。
```js
assert(
__helpers.removeWhiteSpace(code).match(
/document\.getElementById\(('|")message\1\)\.innerHTML=JSON\.stringify\(?\w+\)/g
)
);
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick= () => {
// Add your code below this line
// Add your code above this line
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p id="message" class="box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick= () => {
fetch('/json/cats.json')
.then(response => response.json())
.then(data => {
document.getElementById('message').innerHTML=JSON.stringify(data);
})
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p id="message" class="box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,196 @@
---
id: 587d7fae367417b2b2512be3
title: 使用 XMLHttpRequest 方法獲取 JSON
challengeType: 6
forumTopicId: 301502
dashedName: get-json-with-the-javascript-xmlhttprequest-method
---
# --description--
你還可以從外部來源請求數據。 這就是 API 發揮作用的地方。
請記住API或叫應用程序編程接口是計算機用來互相通信的工具。 你將學習如何通過 AJAX技術 從 API 獲得的數據來更新 HTML。
大部分 web APIs 以 JSON 格式傳輸數據。 JSON 是 JavaScript Object Notation 的簡寫。
JSON 語法與 JavaScript 對象字面符號非常相似。 JSON 具有對象屬性以及其當前值,夾在 `{``}`之間。
這些屬性及其值通常稱爲 "鍵值對"。
但是JSON 是由 API 以`bytes` 形式傳輸的,你的程序以`string`接受它。 它們能轉換成爲 JavaScript 對象,但默認情況下它們不是 JavaScript 對象。 `JSON.parse`方法解析字符串並構造它描述的 JavaScript 對象。
你可以從 freeCodeCamp 的 Cat Photo API 請求 JSON。 以下是你可以在點擊事件中添加的代碼:
```js
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
};
```
這裏介紹每行代碼的作用。 JavaScript `XMLHttpRequest` 對象具有許多用於傳輸數據的屬性和方法。 首先,創建一個`XMLHttpRequest`對象實例,並保存在`req`變量裏 。 然後,`open` 方法初始化一個請求——這個例子是從 API 請求數據,因此它是一個 `GET` 請求。 第二個參數 `open` 是你要從中請求數據的 API 的 URL。 第三個參數是一個布爾值, `true` 使其成爲異步請求。 `send` 方法發送請求。 最後,`onload` 事件處理程序解析返回的數據並應用該 `JSON.stringify` 方法將JavaScript對象轉換爲字符串 然後將此字符串作爲消息文本插入。
# --instructions--
更新代碼,創建並向 freeCodeCamp Cat Photo API 發送 `GET` 請求。 然後單擊 `Get Message` 按鈕。 AJAX 函數將使用 API 的原始 JSON 輸出替換文本 `The message will go here`
# --hints--
應該創建一個新的 `XMLHttpRequest`
```js
assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
```
應該使用該 `open` 方法初始化對 freeCodeCamp Cat Photo API 的 `GET` 請求。
```js
assert(
code.match(
/\.open\(\s*?('|")GET\1\s*?,\s*?('|")\/json\/cats\.json\2\s*?,\s*?true\s*?\)/g
)
);
```
應使用該 `send` 方法發送請求。
```js
assert(code.match(/\.send\(\s*\)/g));
```
應該有一個 `onload` 設置爲函數的事件處理程序。
```js
assert(
code.match(/\.onload\s*=\s*(function|\(\s*?\))\s*?(\(\s*?\)|\=\>)\s*?{/g)
);
```
應該使用該 `JSON.parse` 方法來解析 `responseText`
```js
assert(code.match(/JSON\s*\.parse\(\s*.*\.responseText\s*\)/g));
```
應該使用 `message` 獲取元素,並將其內部 HTML 轉換爲 JSON 數據字符串。
```js
assert(
code.match(
/document\s*\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\s*\.innerHTML\s*?=\s*?JSON\.stringify\(.+?\)/g
)
);
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
// Add your code below this line
// Add your code above this line
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open('GET', '/json/cats.json', true);
req.send();
req.onload = () => {
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,140 @@
---
id: 587d7fad367417b2b2512be1
title: 使用 onclick 屬性處理點擊事件
challengeType: 6
forumTopicId: 301503
dashedName: handle-click-events-with-javascript-using-the-onclick-property
---
# --description--
你希望代碼僅在頁面完成加載後執行。 爲此,你可將名爲`DOMContentLoaded`的 JavaScript 事件附加到文檔中。 以下是實現的代碼:
```js
document.addEventListener('DOMContentLoaded', function() {
});
```
你可以在`DOMContentLoaded`函數內部添加事件處理方法。 你可以添加`onclick`事件處理器,當用戶點擊 id 爲`getMessage`的元素時會觸發事件。 添加以下代碼:
```js
document.getElementById('getMessage').onclick = function(){};
```
# --instructions--
`DOMContentLoaded`函數內爲 id 爲`getMessage`的元素添加一個 click 事件處理器。
# --hints--
你的代碼應該用`document.getElementById`方法來選擇`getMessage`元素。
```js
assert(code.match(/document\s*\.getElementById\(\s*?('|")getMessage\1\s*?\)/g));
```
你的代碼應該添加`onclick`事件處理器。
```js
assert(typeof document.getElementById('getMessage').onclick === 'function');
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
// Add your code below this line
// Add your code above this line
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
// Add your code below this line
document.getElementById('getMessage').onclick = function(){ };
// Add your code above this line
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,206 @@
---
id: 587d7faf367417b2b2512be9
title: 使用 XMLHttpRequest 方法發送數據
challengeType: 6
forumTopicId: 301504
dashedName: post-data-with-the-javascript-xmlhttprequest-method
---
# --description--
在前面的示例中,你通過外部資源獲取數據。 此外,你也可以將數據發送到外部資源,只要該資源支持 AJAX 請求並且你知道 URL。
JavaScript 的`XMLHttpRequest`方法也用於將數據發佈到服務器。 這是一個示例:
```js
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 201){
const serverResponse = JSON.parse(xhr.response);
document.getElementsByClassName('message')[0].textContent = serverResponse.userName + serverResponse.suffix;
}
};
const body = JSON.stringify({ userName: userName, suffix: ' loves cats!' });
xhr.send(body);
```
你之前已經見過這些方法。 `open` 方法將對外部資源的給定 URL 的請求初始化爲 `POST`,並使用 `true` 布爾值使其變成異步的。 `setRequestHeader` 方法設置了 HTTP 請求標頭的值,該標頭包含有關發送人和請求的信息。 它必須在 `open` 方法之後、`send` 方法之前調用。 它的兩個參數表示標頭的內容類型和標頭數據將被設置成什麼值。 接下來,`onreadystatechange` 事件監聽器監聽請求狀態的更改。 `readyState``4`,表示操作已完成。`status``201`,表示請求成功。 文檔的 HTML 可以更新。 最後,`send` 方法發送帶有 `body` 值的請求,其中 `userName` 的值由用戶在 `input` 字段中輸入。
# --instructions--
更新代碼,創建並向 API 發送 `POST` 請求。 然後在輸入框中輸入你的姓名,並點擊 `Send Message`。 你的 AJAX 函數會用服務器返回的數據替換 `Reply from Server will be here.`。 修改返回的請求結果,在你的名字後面添加 `loves cats`
# --hints--
應該創建一個新的 `XMLHttpRequest`
```js
assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
```
應該使用 `open` 方法初始化一個發送給服務器的 `POST` 請求。
```js
assert(code.match(/\.open\(\s*?('|")POST\1\s*?,\s*?url\s*?,\s*?true\s*?\)/g));
```
應該使用 `setRequestHeader` 方法。
```js
assert(
code.match(
/\.setRequestHeader\(\s*?('|")Content-Type\1\s*?,\s*?('|")application\/json;\s*charset=UTF-8\2\s*?\)/g
)
);
```
應該有一個 `onreadystatechange` 的事件監聽器。
```js
assert(code.match(/\.onreadystatechange\s*?=/g));
```
應該獲取 class 爲 `message` 的元素,並將它的 `textContent` 更改爲 `userName loves cats`
```js
assert(
code.match(
/document\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\.textContent\s*?=\s*?.+?\.userName\s*?\+\s*?.+?\.suffix/g
)
);
```
應該使用 `send` 方法。
```js
assert(code.match(/\.send\(\s*?body\s*?\)/g));
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('sendMessage').onclick = function(){
const userName = document.getElementById('name').value;
const url = 'https://jsonplaceholder.typicode.com/posts';
// Add your code below this line
// Add your code above this line
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Friends</h1>
<p class="message box">
Reply from Server will be here
</p>
<p>
<label for="name">Your name:
<input type="text" id="name"/>
</label>
<button id="sendMessage">
Send Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('sendMessage').onclick = function(){
const userName = document.getElementById('name').value;
const url = 'https://jsonplaceholder.typicode.com/posts';
// Add your code below this line
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 201){
const serverResponse = JSON.parse(xhr.response);
document.getElementsByClassName('message')[0].textContent = serverResponse.userName + serverResponse.suffix;
}
};
const body = JSON.stringify({ userName: userName, suffix: ' loves cats!' });
xhr.send(body);
// Add your code above this line
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Friends</h1>
<p class="message">
Reply from Server will be here
</p>
<p>
<label for="name">Your name:
<input type="text" id="name"/>
</label>
<button id="sendMessage">
Send Message
</button>
</p>
```

View File

@@ -0,0 +1,171 @@
---
id: 587d7fae367417b2b2512be7
title: 預先過濾 JSON 以獲得所需的數據
challengeType: 6
forumTopicId: 18257
dashedName: pre-filter-json-to-get-the-data-you-need
---
# --description--
如果你不希望渲染每張從 freeCodeCamp Cat Photo API 取回的貓照片,你可以在循環先預先過濾 JSON 數據。
鑑於 JSON 數據存儲在數組中,你可以使用 `filter` 方法過濾掉 `id` 鍵值爲 `1` 的 cat。
這是執行此操作的代碼:
```js
json = json.filter(function(val) {
return (val.id !== 1);
});
```
# --instructions--
添加代碼以 `filter` json 數據,刪除 `id` 值爲 `1` 的 cat。
# --hints--
應該使用 `filter` 方法。
```js
assert(code.match(/json\.filter/g));
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload=function(){
let json = JSON.parse(req.responseText);
let html = "";
// Add your code below this line
// Add your code above this line
json.forEach(function(val) {
html += "<div class = 'cat'>"
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>"
html += "</div>"
});
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload = function(){
let json = JSON.parse(req.responseText);
let html = "";
// Add your code below this line
json = json.filter(function(val) {
return (val.id !== 1);
});
// Add your code above this line
json.forEach(function(val) {
html += "<div class = 'cat'>"
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>"
html += "</div>"
});
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```

View File

@@ -0,0 +1,163 @@
---
id: 587d7fae367417b2b2512be6
title: 渲染數據源的圖像
challengeType: 6
forumTopicId: 18265
dashedName: render-images-from-data-sources
---
# --description--
前幾個挑戰中表明JSON 數組中的每個對象都包含一個 `imageLink` 鍵,其值爲貓圖像的 URL。
當你遍歷這些對象的時候,你可以使用 `imageLink` 屬性在 `img` 元素中顯示此圖像。
這是執行此操作的代碼:
```js
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>";
```
# --instructions--
添加代碼以在 `img` 標記中使用 `imageLink``altText` 屬性。
# --hints--
應該使用 `imageLink` 屬性來顯示圖像。
```js
assert(code.match(/val\.imageLink/g));
```
應該使用 `altText` 作爲圖片的 `alt` 屬性值。
```js
assert(code.match(/val\.altText/g));
```
# --seed--
## --seed-contents--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req=new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
json.forEach(function(val) {
html += "<div class = 'cat'>";
// Add your code below this line
// Add your code above this line
html += "</div><br>";
});
document.getElementsByClassName('message')[0].innerHTML=html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
# --solutions--
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
json.forEach(function(val) {
html += "<div class = 'cat'>";
// Add your code below this line
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>";
// Add your code above this line
html += "</div><br>";
});
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```