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,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>
```