chore: seed chinese traditional (#42005)
Seeds the chinese traditional files manually so we can deploy to staging.
This commit is contained in:
committed by
GitHub
parent
e46e80e08f
commit
3da4be21bb
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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` 正值將圖形從原點下移
|
||||
|
||||
若要把一個圖形放在上個挑戰的 500(寬)x 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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
@ -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>
|
||||
```
|
Reference in New Issue
Block a user