chore(learn): Applied MDX format to Chinese curriculum files (#40462)

This commit is contained in:
Randell Dawson
2020-12-16 00:37:30 -07:00
committed by GitHub
parent 873fce02a2
commit 9ce4a02a41
1665 changed files with 58741 additions and 88042 deletions

View File

@ -1,132 +1,27 @@
---
id: 587d7faa367417b2b2512bd4
title: 给 D3 元素添加悬停效果
challengeType: 6
forumTopicId: 301469
title: 给 D3 元素添加悬停效果
---
## Description
<section id='description'>
# --description--
我们可以为用户的鼠标悬停行为添加高亮显示的效果。到目前为止,矩形的样式应用了内置的 D3 和 SVG 方法,但是你也可以使用 CSS 来实现。
你可以使用 <code>attr()</code> 方法在 SVG 元素上设置 CSS 类。然后用 <code>:hover</code> 伪类为你新添加的 CSS 类设置鼠标悬停的效果。
</section>
## Instructions
<section id='instructions'>
<code>attr()</code> 方法给所有的 <code>rect</code> 元素都添加 <code>bar</code> 类。当鼠标悬停在元素上时,它的 <code>fill</code> 将变为棕色。
</section>
你可以使用 `attr()` 方法在 SVG 元素上设置 CSS 类。然后用 `:hover` 伪类为你新添加的 CSS 类设置鼠标悬停的效果。
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: <code>rect</code> 元素应该有 <code>bar</code> 类。
testString: assert($('rect').attr('class') == "bar");
`attr()` 方法给所有的 `rect` 元素都添加 `bar` 类。当鼠标悬停在元素上时,它的 `fill` 将变为棕色。
```
# --hints--
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
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>
```
</div>
</section>
## Solution
<section id='solution'>
`rect` 元素应该有 `bar` 类。
```js
<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>
assert($('rect').attr('class') == 'bar');
```
</section>
# --solutions--

View File

@ -1,154 +1,81 @@
---
id: 587d7faa367417b2b2512bd6
title: 给 D3 元素添加工具提示
challengeType: 6
forumTopicId: 301470
title: 给 D3 元素添加工具提示
---
## Description
<section id='description'>
当用户在一个对象上悬停时,提示框可以显示关于这个对象更多的信息。在可视化中有多种方法添加提示框,这个挑战将使用 SVG 的 <code>title</code> 元素。
请使用 <code>tile</code><code>text()</code> 方法一起给每组动态添加数据。
</section>
# --description--
## Instructions
<section id='instructions'>
在每个 <code>rect</code> 节点下面添加一个 <code>title</code> 元素,然后用回调函数调用 <code>text()</code> 方法使它的文本显示数据值。
</section>
当用户在一个对象上悬停时,提示框可以显示关于这个对象更多的信息。在可视化中有多种方法添加提示框,这个挑战将使用 SVG 的 `title` 元素。
## Tests
<section id='tests'>
请使用 `tile``text()` 方法一起给每组动态添加数据。
```yml
tests:
- text: 你应该有 9 个 <code>title</code> 元素。
testString: assert($('title').length == 9);
- text: 第一个 <code>title</code> 元素的提示框文本应为 12。
testString: assert($('title').eq(0).text() == '12');
- text: 第二个 <code>title</code> 元素的提示框文本应为 31。
testString: assert($('title').eq(1).text() == '31');
- text: 第三个 <code>title</code> 元素的提示框文本应为 22。
testString: assert($('title').eq(2).text() == '22');
- text: 第四个 <code>title</code> 元素的提示框文本应为 17。
testString: assert($('title').eq(3).text() == '17');
- text: 第五个 <code>title</code> 元素的提示框文本应为 25。
testString: assert($('title').eq(4).text() == '25');
- text: 第六个 <code>title</code> 元素的提示框文本应为 18。
testString: assert($('title').eq(5).text() == '18');
- text: 第七个 <code>title</code> 元素的提示框文本应为 29。
testString: assert($('title').eq(6).text() == '29');
- text: 第八个 <code>title</code> 元素的提示框文本应为 14。
testString: assert($('title').eq(7).text() == '14');
- text: 第九个 <code>title</code> 元素的提示框文本应为 9。
testString: assert($('title').eq(8).text() == '9');
# --instructions--
在每个 `rect` 节点下面添加一个 `title` 元素,然后用回调函数调用 `text()` 方法使它的文本显示数据值。
# --hints--
你应该有 9 个 `title` 元素。
```js
assert($('title').length == 9);
```
</section>
第一个 `title` 元素的提示框文本应为 12。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
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>
```js
assert($('title').eq(0).text() == '12');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第二个 `title` 元素的提示框文本应为 31。
```js
assert($('title').eq(1).text() == '31');
```
</section>
第三个 `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');
```
# --solutions--

View File

@ -1,144 +1,131 @@
---
id: 587d7fab367417b2b2512bd8
title: 给 Circle 元素添加属性
challengeType: 6
forumTopicId: 301471
title: 给 Circle 元素添加属性
---
## Description
<section id='description'>
上个挑战为 <code>dataset</code> 中的每个点都创建了 <code>circle</code> 元素,并将它们添加到 SVG 画布上。但是 D3 需要更多关于位置和 <code>circle</code> 大小的信息来正确的显示它们。
在 SVG 中 <code>circle</code> 有三个主要的属性。<code>cx</code><code>cy</code> 属性是坐标,它们告诉 D3 将图形的<em>中心</em>放在 SVG 画布的何处。半径( <code>r</code> 属性)给出 <code>circle</code> 的大小。
就像 <code>rect</code><code>y</code> 坐标,<code>circle</code><code>cy</code> 属性是从 SVG 画布的顶端开始测量的,而不是从底端。
所有的属性都可以用回调函数来动态设值。记住,所有串联在 <code>data(dataset)</code> 后面的方法为 <code>dataset</code> 中的每个对象都运行一次。回调函数中的 <code>d</code> 参数指在 <code>dataset</code> 中的当前对象,对每个点来说都是一个数组。就像 <code>d[0]</code>,你可以使用方括号的方式来访问数组中的值。
</section>
# --description--
## Instructions
<section id='instructions'>
<code>circle</code> 元素添加 <code>cx</code><code>cy</code><code>r</code> 属性。<code>cx</code> 的值应该是 <code>dataset</code> 中每个对象的数组的第一个数,<code>cy</code> 的值应该根据数据中的第二个数,但是要确保正向显示图表而不是倒转。所有圆圈的 <code>r</code> 的值应该为 5。
</section>
上个挑战为 `dataset` 中的每个点都创建了 `circle` 元素,并将它们添加到 SVG 画布上。但是 D3 需要更多关于位置和 `circle` 大小的信息来正确的显示它们。
## Tests
<section id='tests'>
在 SVG 中 `circle` 有三个主要的属性。`cx``cy` 属性是坐标,它们告诉 D3 将图形的*中心*放在 SVG 画布的何处。半径( `r` 属性)给出 `circle` 的大小。
```yml
tests:
- text: 你应该有 10 个 <code>circle</code> 元素。
testString: assert($('circle').length == 10);
- text: 第一个 <code>circle</code> 元素的 <code>cx</code> 值应该为 34<code>cy</code> 值应该为 422<code>r</code> 值应该为 5。
testString: assert($('circle').eq(0).attr('cx') == '34' && $('circle').eq(0).attr('cy') == '422' && $('circle').eq(0).attr('r') == '5');
- text: 第二个 <code>circle</code> 元素的 <code>cx</code> 值应该为 109<code>cy</code> 值应该为 220<code>r</code> 值应该为 5。
testString: assert($('circle').eq(1).attr('cx') == '109' && $('circle').eq(1).attr('cy') == '220' && $('circle').eq(1).attr('r') == '5');
- text: 第三个 <code>circle</code> 元素的 <code>cx</code> 值应该为 310<code>cy</code> 值应该为 380<code>r</code> 值应该为 5。
testString: assert($('circle').eq(2).attr('cx') == '310' && $('circle').eq(2).attr('cy') == '380' && $('circle').eq(2).attr('r') == '5');
- text: 第四个 <code>circle</code> 元素的 <code>cx</code> 值应该为 79<code>cy</code> 值应该为 89<code>r</code> 值应该为 5。
testString: assert($('circle').eq(3).attr('cx') == '79' && $('circle').eq(3).attr('cy') == '89' && $('circle').eq(3).attr('r') == '5');
- text: 第五个 <code>circle</code> 元素的 <code>cx</code> 值应该为 420<code>cy</code> 值应该为 280<code>r</code> 值应该为 5。
testString: assert($('circle').eq(4).attr('cx') == '420' && $('circle').eq(4).attr('cy') == '280' && $('circle').eq(4).attr('r') == '5');
- text: 第六个 <code>circle</code> 元素的 <code>cx</code> 值应该为 233<code>cy</code> 值应该为 355<code>r</code> 值应该为 5。
testString: assert($('circle').eq(5).attr('cx') == '233' && $('circle').eq(5).attr('cy') == '355' && $('circle').eq(5).attr('r') == '5');
- text: 第七个 <code>circle</code> 元素的 <code>cx</code> 值应该为 333<code>cy</code> 值应该为 404<code>r</code> 值应该为 5。
testString: assert($('circle').eq(6).attr('cx') == '333' && $('circle').eq(6).attr('cy') == '404' && $('circle').eq(6).attr('r') == '5');
- text: 第八个 <code>circle</code> 元素的 <code>cx</code> 值应该为 222<code>cy</code> 值应该为 167<code>r</code> 值应该为 5。
testString: assert($('circle').eq(7).attr('cx') == '222' && $('circle').eq(7).attr('cy') == '167' && $('circle').eq(7).attr('r') == '5');
- text: 第九个 <code>circle</code> 元素的 <code>cx</code> 值应该为 78<code>cy</code> 值应该为 180<code>r</code> 值应该为 5。
testString: assert($('circle').eq(8).attr('cx') == '78' && $('circle').eq(8).attr('cy') == '180' && $('circle').eq(8).attr('r') == '5');
- text: 第十个 <code>circle</code> 元素的 <code>cx</code> 值应该为 21<code>cy</code> 值应该为 377<code>r</code> 值应该为 5。
testString: assert($('circle').eq(9).attr('cx') == '21' && $('circle').eq(9).attr('cy') == '377' && $('circle').eq(9).attr('r') == '5');
就像 `rect``y` 坐标,`circle``cy` 属性是从 SVG 画布的顶端开始测量的,而不是从底端。
所有的属性都可以用回调函数来动态设值。记住,所有串联在 `data(dataset)` 后面的方法为 `dataset` 中的每个对象都运行一次。回调函数中的 `d` 参数指在 `dataset` 中的当前对象,对每个点来说都是一个数组。就像 `d[0]`,你可以使用方括号的方式来访问数组中的值。
# --instructions--
`circle` 元素添加 `cx``cy``r` 属性。`cx` 的值应该是 `dataset` 中每个对象的数组的第一个数,`cy` 的值应该根据数据中的第二个数,但是要确保正向显示图表而不是倒转。所有圆圈的 `r` 的值应该为 5。
# --hints--
你应该有 10 个 `circle` 元素。
```js
assert($('circle').length == 10);
```
</section>
第一个 `circle` 元素的 `cx` 值应该为 34`cy` 值应该为 422`r` 值应该为 5。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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>
```js
assert(
$('circle').eq(0).attr('cx') == '34' &&
$('circle').eq(0).attr('cy') == '422' &&
$('circle').eq(0).attr('r') == '5'
);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第二个 `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'
);
```
</section>
第三个 `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'
);
```
# --solutions--

View File

@ -1,19 +1,25 @@
---
id: 587d7fad367417b2b2512bdf
title: 添加坐标轴到可视化中
challengeType: 6
forumTopicId: 301472
title: 添加坐标轴到可视化中
---
## Description
<section id='description'>
# --description--
另一种改进散点图的方法是添加 x 轴和 y 轴。
D3 有两种方法来渲染 y 轴和 x 轴,分别是 <code>axisLeft</code><code>axisBottom</code>。下面是一个基于上个挑战中的 <code>xScale</code> 创建 x 轴的例子:
<code>const xAxis = d3.axisBottom(xScale);</code>
下一步是在 SVG 画布上渲染 x 轴。为此,你可以使用一个常见的 SVG 组件, <code>g</code> 元素,<code>g</code> 是英文中组(group)的缩写。
不同于 <code>rect</code><code>circle</code><code>text</code>,在渲染时,轴只是一条直线。因为它是一个简单的图形,所以可以用 <code>g</code>
最后一步是使用 <code>transforms</code> 属性将轴放置在 SVG 画布的正确位置上。否则,轴将会沿着 SVG 画布的边缘渲染,从而不可见。
SVG 支持多种 <code>transforms</code>,但是放置轴需要 <code>translate</code>。当它应用在 <code>g</code> 元素上时,它根据给出的总量移动整组。下面是一个例子:
D3 有两种方法来渲染 y 轴和 x 轴,分别是 `axisLeft``axisBottom`。下面是一个基于上个挑战中的 `xScale` 创建 x 轴的例子:
`const xAxis = d3.axisBottom(xScale);`
下一步是在 SVG 画布上渲染 x 轴。为此,你可以使用一个常见的 SVG 组件, `g` 元素,`g` 是英文中组(group)的缩写。
不同于 `rect``circle``text`,在渲染时,轴只是一条直线。因为它是一个简单的图形,所以可以用 `g`
最后一步是使用 `transforms` 属性将轴放置在 SVG 画布的正确位置上。否则,轴将会沿着 SVG 画布的边缘渲染,从而不可见。
SVG 支持多种 `transforms`,但是放置轴需要 `translate`。当它应用在 `g` 元素上时,它根据给出的总量移动整组。下面是一个例子:
```js
const xAxis = d3.axisBottom(xScale);
@ -23,175 +29,36 @@ svg.append("g")
.call(xAxis);
```
上部分代码将 x 轴放置在 SVG 画布的底端。然后 x 轴作为参数被传递给 <code>call</code> 方法
除了 <code>translate</code> 的参数是 (x,0) 格式的y 轴也是一样的。因为 <code>translate</code> 是上面 <code>attr</code> 方法中的一个字符串,你可以在参数中使用字符串的连接将变量值包括进去。
</section>
上部分代码将 x 轴放置在 SVG 画布的底端。然后 x 轴作为参数被传递给 `call` 方法。 除了 `translate` 的参数是 (x,0) 格式的y 轴也是一样的。因为 `translate` 是上面 `attr` 方法中的一个字符串,你可以在参数中使用字符串的连接将变量值包括进去
## Instructions
<section id='instructions'>
现在散点图有 x 轴了。用 <code>axisLeft</code> 方法在变量 <code>yAxis</code> 中创建 y 轴,然后用 <code>g</code> 元素渲染 y 轴。确保用 <code>transform</code> 属性将 y 轴向右平移 padding 个单位,向下平移 0 个单位。记得 <code>call()</code> y 轴。
</section>
# --instructions--
## Tests
<section id='tests'>
现在散点图有 x 轴了。用 `axisLeft` 方法在变量 `yAxis` 中创建 y 轴,然后用 `g` 元素渲染 y 轴。确保用 `transform` 属性将 y 轴向右平移 padding 个单位,向下平移 0 个单位。记得 `call()` y 轴。
```yml
tests:
- text: 你应该使用参数为 <code>yScale</code>的<code>axisLeft()</code> 方法。
testString: assert(code.match(/\.axisLeft\(yScale\)/g));
- text: y 轴的 <code>g</code>元素应该有一个<code>transform</code> 属性来将 y 轴平移( 600 )。
testString: assert($('g').eq(10).attr('transform').match(/translate\(60\s*?,\s*?0\)/g));
- text: 你应该调用(call) <code>yAxis</code> 。
testString: assert(code.match(/\.call\(\s*yAxis\s*\)/g));
# --hints--
你应该使用参数为 `yScale``axisLeft()` 方法。
```js
assert(code.match(/\.axisLeft\(yScale\)/g));
```
</section>
y 轴的 `g`元素应该有一个`transform` 属性来将 y 轴平移( 600 )。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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);
svg.append("g")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert(
$('g')
.eq(10)
.attr('transform')
.match(/translate\(60\s*?,\s*?0\)/g)
);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
你应该调用(call) `yAxis`
```js
assert(code.match(/\.call\(\s*yAxis\s*\)/g));
```
</section>
# --solutions--

View File

@ -1,99 +1,35 @@
---
id: 587d7fa7367417b2b2512bc8
title: 用 D3 添加 Class
challengeType: 6
forumTopicId: 301473
title: 用 D3 添加 Class
---
## Description
<section id='description'>
即使对小型 app 来说在 HTML 元素中大量使用内联样式表也十分难以管理。更方便的是给元素添加遵守 CSS 规则的类。D3 中的 <code>attr()</code> 方法可以给元素添加任何 HTML 属性,包括类名称。
<code>attr()</code> 方法和 <code>style()</code> 的使用方法一样。它以逗号分隔的键值对为参数使用回调函数。这里是一个给选中元素添加类名为 "container" 的例子:<code>selection.attr("class", "container");</code>
# --description--
即使对小型 app 来说在 HTML 元素中大量使用内联样式表也十分难以管理。更方便的是给元素添加遵守 CSS 规则的类。D3 中的 `attr()` 方法可以给元素添加任何 HTML 属性,包括类名称。
`attr()` 方法和 `style()` 的使用方法一样。它以逗号分隔的键值对为参数使用回调函数。这里是一个给选中元素添加类名为 "container" 的例子:`selection.attr("class", "container");`
注意当 "container" 元素改变或者添加一个 class 时,"class" 参数会保持不变。
</section>
## Instructions
<section id='instructions'>
在编辑器中添加 <code>attr()</code> 方法,给 <code>div</code> 元素添加类名 <code>bar</code>
</section>
# --instructions--
## Tests
<section id='tests'>
在编辑器中添加 `attr()` 方法,给 `div` 元素添加类名 `bar`
```yml
tests:
- text: 你的 <code>div</code>元素应该有一个<code>bar</code> 类。
testString: assert($('div').attr('class') == "bar");
- text: 你应该使用 <code>attr()</code> 方法。
testString: assert(code.match(/\.attr/g));
# --hints--
你的 `div`元素应该有一个`bar` 类。
```js
assert($('div').attr('class') == 'bar');
```
</section>
你应该使用 `attr()` 方法。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert(code.match(/\.attr/g));
```
</div>
# --solutions--
</section>
## Solution
<section id='solution'>
```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>
```
</section>

View File

@ -1,19 +1,26 @@
---
id: 587d7fa6367417b2b2512bc2
title: 用 D3 给文档添加元素
challengeType: 6
forumTopicId: 301474
title: 用 D3 给文档添加元素
---
## Description
<section id='description'>
# --description--
D3 有多种方法可以用来在文档中增加元素、修改元素。
<code>select()</code> 方法用来从文档中选择元素,它以你查询的元素名称作为参数,返回第一个符合条件的 HTML 节点。以下是一个例子:
<code>const anchor = d3.select("a");</code>
上面这个例子找到页面上的第一个 a 标签(锚标签),将它作为一个 HTML 节点保存在变量 <code>anchor</code> 中。你也可以用其他的方法选择页面上的元素。例子中的 "d3" 是对 D3 对象的引用,可以通过它来访问 D3 的方法。
还可以用 <code>append()</code><code>text()</code> 方法。
<code>append()</code> 方法以你想添加到文档中的元素作为参数,给选中的元素添加一个 HTML 节点,返回那个节点的句柄。
<code>text()</code> 方法既可以给节点设置新的文本,也可以获取节点的当前文本。 如果要设置文字内容,需要在圆括号中传入一个 string字符串类型的参数
`select()` 方法用来从文档中选择元素,它以你查询的元素名称作为参数,返回第一个符合条件的 HTML 节点。以下是一个例子:
`const anchor = d3.select("a");`
上面这个例子找到页面上的第一个 a 标签(锚标签),将它作为一个 HTML 节点保存在变量 `anchor` 中。你也可以用其他的方法选择页面上的元素。例子中的 "d3" 是对 D3 对象的引用,可以通过它来访问 D3 的方法
还可以用 `append()``text()` 方法。
`append()` 方法以你想添加到文档中的元素作为参数,给选中的元素添加一个 HTML 节点,返回那个节点的句柄。
`text()` 方法既可以给节点设置新的文本,也可以获取节点的当前文本。 如果要设置文字内容,需要在圆括号中传入一个 string字符串类型的参数。
下面是一个选择无序列表、添加列表项和文字的例子:
```js
@ -23,69 +30,48 @@ d3.select("ul")
```
在 D3 中可以使用英文句号将多个方法串联在一起执行多个操作。
</section>
## Instructions
<section id='instructions'>
使用 <code>select</code> 方法选择文本中的 <code>body</code> 标签。然后用 <code>append</code> 方法为它添加一个 <code>h1</code> 标签,同时在 <code>h1</code> 中添加文本 "Learning D3"。
</section>
# --instructions--
## Tests
<section id='tests'>
使用 `select` 方法选择文本中的 `body` 标签。然后用 `append` 方法为它添加一个 `h1` 标签,同时在 `h1` 中添加文本 "Learning D3"。
```yml
tests:
- text: 你的 <code>body</code> 元素应该包含元素 <code>h1</code>。
testString: assert($('body').children('h1').length == 1);
- text: "你的 <code>h1</code> 元素应该包含文本 'Learning D3'。"
testString: assert($('h1').text() == "Learning D3");
- text: 你应该能访问 <code>d3</code> 的对象。
testString: assert(code.match(/d3/g));
- text: 你应该使用 <code>select</code> 方法。
testString: assert(code.match(/\.select/g));
- text: 你应该使用 <code>append</code> 方法。
testString: assert(code.match(/\.append/g));
- text: 你应该使用 <code>text</code> 方法。
testString: assert(code.match(/\.text/g));
# --hints--
你的 `body` 元素应该包含元素 `h1`
```js
assert($('body').children('h1').length == 1);
```
</section>
你的 `h1` 元素应该包含文本 'Learning D3'。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<body>
<script>
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert($('h1').text() == 'Learning D3');
```
</div>
你应该能访问 `d3` 的对象。
</section>
## Solution
<section id='solution'>
```html
<body>
<script>
d3.select("body")
.append("h1")
.text("Learning D3")
</script>
</body>
```js
assert(code.match(/d3/g));
```
</section>
你应该使用 `select` 方法。
```js
assert(code.match(/\.select/g));
```
你应该使用 `append` 方法。
```js
assert(code.match(/\.append/g));
```
你应该使用 `text` 方法。
```js
assert(code.match(/\.text/g));
```
# --solutions--

View File

@ -1,84 +1,35 @@
---
id: 587d7fa7367417b2b2512bc6
title: 给元素添加内联样式
challengeType: 6
forumTopicId: 301475
title: 给元素添加内联样式
---
## Description
<section id='description'>
D3 可以使用 <code>style()</code> 方法为动态元素添加内联 CSS 样式表。
<code>style()</code> 方法以用逗号分隔的键值对作为参数。这里是一个将选中文本的颜色设为蓝色的例子:
<code>selection.style("color","blue");</code>
</section>
# --description--
## Instructions
<section id='instructions'>
在编辑器中添加 <code>style()</code> 方法,使所有显示的文本的 <code>font-family</code><code>verdana</code>
</section>
D3 可以使用 `style()` 方法为动态元素添加内联 CSS 样式表。
## Tests
<section id='tests'>
`style()` 方法以用逗号分隔的键值对作为参数。这里是一个将选中文本的颜色设为蓝色的例子:
```yml
tests:
- text: 你的 <code>h2</code> 元素的 <code>font-family</code> 应该为 verdana。
testString: assert($('h2').css('font-family') == 'verdana');
- text: 你应该使用 <code>style()</code> 方法。
testString: assert(code.match(/\.style/g));
`selection.style("color","blue");`
# --instructions--
在编辑器中添加 `style()` 方法,使所有显示的文本的 `font-family``verdana`
# --hints--
你的 `h2` 元素的 `font-family` 应该为 verdana。
```js
assert($('h2').css('font-family') == 'verdana');
```
</section>
你应该使用 `style()` 方法。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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>
```js
assert(code.match(/\.style/g));
```
</div>
# --solutions--
</section>
## Solution
<section id='solution'>
```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>
```
</section>

View File

@ -1,134 +1,80 @@
---
id: 587d7faa367417b2b2512bd2
title: 给 D3 元素添加标签
challengeType: 6
forumTopicId: 301476
title: 给 D3 元素添加标签
---
## Description
<section id='description'>
D3 允许使用 SVG 的 <code>text</code> 元素给图形元素贴标签,例如给条形图中的各组都贴上标签。
<code>rect</code> 元素类似,<code>text</code> 元素也需要 <code>x</code><code>y</code> 属性来指定其放置在 SVG 画布上的位置,它也需要能够获取数据来显示数据值。
关于如何给组贴标签D3 给了你很高的控制权。
</section>
# --description--
## Instructions
<section id='instructions'>
编辑器中的代码已经将数据绑定到每个新的 <code>text</code> 元素。首先,在 <code>svg</code> 中添加 <code>text</code> 节点。然后,添加 <code>x</code><code>y</code> 坐标属性,除了 <code>text</code><code>y</code> 值应该使标签比组的高 <code>y</code> 3 个单位,其余值的计算方法应该和 <code>rect</code> 中计算方法一样。最后,用 D3 的 <code>text()</code> 方法将标签的文本设置为和数据点相等的值。
<strong>提示</strong><br>关于标签比组高,想一想 <code>text</code><code>y</code> 值应该比组的 <code>y</code> 值大 3 还是小 3。
</section>
D3 允许使用 SVG 的 `text` 元素给图形元素贴标签,例如给条形图中的各组都贴上标签。
## Tests
<section id='tests'>
`rect` 元素类似,`text` 元素也需要 `x``y` 属性来指定其放置在 SVG 画布上的位置,它也需要能够获取数据来显示数据值。
```yml
tests:
- text: 第一个 <code>text</code> 元素应该有一个值为 12 的标签并且 <code>y</code> 值为 61。
testString: assert($('text').eq(0).text() == '12' && $('text').eq(0).attr('y') == '61');
- text: 第二个 <code>text</code> 元素应该有一个值为 31 的标签并且 <code>y</code> 值为 4。
testString: assert($('text').eq(1).text() == '31' && $('text').eq(1).attr('y') == '4');
- text: 第三个 <code>text</code> 元素应该有一个值为 22 的标签并且 <code>y</code> 值为 31。
testString: assert($('text').eq(2).text() == '22' && $('text').eq(2).attr('y') == '31');
- text: 第四个 <code>text</code> 元素应该有一个值为 17 的标签并且 <code>y</code> 值为 46。
testString: assert($('text').eq(3).text() == '17' && $('text').eq(3).attr('y') == '46');
- text: 第五个 <code>text</code> 元素应该有一个值为 25 的标签并且 <code>y</code> 值为 22。
testString: assert($('text').eq(4).text() == '25' && $('text').eq(4).attr('y') == '22');
- text: 第六个 <code>text</code> 元素应该有一个值为 18 的标签并且 <code>y</code> 值为 43。
testString: assert($('text').eq(5).text() == '18' && $('text').eq(5).attr('y') == '43');
- text: 第七个 <code>text</code> 元素应该有一个值为 29 的标签并且 <code>y</code> 值为 10。
testString: assert($('text').eq(6).text() == '29' && $('text').eq(6).attr('y') == '10');
- text: 第八个 <code>text</code> 元素应该有一个值为 14 的标签并且 <code>y</code> 值为 55。
testString: assert($('text').eq(7).text() == '14' && $('text').eq(7).attr('y') == '55');
- text: 第九个 <code>text</code> 元素应该有一个值为 9 的标签并且 <code>y</code> 值为 70。
testString: assert($('text').eq(8).text() == '9' && $('text').eq(8).attr('y') == '70');
关于如何给组贴标签D3 给了你很高的控制权。
```
# --instructions--
</section>
编辑器中的代码已经将数据绑定到每个新的 `text` 元素。首先,在 `svg` 中添加 `text` 节点。然后,添加 `x``y` 坐标属性,除了 `text``y` 值应该使标签比组的高 `y` 3 个单位,其余值的计算方法应该和 `rect` 中计算方法一样。最后,用 D3 的 `text()` 方法将标签的文本设置为和数据点相等的值。
## Challenge Seed
<section id='challengeSeed'>
**提示**
关于标签比组高,想一想 `text``y` 值应该比组的 `y` 值大 3 还是小 3。
<div id='html-seed'>
# --hints--
```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()
// 在下面添加你的代码
// 在上面添加你的代码
</script>
<body>
```
</div>
</section>
## Solution
<section id='solution'>
第一个 `text` 元素应该有一个值为 12 的标签并且 `y` 值为 61。
```js
<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>
assert($('text').eq(0).text() == '12' && $('text').eq(0).attr('y') == '61');
```
</section>
第二个 `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');
```
# --solutions--

View File

@ -1,158 +1,129 @@
---
id: 587d7fab367417b2b2512bd9
title: 向散点图的 Circles 添加标签
challengeType: 6
forumTopicId: 301477
title: 向散点图的 Circles 添加标签
---
## Description
<section id='description'>
# --description--
你可以添加文本为散点图中的点创建标签。
目标是显示以逗号分隔的值,分别为 <code>dataset</code> 中每个对象的第一个(<code>x</code>)和第二个(<code>y</code>)字段
<code>text</code> 节点需要 <code>x</code><code>y</code> 属性来指定放置在 SVG 画布中的位置。在这个挑战中,<code>y</code> 值(决定高度)可以用和 <code>circle</code><code>cy</code> 属性相同的值,<code>x</code> 值可以比 <code>circle</code><code>cx</code> 值稍微大一些,这样标签才是可见的并且被放置在散点的右边。
</section>
## Instructions
<section id='instructions'>
<code>text</code> 元素为散点图中的每个点创建标签。标签的文本应该为用一个逗号和一个空格分隔开的两个值,例如,第一个点的标签为 "34, 78"。设置 <code>x</code> 属性比 <code>circle</code><code>cx</code> 属性大 5 个单位,设置 <code>y</code> 属性和 <code>circle</code><code>cy</code> 属性相同。
</section>
目标是显示以逗号分隔的值,分别为 `dataset` 中每个对象的第一个(`x`)和第二个(`y`)字段
## Tests
<section id='tests'>
`text` 节点需要 `x``y` 属性来指定放置在 SVG 画布中的位置。在这个挑战中,`y` 值(决定高度)可以用和 `circle``cy` 属性相同的值,`x` 值可以比 `circle``cx` 值稍微大一些,这样标签才是可见的并且被放置在散点的右边。
```yml
tests:
- text: 你应该有 10 个 <code>text</code> 元素。
testString: assert($('text').length == 10);
- text: "第一个标签的文本应该为 '34, 78' <code>x</code> 值应该为 39 <code>y</code> 应该为 422。"
testString: assert($('text').eq(0).text() == '34, 78' && $('text').eq(0).attr('x') == '39' && $('text').eq(0).attr('y') == '422');
- text: "第二个标签的文本应该为 '109, 280' <code>x</code> 值应该为 114 <code>y</code> 应该为 220。"
testString: assert($('text').eq(1).text() == '109, 280' && $('text').eq(1).attr('x') == '114' && $('text').eq(1).attr('y') == '220');
- text: "第三个标签的文本应该为 '310, 120' <code>x</code> 值应该为 315 <code>y</code> 应该为 380。"
testString: assert($('text').eq(2).text() == '310, 120' && $('text').eq(2).attr('x') == '315' && $('text').eq(2).attr('y') == '380');
- text: "第四个标签的文本应该为 '79, 411' <code>x</code> 值应该为 84 <code>y</code> 应该为 89。"
testString: assert($('text').eq(3).text() == '79, 411' && $('text').eq(3).attr('x') == '84' && $('text').eq(3).attr('y') == '89');
- text: "第五个标签的文本应该为 '420, 220' <code>x</code> 值应该为 425 <code>y</code> 应该为 280。"
testString: assert($('text').eq(4).text() == '420, 220' && $('text').eq(4).attr('x') == '425' && $('text').eq(4).attr('y') == '280');
- text: "第六个标签的文本应该为 '233, 145' <code>x</code> 值应该为 238 <code>y</code> 应该为 355。"
testString: assert($('text').eq(5).text() == '233, 145' && $('text').eq(5).attr('x') == '238' && $('text').eq(5).attr('y') == '355');
- text: "第七个标签的文本应该为 '333, 96' <code>x</code> 值应该为 338 <code>y</code> 应该为 404。"
testString: assert($('text').eq(6).text() == '333, 96' && $('text').eq(6).attr('x') == '338' && $('text').eq(6).attr('y') == '404');
- text: "第八个标签的文本应该为 '222, 333' <code>x</code> 值应该为 227 <code>y</code> 应该为 167。"
testString: assert($('text').eq(7).text() == '222, 333' && $('text').eq(7).attr('x') == '227' && $('text').eq(7).attr('y') == '167');
- text: "第九个标签的文本应该为 '78, 320' <code>x</code> 值应该为 83 <code>y</code> 应该为 180。"
testString: assert($('text').eq(8).text() == '78, 320' && $('text').eq(8).attr('x') == '83' && $('text').eq(8).attr('y') == '180');
- text: "第十个标签的文本应该为 '21, 123' <code>x</code> 值应该为 26 <code>y</code> 应该为 377。"
testString: assert($('text').eq(9).text() == '21, 123' && $('text').eq(9).attr('x') == '26' && $('text').eq(9).attr('y') == '377');
# --instructions--
`text` 元素为散点图中的每个点创建标签。标签的文本应该为用一个逗号和一个空格分隔开的两个值,例如,第一个点的标签为 "34, 78"。设置 `x` 属性比 `circle``cx` 属性大 5 个单位,设置 `y` 属性和 `circle``cy` 属性相同。
# --hints--
你应该有 10 个 `text` 元素。
```js
assert($('text').length == 10);
```
</section>
第一个标签的文本应该为 '34, 78' `x` 值应该为 39 `y` 应该为 422。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert(
$('text').eq(0).text() == '34, 78' &&
$('text').eq(0).attr('x') == '39' &&
$('text').eq(0).attr('y') == '422'
);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第二个标签的文本应该为 '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'
);
```
</section>
第三个标签的文本应该为 '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'
);
```
# --solutions--

View File

@ -1,14 +1,15 @@
---
id: 587d7fa7367417b2b2512bc7
title: 根据数据更改样式
challengeType: 6
forumTopicId: 301479
title: 根据数据更改样式
---
## Description
<section id='description'>
D3 是关于可视化和展示数据的。如果你期望基于数据来改变元素的样式,你可以在 <code>style()</code> 方法中使用回调函数为不同元素改变样式。
例如,你想将值小于 20 的数据点设置为蓝色,其余设置为红色。你可以在 <code>style()</code> 方法中使用包含条件逻辑的回调函数。回调函数以 <code>d</code> 作为参数来表示一个数据点:
# --description--
D3 是关于可视化和展示数据的。如果你期望基于数据来改变元素的样式,你可以在 `style()` 方法中使用回调函数为不同元素改变样式。
例如,你想将值小于 20 的数据点设置为蓝色,其余设置为红色。你可以在 `style()` 方法中使用包含条件逻辑的回调函数。回调函数以 `d` 作为参数来表示一个数据点:
```js
selection.style("color", (d) => {
@ -16,90 +17,70 @@ selection.style("color", (d) => {
});
```
<code>style()</code> 方法不仅仅可以设置 <code>color</code>——它也适用于其他 CSS 属性。
</section>
`style()` 方法不仅仅可以设置 `color`——它也适用于其他 CSS 属性。
## Instructions
<section id='instructions'>
在编辑器中添加 <code>style()</code> 方法,根据条件设置 <code>h2</code> 元素的 <code>color</code> 属性。写一个回调函数,如果值小于 20 返回 "red",否则返回 "green"。
<strong>提示</strong><br>你可以使用 if-else 语句或者三目操作符。
</section>
# --instructions--
## Tests
<section id='tests'>
在编辑器中添加 `style()` 方法,根据条件设置 `h2` 元素的 `color` 属性。写一个回调函数,如果值小于 20 返回 "red",否则返回 "green"。
```yml
tests:
- text: 第一个 <code>h2</code> 的 <code>color</code> 应该为 red。
testString: assert($('h2').eq(0).css('color') == "rgb(255, 0, 0)");
- text: 第二个 <code>h2</code> 的 <code>color</code> 应该为 green。
testString: assert($('h2').eq(1).css('color') == "rgb(0, 128, 0)");
- text: 第三个 <code>h2</code> 的 <code>color</code> 应该为 green。
testString: assert($('h2').eq(2).css('color') == "rgb(0, 128, 0)");
- text: 第四个 <code>h2</code> 的 <code>color</code> 应该为 red。
testString: assert($('h2').eq(3).css('color') == "rgb(255, 0, 0)");
- text: 第五个 <code>h2</code> 的 <code>color</code> 应该为 green。
testString: assert($('h2').eq(4).css('color') == "rgb(0, 128, 0)");
- text: 第六个 <code>h2</code> 的 <code>color</code> 应该为 red。
testString: assert($('h2').eq(5).css('color') == "rgb(255, 0, 0)");
- text: 第七个 <code>h2</code> 的 <code>color</code> 应该为 green。
testString: assert($('h2').eq(6).css('color') == "rgb(0, 128, 0)");
- text: 第八个 <code>h2</code> 的 <code>color</code> 应该为 red。
testString: assert($('h2').eq(7).css('color') == "rgb(255, 0, 0)");
- text: 第九个 <code>h2</code> 的 <code>color</code> 应该为 red。
testString: assert($('h2').eq(8).css('color') == "rgb(255, 0, 0)");
**提示**
你可以使用 if-else 语句或者三目操作符。
# --hints--
第一个 `h2``color` 应该为 red。
```js
assert($('h2').eq(0).css('color') == 'rgb(255, 0, 0)');
```
</section>
第二个 `h2``color` 应该为 green。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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>
```js
assert($('h2').eq(1).css('color') == 'rgb(0, 128, 0)');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第三个 `h2``color` 应该为 green。
```js
assert($('h2').eq(2).css('color') == 'rgb(0, 128, 0)');
```
</section>
第四个 `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)');
```
# --solutions--

View File

@ -1,103 +1,27 @@
---
id: 587d7fa9367417b2b2512bd1
title: 更改 SVG 元素的颜色
challengeType: 6
forumTopicId: 301480
title: 更改 SVG 元素的颜色
---
## Description
<section id='description'>
# --description--
所有组都在正确的位置上了但是它们都是一样的黑色。SVG 可以改变组的颜色。
在 SVG 中, <code>rect</code> 图形用 <code>fill</code> 属性着色它支持十六进制代码、颜色名称、rgb 值以及更复杂的选项,比如渐变和透明。
</section>
## Instructions
<section id='instructions'>
添加 <code>attr()</code> 方法,将所有组的 "fill" 设置为 "navy"。
</section>
在 SVG 中, `rect` 图形用 `fill` 属性着色它支持十六进制代码、颜色名称、rgb 值以及更复杂的选项,比如渐变和透明。
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: 所有组的 <code>fill</code> 颜色都应该是 navy。
testString: assert($('rect').css('fill') == "rgb(0, 0, 128)");
添加 `attr()` 方法,将所有组的 "fill" 设置为 "navy"。
# --hints--
所有组的 `fill` 颜色都应该是 navy。
```js
assert($('rect').css('fill') == 'rgb(0, 0, 128)');
```
</section>
# --solutions--
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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>
```
</div>
</section>
## Solution
<section id='solution'>
```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>
```
</section>

View File

@ -1,114 +1,107 @@
---
id: 587d7fa8367417b2b2512bca
title: 更改条形图的显示方式
challengeType: 6
forumTopicId: 301481
title: 更改条形图的显示方式
---
## Description
<section id='description'>
# --description--
这里有一些格式的改变可以美化上个挑战中创建的条形图:
1) 通过在 CSS 中为 <code>bar</code> 的类添加 margin 属性,为每一组之间添加空格以直观的将它们分开
1) 通过在 CSS 中为 `bar` 的类添加 margin 属性,为每一组之间添加空格以直观的将它们分开
2) 通过给每个值乘以一个数来缩放高度,增加高度以更好地显示值的差异
</section>
## Instructions
<section id='instructions'>
首先,在 <code>style</code> 标签中为 <code>bar</code> 类添加 2px 的 <code>margin</code> 属性。然后,在 <code>style()</code> 方法中修改回调函数,使它返回 10 倍原数值的值(在后面加上 "px")。
<strong>提示</strong><br>通过给每一个数值点乘以<em>相同的</em>常量值仅仅改变比例。这就像放大,它不会改变底层数据的含义。
</section>
# --instructions--
## Tests
<section id='tests'>
首先,在 `style` 标签中为 `bar` 类添加 2px 的 `margin` 属性。然后,在 `style()` 方法中修改回调函数,使它返回 10 倍原数值的值(在后面加上 "px")。
```yml
tests:
- text: 第一个 <code>div</code> 的 <code>height</code> 应该为 120 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(0).css('height') == '120px' && $('div').eq(0).css('margin-right') == '2px');
- text: 第二个 <code>div</code> 的 <code>height</code> 应该为 310 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(1).css('height') == '310px' && $('div').eq(1).css('margin-right') == '2px');
- text: 第三个 <code>div</code> 的 <code>height</code> 应该为 220 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(2).css('height') == '220px' && $('div').eq(2).css('margin-right') == '2px');
- text: 第四个 <code>div</code> 的 <code>height</code> 应该为 170 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(3).css('height') == '170px' && $('div').eq(3).css('margin-right') == '2px');
- text: 第五个 <code>div</code> 的 <code>height</code> 应该为 250 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(4).css('height') == '250px' && $('div').eq(4).css('margin-right') == '2px');
- text: 第六个 <code>div</code> 的 <code>height</code> 应该为 180 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(5).css('height') == '180px' && $('div').eq(5).css('margin-right') == '2px');
- text: 第七个 <code>div</code> 的 <code>height</code> 应该为 290 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(6).css('height') == '290px' && $('div').eq(6).css('margin-right') == '2px');
- text: 第八个 <code>div</code> 的 <code>height</code> 应该为 140 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(7).css('height') == '140px' && $('div').eq(7).css('margin-right') == '2px');
- text: 第九个 <code>div</code> 的 <code>height</code> 应该为 90 个像素,<code>margin</code> 应该为 2 个像素。
testString: assert($('div').eq(8).css('height') == '90px' && $('div').eq(8).css('margin-right') == '2px');
**提示**
通过给每一个数值点乘以*相同的*常量值仅仅改变比例。这就像放大,它不会改变底层数据的含义。
# --hints--
第一个 `div``height` 应该为 120 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(0).css('height') == '120px' &&
$('div').eq(0).css('margin-right') == '2px'
);
```
</section>
第二个 `div``height` 应该为 310 个像素,`margin` 应该为 2 个像素。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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>
```js
assert(
$('div').eq(1).css('height') == '310px' &&
$('div').eq(1).css('margin-right') == '2px'
);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第三个 `div``height` 应该为 220 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(2).css('height') == '220px' &&
$('div').eq(2).css('margin-right') == '2px'
);
```
</section>
第四个 `div``height` 应该为 170 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(3).css('height') == '170px' &&
$('div').eq(3).css('margin-right') == '2px'
);
```
第五个 `div``height` 应该为 250 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(4).css('height') == '250px' &&
$('div').eq(4).css('margin-right') == '2px'
);
```
第六个 `div``height` 应该为 180 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(5).css('height') == '180px' &&
$('div').eq(5).css('margin-right') == '2px'
);
```
第七个 `div``height` 应该为 290 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(6).css('height') == '290px' &&
$('div').eq(6).css('margin-right') == '2px'
);
```
第八个 `div``height` 应该为 140 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(7).css('height') == '140px' &&
$('div').eq(7).css('margin-right') == '2px'
);
```
第九个 `div``height` 应该为 90 个像素,`margin` 应该为 2 个像素。
```js
assert(
$('div').eq(8).css('height') == '90px' &&
$('div').eq(8).css('margin-right') == '2px'
);
```
# --solutions--

View File

@ -1,14 +1,15 @@
---
id: 587d7fa8367417b2b2512bcd
title: 为集合中的每个数据点创建一个 Bar
challengeType: 6
forumTopicId: 301482
title: 为集合中的每个数据点创建一个 Bar
---
## Description
<section id='description'>
上个挑战仅仅在 <code>svg</code> 中添加了一个矩形来表示一组。接下来你将结合到目前为止所学的关于 <code>data()</code><code>enter()</code>、SVG 图形的知识,为 <code>dataset</code> 中的每一个数据点创建并且添加一个矩形。
之前的挑战展示了如何为 <code>dataset</code> 中的每个对象创建并添加一个 <code>div</code>
# --description--
上个挑战仅仅在 `svg` 中添加了一个矩形来表示一组。接下来你将结合到目前为止所学的关于 `data()``enter()`、SVG 图形的知识,为 `dataset` 中的每一个数据点创建并且添加一个矩形。
之前的挑战展示了如何为 `dataset` 中的每个对象创建并添加一个 `div`
```js
d3.select("body").selectAll("div")
@ -17,97 +18,37 @@ d3.select("body").selectAll("div")
.append("div")
```
<code>rect</code> 元素和 <code>div</code> 有一些不同,<code>rect</code> 必须添加在 <code>svg</code> 元素内,而不能直接添加在 <code>body</code> 内。同时,你需要告诉 D3 将 <code>rect</code> 放在 <code>svg</code> 区域的哪个位置。组的放置会在下一个挑战中讲到。
</section>
`rect` 元素和 `div` 有一些不同,`rect` 必须添加在 `svg` 元素内,而不能直接添加在 `body` 内。同时,你需要告诉 D3 将 `rect` 放在 `svg` 区域的哪个位置。组的放置会在下一个挑战中讲到。
## Instructions
<section id='instructions'>
<code>data()</code><code>enter()</code><code>append()</code> 方法为 <code>dataset</code> 中的每一个对象创建并添加一个 <code>rect</code> 。每一组都将直接显示在上一组的上面,将上一组覆盖,这将会在下一个挑战中得到修改。
</section>
# --instructions--
## Tests
<section id='tests'>
`data()``enter()``append()` 方法为 `dataset` 中的每一个对象创建并添加一个 `rect` 。每一组都将直接显示在上一组的上面,将上一组覆盖,这将会在下一个挑战中得到修改。
```yml
tests:
- text: 你的文档应该有 9 个 <code>rect</code> 元素。
testString: assert($('rect').length == 9);
- text: 你应该使用 <code>data()</code> 方法。
testString: assert(code.match(/\.data/g));
- text: 你应该使用 <code>enter()</code> 方法。
testString: assert(code.match(/\.enter/g));
- text: 你应该使用 <code>append()</code> 方法。
testString: assert(code.match(/\.append/g));
# --hints--
你的文档应该有 9 个 `rect` 元素。
```js
assert($('rect').length == 9);
```
</section>
你应该使用 `data()` 方法。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
.attr("x", 0)
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
```js
assert(code.match(/\.data/g));
```
</div>
</section>
## Solution
<section id='solution'>
```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>
你应该使用 `enter()` 方法。
```js
assert(code.match(/\.enter/g));
```
</section>
你应该使用 `append()` 方法。
```js
assert(code.match(/\.append/g));
```
# --solutions--

View File

@ -1,88 +1,49 @@
---
id: 587d7fab367417b2b2512bda
title: 用 D3 创建线性比例
challengeType: 6
forumTopicId: 301483
title: 用 D3 创建线性比例
---
## Description
<section id='description'>
# --description--
条形图和散点图都直接在 SVG 画布上绘制数据。但是,如果一组的高或者其中一个数据点比 SVG 的高或宽更大,它将跑到 SVG 区域外。
D3 中,比例尺可帮助布局数据。 <code>Scales</code> 是告诉程序如何将一组原始数据点映射到 SVG 画布上像素的函数。
D3 中,比例尺可帮助布局数据。 `Scales` 是告诉程序如何将一组原始数据点映射到 SVG 画布上像素的函数。
例如,假设你有一个 100x500 大小的 SVG 画布,你想为许多国家绘制国内生产总值(GDP)的图表。这组数据将在十亿美元或万亿美元的范围内。你给 D3 提供一种缩放方法告诉它如何将大的 GDP 值放置在 100x500 大小的区域。
你不太可能按原样绘制原始数据,在绘制之前,将整个数据集缩放,这样 <code>x</code><code>y</code> 值才适合你画布的宽高。
D3 有几种缩放类型。对于线性缩放(通常使用于定量数据),使用 D3 的 <code>scaleLinear()</code> 方法:
<code> const scale = d3.scaleLinear()</code>
你不太可能按原样绘制原始数据,在绘制之前,将整个数据集缩放,这样 `x``y` 值才适合你画布的宽高。
D3 有几种缩放类型。对于线性缩放(通常使用于定量数据),使用 D3 的 `scaleLinear()` 方法:
`const scale = d3.scaleLinear()`
默认情况下,比例尺使用一比一的比例,输出的值和输入的值相同。在后面的章节中将涉及如何改变默认比例。
</section>
## Instructions
<section id='instructions'>
改变 <code>scale</code> 变量的值创建线性缩放,然后将 <code>output</code> 变量设置为 <code>scale</code> 函数(参数为 50
</section>
# --instructions--
## Tests
<section id='tests'>
改变 `scale` 变量的值创建线性缩放,然后将 `output` 变量设置为 `scale` 函数(参数为 50
```yml
tests:
- text: <code>h2</code> 的文本应该为 50。
testString: assert($('h2').text() == '50');
- text: 你应该使用 <code>scaleLinear</code> 方法。
testString: assert(code.match(/\.scaleLinear/g));
- text: <code>output</code> 变量应该调用输入参数为 50 的 scale 的值。
testString: assert(output == 50 && code.match(/scale\(\s*?50\s*?\)/g));
# --hints--
`h2` 的文本应该为 50。
```js
assert($('h2').text() == '50');
```
</section>
你应该使用 `scaleLinear` 方法。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<body>
<script>
// 在下面添加你的代码
const scale = undefined; // 在这里创建 scale
const output = scale(); // 在这里用一个参数调用 scale
// 在上面添加你的代码
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
```js
assert(code.match(/\.scaleLinear/g));
```
</div>
</section>
## Solution
<section id='solution'>
```html
<body>
<script>
const scale = d3.scaleLinear();
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
`output` 变量应该调用输入参数为 50 的 scale 的值。
```js
assert(output == 50 && code.match(/scale\(\s*?50\s*?\)/g));
```
</section>
# --solutions--

View File

@ -1,117 +1,30 @@
---
id: 587d7fab367417b2b2512bd7
title: 使用 SVG Circles 创建散点图
challengeType: 6
forumTopicId: 301484
title: 使用 SVG Circles 创建散点图
---
## Description
<section id='description'>
散点图是另一种形式的可视化。它用圆圈来映射数据点,每个数据点有两个值,这两个值和 <code>x</code><code>y</code> 轴相关联,在可视化中用来给圆圈定位。
SVG 用 <code>circle</code> 标签来创建圆形,它和之前用来构建条形图的 <code>rect</code> 非常相像。
</section>
# --description--
## Instructions
<section id='instructions'>
使用 <code>data()</code><code>enter()</code><code>append()</code> 方法将 <code>dataset</code> 和新添加到 SVG 画布上的 <code>circle</code> 元素绑定起来。
<strong>注意</strong><br>circles 并不可见,因为我们还没有设置它们的属性。我们会在下一个挑战来设置它。
</section>
散点图是另一种形式的可视化。它用圆圈来映射数据点,每个数据点有两个值,这两个值和 `x``y` 轴相关联,在可视化中用来给圆圈定位。
## Tests
<section id='tests'>
SVG 用 `circle` 标签来创建圆形,它和之前用来构建条形图的 `rect` 非常相像。
```yml
tests:
- text: 你应该有 10 个 <code>circle</code> 元素。
testString: assert($('circle').length == 10);
# --instructions--
使用 `data()``enter()``append()` 方法将 `dataset` 和新添加到 SVG 画布上的 `circle` 元素绑定起来。
**注意**
circles 并不可见,因为我们还没有设置它们的属性。我们会在下一个挑战来设置它。
# --hints--
你应该有 10 个 `circle` 元素。
```js
assert($('circle').length == 10);
```
</section>
# --solutions--
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```
</div>
</section>
## Solution
<section id='solution'>
```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>
```
</section>

View File

@ -1,99 +1,57 @@
---
id: 587d7fa8367417b2b2512bcc
title: 用 SVG 显示形状
challengeType: 6
forumTopicId: 301485
title: 用 SVG 显示形状
---
## Description
<section id='description'>
上个挑战用给定的宽和高创建了一个 <code>svg</code> 元素,因为在它的 <code>style</code> 标签中有 <code>background-color</code>,所以它是可见的。这一段代码为给定的宽和高腾出空间。
下一步是在 <code>svg</code> 区域中创建图形。SVG 支持多种图形,比如矩形和圆形,并用它们来显示数据。例如,在条形图中一个矩形(<code>&lt;rect&gt;</code>SVG 图形可以创建一个组。
当把图形放入 <code>svg</code> 区域中时,你可以用 <code>x</code><code>y</code> 坐标来指定它的位置。起始点 (0,0) 是在左上角。<code>x</code> 正值将图形右移,<code>y</code> 正值将图形从原点下移
若要把一个图形放在上个挑战的 500x 100<code>svg</code> 中心,可将 <code>x</code> 坐标设置为 250<code>y</code> 坐标设置为 50。
SVG 的 <code>rect</code> 有四个属性。<code>x</code><code>y</code> 坐标指定图形放在 <code>svg</code> 区域的位置,<code>height</code><code>width</code> 指定图形大小。
</section>
# --description--
## Instructions
<section id='instructions'>
<code>append()</code> 方法给 <code>svg</code> 添加一个 <code>rect</code> 图形。将它的 <code>width</code> 属性设置为 25<code>height</code> 属性设置为 100<code>x</code><code>y</code> 属性都设置为 0。
</section>
上个挑战用给定的宽和高创建了一个 `svg` 元素,因为在它的 `style` 标签中有 `background-color`,所以它是可见的。这一段代码为给定的宽和高腾出空间。
## Tests
<section id='tests'>
下一步是在 `svg` 区域中创建图形。SVG 支持多种图形,比如矩形和圆形,并用它们来显示数据。例如,在条形图中一个矩形(`<rect>`SVG 图形可以创建一个组。
```yml
tests:
- text: 你的文档应该有 1 个 <code>rect</code> 元素。
testString: assert($('rect').length == 1);
- text: <code>rect</code> 元素的 <code>width</code> 属性应该为 25。
testString: assert($('rect').attr('width') == '25');
- text: <code>rect</code> 元素的 <code>height</code> 属性应该为 100。
testString: assert($('rect').attr('height') == '100');
- text: <code>rect</code> 元素的 <code>x</code> 属性应该为 0。
testString: assert($('rect').attr('x') == '0');
- text: <code>rect</code> 元素的 <code>y</code> 属性应该为 0。
testString: assert($('rect').attr('y') == '0');
当把图形放入 `svg` 区域中时,你可以用 `x``y` 坐标来指定它的位置。起始点 (0,0) 是在左上角。`x` 正值将图形右移,`y` 正值将图形从原点下移
若要把一个图形放在上个挑战的 500x 100`svg` 中心,可将 `x` 坐标设置为 250`y` 坐标设置为 50。
SVG 的 `rect` 有四个属性。`x``y` 坐标指定图形放在 `svg` 区域的位置,`height``width` 指定图形大小。
# --instructions--
`append()` 方法给 `svg` 添加一个 `rect` 图形。将它的 `width` 属性设置为 25`height` 属性设置为 100`x``y` 属性都设置为 0。
# --hints--
你的文档应该有 1 个 `rect` 元素。
```js
assert($('rect').length == 1);
```
</section>
`rect` 元素的 `width` 属性应该为 25。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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)
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert($('rect').attr('width') == '25');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
`rect` 元素的 `height` 属性应该为 100。
```js
assert($('rect').attr('height') == '100');
```
</section>
`rect` 元素的 `x` 属性应该为 0。
```js
assert($('rect').attr('x') == '0');
```
`rect` 元素的 `y` 属性应该为 0。
```js
assert($('rect').attr('y') == '0');
```
# --solutions--

View File

@ -1,13 +1,13 @@
---
id: 587d7fa9367417b2b2512bcf
title: 动态更改每个条的高度
challengeType: 6
forumTopicId: 301486
title: 动态更改每个条的高度
---
## Description
<section id='description'>
和动态设置 <code>x</code> 值一样,每组的高也可以被设置成数组中数据点的值。
# --description--
和动态设置 `x` 值一样,每组的高也可以被设置成数组中数据点的值。
```js
selection.attr("property", (d, i) => {
@ -18,113 +18,68 @@ selection.attr("property", (d, i) => {
})
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
改变 <code>height</code> 属性的回调函数,让它返回数据值乘以 3 的值。
<strong>提示</strong><br>记住,把所有数据点乘以相同的常数来对数据进行缩放(就像放大)。这有利于看清例子中每组之间的差异。
</section>
改变 `height` 属性的回调函数,让它返回数据值乘以 3 的值。
## Tests
<section id='tests'>
**提示**
记住,把所有数据点乘以相同的常数来对数据进行缩放(就像放大)。这有利于看清例子中每组之间的差异。
```yml
tests:
- text: 第一个 <code>rect</code> 的 <code>height</code> 应该为 36。
testString: assert($('rect').eq(0).attr('height') == '36');
- text: 第二个 <code>rect</code> 的 <code>height</code> 应该为 93。
testString: assert($('rect').eq(1).attr('height') == '93');
- text: 第三个 <code>rect</code> 的 <code>height</code> 应该为 66。
testString: assert($('rect').eq(2).attr('height') == '66');
- text: 第四个 <code>rect</code> 的 <code>height</code> 应该为 51。
testString: assert($('rect').eq(3).attr('height') == '51');
- text: 第五个 <code>rect</code> 的 <code>height</code> 应该为 75。
testString: assert($('rect').eq(4).attr('height') == '75');
- text: 第六个 <code>rect</code> 的 <code>height</code> 应该为 54。
testString: assert($('rect').eq(5).attr('height') == '54');
- text: 第七个 <code>rect</code> 的 <code>height</code> 应该为 87。
testString: assert($('rect').eq(6).attr('height') == '87');
- text: 第八个 <code>rect</code> 的 <code>height</code> 应该为 42。
testString: assert($('rect').eq(7).attr('height') == '42');
- text: 第九个 <code>rect</code> 的 <code>height</code> 应该为 27。
testString: assert($('rect').eq(8).attr('height') == '27');
# --hints--
第一个 `rect``height` 应该为 36。
```js
assert($('rect').eq(0).attr('height') == '36');
```
</section>
第二个 `rect``height` 应该为 93。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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) => {
// 在下面添加你的代码
// 在上面添加你的代码
});
</script>
</body>
```js
assert($('rect').eq(1).attr('height') == '93');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第三个 `rect``height` 应该为 66。
```js
assert($('rect').eq(2).attr('height') == '66');
```
</section>
第四个 `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');
```
# --solutions--

View File

@ -1,16 +1,19 @@
---
id: 587d7fa9367417b2b2512bce
title: 动态设置每个 Bar 的坐标
challengeType: 6
forumTopicId: 301487
title: 动态设置每个 Bar 的坐标
---
## Description
<section id='description'>
上个挑战在 <code>svg</code> 元素中为 <code>dataset</code> 的每一个数据点创建并且添加了一个矩形。其中一个矩形表示一组,但是它们相互重叠。
矩形的摆放是由 <code>x</code><code>y</code> 属性处理的,它们告诉 D3 在 <code>svg</code> 区域的哪个位置开始绘制图形。上个挑战将它们都设置为 0所以所有组都摆放在左上角。
对于条形图,所有组应该处于相同的垂直水平上,也就是说所有组的 <code>y</code> 值相同(为 0但是 <code>x</code> 值需要随着增添新的组而变化。注意 <code>x</code> 值越大图形就越靠近右边,所以当遍历 <code>dataset</code> 中的元素时,<code>x</code> 的值应该递增
D3 的 <code>attr()</code> 方法可接收一个回调函数来动态设置属性。这个回调函数有两个参数,一个是数据点本身(通常是 <code>d</code>),另一个是该数据点在数组中的下标,这个参数是可选的。下面是其格式:
# --description--
上个挑战在 `svg` 元素中为 `dataset` 的每一个数据点创建并且添加了一个矩形。其中一个矩形表示一组,但是它们相互重叠。
矩形的摆放是由 `x``y` 属性处理的,它们告诉 D3 在 `svg` 区域的哪个位置开始绘制图形。上个挑战将它们都设置为 0所以所有组都摆放在左上角
对于条形图,所有组应该处于相同的垂直水平上,也就是说所有组的 `y` 值相同(为 0但是 `x` 值需要随着增添新的组而变化。注意 `x` 值越大图形就越靠近右边,所以当遍历 `dataset` 中的元素时,`x` 的值应该递增。
D3 的 `attr()` 方法可接收一个回调函数来动态设置属性。这个回调函数有两个参数,一个是数据点本身(通常是 `d`),另一个是该数据点在数组中的下标,这个参数是可选的。下面是其格式:
```js
selection.attr("property", (d, i) => {
@ -21,114 +24,70 @@ selection.attr("property", (d, i) => {
})
```
值得注意的是,你不需要写 <code>for</code> 循环或者用 <code>forEach</code> 迭代数据集中的对象。<code>data()</code> 方法会解析数据集,任何链接在它后面的方法都会为数据集中的每个对象运行一次。
</section>
值得注意的是,你不需要写 `for` 循环或者用 `forEach` 迭代数据集中的对象。`data()` 方法会解析数据集,任何链接在它后面的方法都会为数据集中的每个对象运行一次。
## Instructions
<section id='instructions'>
改变 <code>x</code> 属性的回调函数,让它返回下标乘以 30 的值。
<strong>提示</strong><br>每组的宽为 25所以每次 <code>x</code> 增加 30 可在每组之间留出一些空隙。在这个例子中任何比 25 大的数也同样适用。
</section>
# --instructions--
## Tests
<section id='tests'>
改变 `x` 属性的回调函数,让它返回下标乘以 30 的值。
```yml
tests:
- text: 第一个 <code>rect</code> 的 <code>x</code> 应该为 0。
testString: assert($('rect').eq(0).attr('x') == '0');
- text: 第二个 <code>rect</code> 的 <code>x</code> 应该为 30。
testString: assert($('rect').eq(1).attr('x') == '30');
- text: 第三个 <code>rect</code> 的 <code>x</code> 应该为 60。
testString: assert($('rect').eq(2).attr('x') == '60');
- text: 第四个 <code>rect</code> 的 <code>x</code> 应该为 90。
testString: assert($('rect').eq(3).attr('x') == '90');
- text: 第五个 <code>rect</code> 的 <code>x</code> 应该为 120。
testString: assert($('rect').eq(4).attr('x') == '120');
- text: 第六个 <code>rect</code> 的 <code>x</code> 应该为 150。
testString: assert($('rect').eq(5).attr('x') == '150');
- text: 第七个 <code>rect</code> 的 <code>x</code> 应该为 180。
testString: assert($('rect').eq(6).attr('x') == '180');
- text: 第八个 <code>rect</code> 的 <code>x</code> 应该为 210。
testString: assert($('rect').eq(7).attr('x') == '210');
- text: 第九个 <code>rect</code> 的 <code>x</code> 应该为 240。
testString: assert($('rect').eq(8).attr('x') == '240');
**提示**
每组的宽为 25所以每次 `x` 增加 30 可在每组之间留出一些空隙。在这个例子中任何比 25 大的数也同样适用。
# --hints--
第一个 `rect``x` 应该为 0。
```js
assert($('rect').eq(0).attr('x') == '0');
```
</section>
第二个 `rect``x` 应该为 30。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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) => {
// 在下面添加你的代码
// 在上面添加你的代码
})
.attr("y", 0)
.attr("width", 25)
.attr("height", 100);
</script>
</body>
```js
assert($('rect').eq(1).attr('x') == '30');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第三个 `rect``x` 应该为 60。
```js
assert($('rect').eq(2).attr('x') == '60');
```
</section
第四个 `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');
```
# --solutions--

View File

@ -1,122 +1,84 @@
---
id: 587d7fa9367417b2b2512bd0
title: 反转 SVG 元素
challengeType: 6
forumTopicId: 301488
title: 反转 SVG 元素
---
## Description
<section id='description'>
# --description--
你可能已经注意到了常见的条形图像是把这个翻转或者颠倒过来。这是因为 SVG 的 (x, y) 坐标有些特别。
在 SVG 中,坐标轴的原点在左上角。<code>x</code> 坐标为 0 将图形放在 SVG 区域的左边缘,<code>y</code> 坐标为 0 将图形放在 SVG 区域的上边缘。<code>x</code> 值增大矩形将向右移动,<code>y</code> 值增大矩形将向下移动。
为了使条形图向上,需要改变 <code>y</code> 坐标计算的方式。这需要计算组的高度和 SVG 区域的总高度。
SVG 区域的高度为 100。如果在集合中一个数据点的值为 0这组将从 SVG 区域的最底端开始(而不是顶端)。为此,<code>y</code> 坐标的值应为 100。如果数据点的值为 1你将从 <code>y</code> 坐标为 100 开始来将这组设置在底端,然后需要考虑该组的高度为 1所以最终的 <code>y</code> 坐标将是 99。
<code>y</code> 坐标为 <code>y = heightOfSVG - heightOfBar</code> 会将条形图向上放置。
</section>
## Instructions
<section id='instructions'>
改变 <code>y</code> 属性的回调函数,让条形图向上放置。<code>height</code> 的值是 3 倍 <code>d</code> 的值。
<strong>提示</strong><br>通常,高度关系为 <code>y = h - m * d</code>,其中 <code>m</code> 是对数据点进行缩放的比例。
</section>
在 SVG 中,坐标轴的原点在左上角。`x` 坐标为 0 将图形放在 SVG 区域的左边缘,`y` 坐标为 0 将图形放在 SVG 区域的上边缘。`x` 值增大矩形将向右移动,`y` 值增大矩形将向下移动。
## Tests
<section id='tests'>
为了使条形图向上,需要改变 `y` 坐标计算的方式。这需要计算组的高度和 SVG 区域的总高度。
```yml
tests:
- text: 第一个 <code>rect</code> 的 <code>y</code> 值应该为 64。
testString: assert($('rect').eq(0).attr('y') == h - (dataset[0] * 3));
- text: 第二个 <code>rect</code> 的 <code>y</code> 值应该为 7。
testString: assert($('rect').eq(1).attr('y') == h - (dataset[1] * 3));
- text: 第三个 <code>rect</code> 的 <code>y</code> 值应该为 34。
testString: assert($('rect').eq(2).attr('y') == h - (dataset[2] * 3));
- text: 第四个 <code>rect</code> 的 <code>y</code> 值应该为 49。
testString: assert($('rect').eq(3).attr('y') == h - (dataset[3] * 3));
- text: 第五个 <code>rect</code> 的 <code>y</code> 值应该为 25。
testString: assert($('rect').eq(4).attr('y') == h - (dataset[4] * 3));
- text: 第六个 <code>rect</code> 的 <code>y</code> 值应该为 46。
testString: assert($('rect').eq(5).attr('y') == h - (dataset[5] * 3));
- text: 第七个 <code>rect</code> 的 <code>y</code> 值应该为 13。
testString: assert($('rect').eq(6).attr('y') == h - (dataset[6] * 3));
- text: 第八个 <code>rect</code> 的 <code>y</code> 值应该为 58。
testString: assert($('rect').eq(7).attr('y') == h - (dataset[7] * 3));
- text: 第九个 <code>rect</code> 的 <code>y</code> 值应该为 73。
testString: assert($('rect').eq(8).attr('y') == h - (dataset[8] * 3));
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);
```
</section>
第二个 `rect``y` 值应该为 7。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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) => {
// 在下面添加你的代码
// 在上面添加你的代码
})
.attr("width", 25)
.attr("height", (d, i) => 3 * d);
</script>
</body>
```js
assert($('rect').eq(1).attr('y') == h - dataset[1] * 3);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第三个 `rect``y` 值应该为 34。
```js
assert($('rect').eq(2).attr('y') == h - dataset[2] * 3);
```
</section>
第四个 `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);
```
# --solutions--

View File

@ -1,97 +1,46 @@
---
id: 587d7fa8367417b2b2512bcb
title: 了解 D3 中的 SVG
challengeType: 6
forumTopicId: 301489
title: 了解 D3 中的 SVG
---
## Description
<section id='description'>
SVG 是 <code>Scalable Vector Graphics</code> 的缩写。
# --description--
SVG 是 `Scalable Vector Graphics` 的缩写。
"scalable" 的意思是如果放大或缩小一个对象,它不会像素化。不管是在小的移动手机屏幕上还是在大的电视显示器上它都会随着显示系统缩放。
SVG 用于制作常见的几何图形。由于 D3 将数据映射成可视化表达,它用 SVG 来创建可视化的图形。网页上的 SVG 图形必须在 HTML 的 <code>svg</code> 标签中。
当使用相对单位(例如 <code>vh</code><code>vw</code> 或者百分比CSS 是可伸缩的。但是在实现数据可视化的时候 SVG 更加的灵活。
</section>
## Instructions
<section id='instructions'>
<code>append()</code><code>body</code> 加一个 <code>svg</code> 节点。分别使用 <code>attr()</code> 给这个 <code>svg</code> 一个 <code>width</code> 属性和一个 <code>height</code> 属性,并分别将它们设置为给定的常量 <code>w</code> 和给定的常量 <code>h</code>。你可以在输出中看见它,因为在 <code>style</code> 标签中它的 <code>background-color</code> 设置为 pink。
<strong>提示</strong><br> <code>width</code><code>height</code> 属性没有单位,它们是来定义缩放的。但无论怎么缩放,这个 <code>svg</code> 元素的宽高比永远是 5:1 。
</section>
SVG 用于制作常见的几何图形。由于 D3 将数据映射成可视化表达,它用 SVG 来创建可视化的图形。网页上的 SVG 图形必须在 HTML 的 `svg` 标签中。
## Tests
<section id='tests'>
当使用相对单位(例如 `vh``vw` 或者百分比CSS 是可伸缩的。但是在实现数据可视化的时候 SVG 更加的灵活。
```yml
tests:
- text: 你的文档应该有 1 个 <code>svg</code> 元素。
testString: assert($('svg').length == 1);
- text: <code>svg</code> 元素的 <code>width</code> 属性应该为 500。
testString: assert($('svg').attr('width') == '500'||$('svg').css('width') == '500px');
- text: <code>svg</code> 元素的 <code>height</code> 属性应该为 100。
testString: assert($('svg').attr('height') == '100'||$('svg').css('height') == '100px');
# --instructions--
`append()``body` 加一个 `svg` 节点。分别使用 `attr()` 给这个 `svg` 一个 `width` 属性和一个 `height` 属性,并分别将它们设置为给定的常量 `w` 和给定的常量 `h`。你可以在输出中看见它,因为在 `style` 标签中它的 `background-color` 设置为 pink。
**提示**
`width``height` 属性没有单位,它们是来定义缩放的。但无论怎么缩放,这个 `svg` 元素的宽高比永远是 5:1 。
# --hints--
你的文档应该有 1 个 `svg` 元素。
```js
assert($('svg').length == 1);
```
</section>
`svg` 元素的 `width` 属性应该为 500。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert($('svg').attr('width') == '500' || $('svg').css('width') == '500px');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
`svg` 元素的 `height` 属性应该为 100。
```js
assert($('svg').attr('height') == '100' || $('svg').css('height') == '100px');
```
</section>
# --solutions--

View File

@ -1,82 +1,45 @@
---
id: 587d7fa6367417b2b2512bc3
title: 用 D3 选择一组元素
challengeType: 6
forumTopicId: 301490
title: 用 D3 选择一组元素
---
## Description
<section id='description'>
<code>selectAll()</code> 方法选择一组元素。它以 HTML 节点数组的形式返回该文本中所有匹配所输入字符串的对象。以下是一个选择文本中所有锚标签的例子:
<code>const anchors = d3.selectAll("a");</code>
<code>select()</code> 方法一样,<code>selectAll()</code> 也支持链式调用,你可以在它之后调用其他方法。
</section>
# --description--
## Instructions
<section id='instructions'>
选择所有的 <code>li</code> 标签,通过 <code>.text()</code> 方法将它的文本改为 "list item" 。
</section>
`selectAll()` 方法选择一组元素。它以 HTML 节点数组的形式返回该文本中所有匹配所输入字符串的对象。以下是一个选择文本中所有锚标签的例子:
## Tests
<section id='tests'>
`const anchors = d3.selectAll("a");`
```yml
tests:
- text: "页面上应该有 3 个 <code>li</code> 元素,每个元素的文本内容应为 'list item'。大小写和空格必须一致。"
testString: assert($('li').text().match(/list item/g).length == 3);
- text: 你应该能访问 <code>d3</code> 的对象。
testString: assert(code.match(/d3/g));
- text: 你应该使用 <code>selectAll</code> 方法。
testString: assert(code.match(/\.selectAll/g));
`select()` 方法一样,`selectAll()` 也支持链式调用,你可以在它之后调用其他方法。
# --instructions--
选择所有的 `li` 标签,通过 `.text()` 方法将它的文本改为 "list item" 。
# --hints--
页面上应该有 3 个 `li` 元素,每个元素的文本内容应为 'list item'。大小写和空格必须一致。
```js
assert(
$('li')
.text()
.match(/list item/g).length == 3
);
```
</section>
你应该能访问 `d3` 的对象。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<body>
<ul>
<li>Example</li>
<li>Example</li>
<li>Example</li>
</ul>
<script>
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert(code.match(/d3/g));
```
</div>
</section>
## Solution
<section id='solution'>
```html
<body>
<ul>
<li>Example</li>
<li>Example</li>
<li>Example</li>
</ul>
<script>
d3.selectAll("li")
.text("list item")
</script>
</body>
你应该使用 `selectAll` 方法。
```js
assert(code.match(/\.selectAll/g));
```
</section>
# --solutions--

View File

@ -1,16 +1,19 @@
---
id: 587d7fac367417b2b2512bdb
title: 按比例设置域和范围
challengeType: 6
forumTopicId: 301491
title: 按比例设置域和范围
---
## Description
<section id='description'>
# --description--
默认情况下,比例尺使用同一关系(identity relationship),即输入值直接映射为输出值。但是比例尺可以更灵活更有趣。
假设有一个数据集范围为 50 到 480这是缩放的输入信息也被称为域(domain)。
你想沿着 10 个单位到 500 个单位的 <code>x</code> 轴映射这些点到 SVG 画布上。这是输出信息,也被称为范围(range)。
<code>domain()</code><code>range()</code> 方法设置缩放的值,它们都以至少有两个元素的数组为参数。下面是一个例子:
你想沿着 10 个单位到 500 个单位的 `x` 轴映射这些点到 SVG 画布上。这是输出信息,也被称为范围(range)。
`domain()``range()` 方法设置缩放的值,它们都以至少有两个元素的数组为参数。下面是一个例子:
```js
// 设置域
@ -27,78 +30,45 @@ d3.scaleLinear()
```
注意,比例尺使用了域和范围之间的线性关系来找出给定数字的输出值。域中的最小值(50)映射为范围中的最小值(10)。
</section>
## Instructions
<section id='instructions'>
创建一个比例尺,将它的域设置为 <code>[250, 500]</code>,范围设置为 <code>[10, 150]</code>
<strong>提示</strong><br>你可以将 <code>domain()</code><code>range()</code> 方法串联在 <code>scale</code> 变量后。
</section>
# --instructions--
## Tests
<section id='tests'>
创建一个比例尺,将它的域设置为 `[250, 500]`,范围设置为 `[10, 150]`
```yml
tests:
- text: 你应该使用 <code>domain()</code> 方法。
testString: assert(code.match(/\.domain/g));
- text: 比例尺的 <code>domain()</code> 应该设置为 <code>[250, 500]</code>。
testString: assert(JSON.stringify(scale.domain()) == JSON.stringify([250, 500]));
- text: 你应该使用 <code>range()</code> 方法。
testString: assert(code.match(/\.range/g));
- text: 比例尺的 <code>range()</code> 应该设置为 <code>[10, 150]</code>。
testString: assert(JSON.stringify(scale.range()) == JSON.stringify([10, 150]));
- text: <code>h2</code> 的文本应该为 -102。
testString: assert($('h2').text() == '-102');
**提示**
你可以将 `domain()``range()` 方法串联在 `scale` 变量后。
# --hints--
你应该使用 `domain()` 方法。
```js
assert(code.match(/\.domain/g));
```
</section>
比例尺的 `domain()` 应该设置为 `[250, 500]`
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<body>
<script>
// 在下面添加你的代码
const scale = d3.scaleLinear();
// 在上面添加你的代码
const output = scale(50);
d3.select("body")
.append("h2")
.text(output);
</script>
</body>
```js
assert(JSON.stringify(scale.domain()) == JSON.stringify([250, 500]));
```
</div>
</section>
## Solution
<section id='solution'>
```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>
你应该使用 `range()` 方法。
```js
assert(code.match(/\.range/g));
```
</section>
比例尺的 `range()` 应该设置为 `[10, 150]`
```js
assert(JSON.stringify(scale.range()) == JSON.stringify([10, 150]));
```
`h2` 的文本应该为 -102。
```js
assert($('h2').text() == '-102');
```
# --solutions--

View File

@ -1,122 +1,31 @@
---
id: 587d7faa367417b2b2512bd3
title: 给 D3 标签添加样式
challengeType: 6
forumTopicId: 301492
title: 给 D3 标签添加样式
---
## Description
<section id='description'>
D3 可以将样式添加到组标签中。<code>fill</code> 属性为 <code>text</code> 节点设置文本颜色,<code>style()</code> 方法设置其它样式的 CSS 规则,例如 "font-family"、"font-size"。
</section>
# --description--
## Instructions
<section id='instructions'>
<code>text</code> 元素的 <code>font-size</code> 设置为 25px文本颜色设置为 red。
</section>
D3 可以将样式添加到组标签中。`fill` 属性为 `text` 节点设置文本颜色,`style()` 方法设置其它样式的 CSS 规则,例如 "font-family"、"font-size"。
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: 所有标签的 <code>fill</code> 颜色应该是 red。
testString: assert($('text').css('fill') == 'rgb(255, 0, 0)');
- text: 所有标签的 <code>font-size</code> 应该为 25 个像素。
testString: assert($('text').css('font-size') == '25px');
`text` 元素的 `font-size` 设置为 25px文本颜色设置为 red。
# --hints--
所有标签的 `fill` 颜色应该是 red。
```js
assert($('text').css('fill') == 'rgb(255, 0, 0)');
```
</section>
所有标签的 `font-size` 应该为 25 个像素。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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)
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert($('text').css('font-size') == '25px');
```
</div>
# --solutions--
</section>
## Solution
<section id='solution'>
```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>
```
</section>

View File

@ -1,114 +1,81 @@
---
id: 587d7fa8367417b2b2512bc9
title: 动态更新元素的高度
challengeType: 6
forumTopicId: 301493
title: 动态更新元素的高度
---
## Description
<section id='description'>
# --description--
之前的挑战包括如何从数组中显示数据和如何添加 CSS 类。将这些课程的内容结合起来只需两步你就能创建出一个简单的条形图:
1) 为每一个数组中的数据点都创建一个 <code>div</code>
2) 为每<code>div</code> 动态分配高度值,在 <code>style()</code> 方法中使用回调函数将高度值设置为数据大小
1) 为每一个数组中的数据点都创建一个 `div`
2) 为每个 `div` 动态分配高度值,在 `style()` 方法中使用回调函数将高度值设置为数据大小
回想使用回调函数设置样式的格式:
<code>selection.style("cssProperty", (d) => d)</code>
</section>
## Instructions
<section id='instructions'>
在编辑器中添加 <code>style()</code> 方法给每个元素设置 <code>height</code> 属性。使用回调函数返回数据点的值加上字符串 "px"。
</section>
`selection.style("cssProperty", (d) => d)`
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: 第一个 <code>div</code> 的 <code>height</code> 应该为 12 个像素。
testString: assert($('div').eq(0)[0].style.height === '12px');
- text: 第二个 <code>div</code> 的 <code>height</code> 应该为 31 个像素。
testString: assert($('div').eq(1)[0].style.height === '31px');
- text: 第三个 <code>div</code> 的 <code>height</code> 应该为 22 个像素。
testString: assert($('div').eq(2)[0].style.height === '22px');
- text: 第四个 <code>div</code> 的 <code>height</code> 应该为 17 个像素。
testString: assert($('div').eq(3)[0].style.height === '17px');
- text: 第五个 <code>div</code> 的 <code>height</code> 应该为 25 个像素。
testString: assert($('div').eq(4)[0].style.height === '25px');
- text: 第六个 <code>div</code> 的 <code>height</code> 应该为 18 个像素。
testString: assert($('div').eq(5)[0].style.height === '18px');
- text: 第七个 <code>div</code> 的 <code>height</code> 应该为 29 个像素。
testString: assert($('div').eq(6)[0].style.height === '29px');
- text: 第八个 <code>div</code> 的 <code>height</code> 应该为 14 个像素。
testString: assert($('div').eq(7)[0].style.height === '14px');
- text: 第九个 <code>div</code> 的 <code>height</code> 应该为 9 个像素。
testString: assert($('div').eq(8)[0].style.height === '9px');
在编辑器中添加 `style()` 方法给每个元素设置 `height` 属性。使用回调函数返回数据点的值加上字符串 "px"。
# --hints--
第一个 `div``height` 应该为 12 个像素。
```js
assert($('div').eq(0)[0].style.height === '12px');
```
</section>
第二个 `div``height` 应该为 31 个像素。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert($('div').eq(1)[0].style.height === '31px');
```
</div>
第三个 `div``height` 应该为 22 个像素。
</section>
## Solution
<section id='solution'>
```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>
```js
assert($('div').eq(2)[0].style.height === '22px');
```
</section>
第四个 `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');
```
# --solutions--

View File

@ -1,207 +1,232 @@
---
id: 587d7fac367417b2b2512bde
title: 使用预定义的比例放置元素
challengeType: 6
forumTopicId: 301494
title: 使用预定义的比例放置元素
---
## Description
<section id='description'>
# --description--
当比例尺建立好后,是时候重新映射散点图了。比例尺就像操作函数一样,将 x 和 y 的原数据值变为适合并可在 SVG 画布上正确渲染的值。它们使数据在屏幕的布局区域内部。
用比例尺函数为 SVG 图形设置坐标属性值。这包括 <code>rect</code> 或者 <code>text</code> 元素的 <code>x</code><code>y</code> 属性,或者 <code>circles</code><code>cx</code><code>cy</code>。以下是一个例子:
用比例尺函数为 SVG 图形设置坐标属性值。这包括 `rect` 或者 `text` 元素的 `x``y` 属性,或者 `circles``cx``cy`。以下是一个例子:
```js
shape
.attr("x", (d) => xScale(d[0]))
```
比例尺设置图形坐标属性来将数据点放置在 SVG 画布上。当你显示实际数据值时,不用使用比例尺,例如,在提示框或标签中的 <code>text()</code> 方法。
</section>
比例尺设置图形坐标属性来将数据点放置在 SVG 画布上。当你显示实际数据值时,不用使用比例尺,例如,在提示框或标签中的 `text()` 方法。
## Instructions
<section id='instructions'>
使用 <code>xScale</code><code>yScale</code><code>circle</code><code>text</code> 图形放置在 SVG 画布上。对于 <code>circles</code>,使用比例尺设置 <code>cx</code><code>cy</code> 属性,半径为 5 个单位。
对于 <code>text</code> 元素,使用比例尺设置 <code>x</code><code>y</code> 属性。标签应该标注在点的右边,为此,在将 x 数据值传递给 <code>xScale</code> 之前要将它加上 10 个单位。
</section>
# --instructions--
## Tests
<section id='tests'>
使用 `xScale``yScale``circle``text` 图形放置在 SVG 画布上。对于 `circles`,使用比例尺设置 `cx``cy` 属性,半径为 5 个单位。
```yml
tests:
- text: 你应该有 10 个 <code>circle</code> 元素。
testString: assert($('circle').length == 10);
- text: 在使用比例尺后第一个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 91<code>cy</code> 值应该大约为 368。它的 <code>r</code> 值应该为 5。
testString: assert(Math.round($('circle').eq(0).attr('cx')) == '91' && Math.round($('circle').eq(0).attr('cy')) == '368' && $('circle').eq(0).attr('r') == '5');
- text: 在使用比例尺后第二个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 159<code>cy</code> 值应该大约为 181。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(1).attr('cx')) == '159' && Math.round($('circle').eq(1).attr('cy')) == '181' && $('circle').eq(1).attr('r') == '5');
- text: 在使用比例尺后第三个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 340<code>cy</code> 值应该大约为 329。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(2).attr('cx')) == '340' && Math.round($('circle').eq(2).attr('cy')) == '329' && $('circle').eq(2).attr('r') == '5');
- text: 在使用比例尺后第四个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 131<code>cy</code> 值应该大约为 60。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(3).attr('cx')) == '131' && Math.round($('circle').eq(3).attr('cy')) == '60' && $('circle').eq(3).attr('r') == '5');
- text: 在使用比例尺后第五个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 440<code>cy</code> 值应该大约为 237。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(4).attr('cx')) == '440' && Math.round($('circle').eq(4).attr('cy')) == '237' && $('circle').eq(4).attr('r') == '5');
- text: 在使用比例尺后第六个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 271<code>cy</code> 值应该大约为 306。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(5).attr('cx')) == '271' && Math.round($('circle').eq(5).attr('cy')) == '306' && $('circle').eq(5).attr('r') == '5');
- text: 在使用比例尺后第七个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 361<code>cy</code> 值应该大约为 351。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(6).attr('cx')) == '361' && Math.round($('circle').eq(6).attr('cy')) == '351' && $('circle').eq(6).attr('r') == '5');
- text: 在使用比例尺后第八个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 261<code>cy</code> 值应该大约为 132。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(7).attr('cx')) == '261' && Math.round($('circle').eq(7).attr('cy')) == '132' && $('circle').eq(7).attr('r') == '5');
- text: 在使用比例尺后第九个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 131<code>cy</code> 值应该大约为 144。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(8).attr('cx')) == '131' && Math.round($('circle').eq(8).attr('cy')) == '144' && $('circle').eq(8).attr('r') == '5');
- text: 在使用比例尺后第十个 <code>circle</code> 元素的 <code>cx</code> 值应该大约为 79<code>cy</code> 值应该大约为 326。它的 <code>r</code> 值也应该为 5。
testString: assert(Math.round($('circle').eq(9).attr('cx')) == '79' && Math.round($('circle').eq(9).attr('cy')) == '326' && $('circle').eq(9).attr('r') == '5');
- text: 你应该有 10 个 <code>text</code> 元素。
testString: assert($('text').length == 10);
- text: 在使用比例尺后第一个标签的 <code>x</code> 值应该大约为 100<code>y</code> 值应该大约为 368。
testString: assert(Math.round($('text').eq(0).attr('x')) == '100' && Math.round($('text').eq(0).attr('y')) == '368');
- text: 在使用比例尺后第二个标签的 <code>x</code> 值应该大约为 168<code>y</code> 值应该大约为 181。
testString: assert(Math.round($('text').eq(1).attr('x')) == '168' && Math.round($('text').eq(1).attr('y')) == '181');
- text: 在使用比例尺后第三个标签的 <code>x</code> 值应该大约为 350<code>y</code> 值应该大约为 329。
testString: assert(Math.round($('text').eq(2).attr('x')) == '350' && Math.round($('text').eq(2).attr('y')) == '329');
- text: 在使用比例尺后第四个标签的 <code>x</code> 值应该大约为 141<code>y</code> 值应该大约为 60。
testString: assert(Math.round($('text').eq(3).attr('x')) == '141' && Math.round($('text').eq(3).attr('y')) == '60');
- text: 在使用比例尺后第五个标签的 <code>x</code> 值应该大约为 449<code>y</code> 值应该大约为 237。
testString: assert(Math.round($('text').eq(4).attr('x')) == '449' && Math.round($('text').eq(4).attr('y')) == '237');
- text: 在使用比例尺后第六个标签的 <code>x</code> 值应该大约为 280<code>y</code> 值应该大约为 306。
testString: assert(Math.round($('text').eq(5).attr('x')) == '280' && Math.round($('text').eq(5).attr('y')) == '306');
- text: 在使用比例尺后第七个标签的 <code>x</code> 值应该大约为 370<code>y</code> 值应该大约为 351。
testString: assert(Math.round($('text').eq(6).attr('x')) == '370' && Math.round($('text').eq(6).attr('y')) == '351');
- text: 在使用比例尺后第八个标签的 <code>x</code> 值应该大约为 270<code>y</code> 值应该大约为 132。
testString: assert(Math.round($('text').eq(7).attr('x')) == '270' && Math.round($('text').eq(7).attr('y')) == '132');
- text: 在使用比例尺后第九个标签的 <code>x</code> 值应该大约为 140<code>y</code> 值应该大约为 144。
testString: assert(Math.round($('text').eq(8).attr('x')) == '140' && Math.round($('text').eq(8).attr('y')) == '144');
- text: 在使用比例尺后第十个标签的 <code>x</code> 值应该大约为 88<code>y</code> 值应该大约为 326。
testString: assert(Math.round($('text').eq(9).attr('x')) == '88' && Math.round($('text').eq(9).attr('y')) == '326');
对于 `text` 元素,使用比例尺设置 `x``y` 属性。标签应该标注在点的右边,为此,在将 x 数据值传递给 `xScale` 之前要将它加上 10 个单位。
# --hints--
你应该有 10 个 `circle` 元素。
```js
assert($('circle').length == 10);
```
</section>
在使用比例尺后第一个 `circle` 元素的 `cx` 值应该大约为 91`cy` 值应该大约为 368。它的 `r` 值应该为 5。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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")
// 在下面添加你的代码
// 在上面添加你的代码
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text((d) => (d[0] + ", "
+ d[1]))
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert(
Math.round($('circle').eq(0).attr('cx')) == '91' &&
Math.round($('circle').eq(0).attr('cy')) == '368' &&
$('circle').eq(0).attr('r') == '5'
);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
在使用比例尺后第二个 `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'
);
```
</section>
在使用比例尺后第三个 `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'
);
```
# --solutions--

View File

@ -1,16 +1,19 @@
---
id: 587d7fac367417b2b2512bdd
title: 使用动态比例
challengeType: 6
forumTopicId: 301495
title: 使用动态比例
---
## Description
<section id='description'>
D3 的 <code>min()</code><code>max()</code> 方法在设置比例尺时十分有用。
# --description--
D3 的 `min()``max()` 方法在设置比例尺时十分有用。
对于一个复杂的数据集,首要是设置比例尺,这样可视化才能适合 SVG 容器的宽和高。所有数据都应布局在 SVG 画布内部,这样它们在页面上才是可见的。
下面这个例子为散点图设置了 x 轴的比例尺。<code>domain()</code> 方法给比例尺传递关于散点图原数据值的信息,<code>range()</code> 方法给出在页面上进行可视化的实际空间信息。
这个例子domain 是从 0 到数据集中的最大值,它使用 <code>max()</code> 方法和基于数组中 x 值的回调函数。range 使用 SVG 画布的宽(<code>w</code>)并包含 padding这将在散点图和 SVG 画布边缘之间添加空隙
下面这个例子为散点图设置了 x 轴的比例尺。`domain()` 方法给比例尺传递关于散点图原数据值的信息,`range()` 方法给出在页面上进行可视化的实际空间信息
在这个例子中domain 是从 0 到数据集中的最大值,它使用 `max()` 方法和基于数组中 x 值的回调函数。range 使用 SVG 画布的宽(`w`)并包含 padding这将在散点图和 SVG 画布边缘之间添加空隙。
```js
const dataset = [
@ -35,127 +38,34 @@ const xScale = d3.scaleLinear()
.range([padding, w - padding]);
```
在一开始可能很难理解 padding。想象 x 轴是一条从 0 到 500 SVG 画布宽的值)的水平直线。在 <code>range()</code> 方法中包含 padding 使散点图沿着这条直线从 30 (而不是 0开始在 470 (而不是 500结束。
</section>
在一开始可能很难理解 padding。想象 x 轴是一条从 0 到 500 SVG 画布宽的值)的水平直线。在 `range()` 方法中包含 padding 使散点图沿着这条直线从 30 (而不是 0开始在 470 (而不是 500结束。
## Instructions
<section id='instructions'>
使用 <code>yScale</code> 变量创建一个线性的 y 轴比例尺。<code>domain</code> 应该从 0 开始到数据集中 y 的最大值range 应该使用 SVG 的高(<code>h</code>)并包含 padding。
<strong>提示</strong><br>记得正向布局。当你为 y 坐标设置 range 时大的值height 减去 padding是第一个参数小的值是第二个参数。
</section>
# --instructions--
## Tests
<section id='tests'>
使用 `yScale` 变量创建一个线性的 y 轴比例尺。`domain` 应该从 0 开始到数据集中 y 的最大值range 应该使用 SVG 的高(`h`)并包含 padding。
```yml
tests:
- text: <code>h2</code> 中的文本应该是 30。
testString: assert(output == 30 && $('h2').text() == '30');
- text: yScale 的 <code>domain()</code> 应该等于 <code>[0, 411]</code>。
testString: assert(JSON.stringify(yScale.domain()) == JSON.stringify([0, 411]));
- text: yScale 的 <code>range()</code> 应该等于 <code>[470, 30]</code>。
testString: assert(JSON.stringify(yScale.range()) == JSON.stringify([470, 30]));
**提示**
记得正向布局。当你为 y 坐标设置 range 时大的值height 减去 padding是第一个参数小的值是第二个参数。
# --hints--
`h2` 中的文本应该是 30。
```js
assert(output == 30 && $('h2').text() == '30');
```
</section>
yScale 的 `domain()` 应该等于 `[0, 411]`
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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;
// SVG 画布边缘和图形之间的padding
const padding = 30;
// 创建 x 和 y 的比例尺
const xScale = d3.scaleLinear()
.domain([0, d3.max(dataset, (d) => d[0])])
.range([padding, w - padding]);
// 在下面添加你的代码
const yScale = undefined;
// 在上面添加你的代码
const output = yScale(411); // 返回 30
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
```js
assert(JSON.stringify(yScale.domain()) == JSON.stringify([0, 411]));
```
</div>
</section>
## Solution
<section id='solution'>
```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>
yScale 的 `range()` 应该等于 `[470, 30]`
```js
assert(JSON.stringify(yScale.range()) == JSON.stringify([470, 30]));
```
</section>
# --solutions--

View File

@ -1,15 +1,17 @@
---
id: 587d7fac367417b2b2512bdc
title: 使用 d3.max 和 d3.min 函数在数据集中查找最小值和最大值
challengeType: 6
forumTopicId: 301496
title: 使用 d3.max 和 d3.min 函数在数据集中查找最小值和最大值
---
## Description
<section id='description'>
D3 的方法 <code>domain()</code><code>range()</code> 根据数据设置比例尺的信息。下面有几种更简单的方法。
# --description--
D3 的方法 `domain()``range()` 根据数据设置比例尺的信息。下面有几种更简单的方法。
通常当你设置域的时候,你会想用数据集中的最小值和最大值。尤其是在很大的数据集中,尝试手动的找到这些值可能会出错。
D3 有两个方法——<code>min()</code><code>max()</code> 来返回这些值。下面是一个例子:
D3 有两个方法——`min()``max()` 来返回这些值。下面是一个例子:
```js
const exampleData = [34, 234, 73, 90, 6, 52];
@ -17,9 +19,7 @@ d3.min(exampleData) // 返回 6
d3.max(exampleData) // 返回 234
```
像在散点图的例子中的 [x, y] 坐标对一样,数据集有可能嵌套数组。在这种情况下,你需要告诉 D3 怎么计算最大值和最小值。
辛运的是,<code>min()</code><code>max()</code> 都可以使用回调函数。
在下面这个例子中,回调函数的参数 <code>d</code> 是当前的内数组。回调函数需要从内数组中返回你想比较大小的元素x 还是 y 值)。下面是一个如何找到二维数组的最大值和最小值的例子:
像在散点图的例子中的 \[x, y] 坐标对一样,数据集有可能嵌套数组。在这种情况下,你需要告诉 D3 怎么计算最大值和最小值。 辛运的是,`min()``max()` 都可以使用回调函数。 在下面这个例子中,回调函数的参数 `d` 是当前的内数组。回调函数需要从内数组中返回你想比较大小的元素x 还是 y 值)。下面是一个如何找到二维数组的最大值和最小值的例子:
```js
const locationData = [[1, 7],[6, 3],[8, 3]];
@ -28,71 +28,26 @@ const minX = d3.min(locationData, (d) => d[0]);
// 在 168 中 minX 为 1
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
<code>positionData</code> 变量中保存一个三维数组。用 D3 的方法去找到数组中 z 坐标(第三个值)的最大值并将它保存在 <code>output</code> 变量中。
</section>
`positionData` 变量中保存一个三维数组。用 D3 的方法去找到数组中 z 坐标(第三个值)的最大值并将它保存在 `output` 变量中。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: <code>h2</code> 的文本应该为 8。
testString: assert(output == 8 && $('h2').text() == '8');
- text: 你应该使用 <code>max()</code> 方法。
testString: assert(code.match(/\.max/g), 'Your code should use the <code>max()</code> method.')
`h2` 的文本应该为 8。
```js
assert(output == 8 && $('h2').text() == '8');
```
</section>
你应该使用 `max()` 方法。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<body>
<script>
const positionData = [[1, 7, -4],[6, 3, 8],[2, 8, 3]]
// 在下面添加你的代码
const output = undefined; // 修改这一行
// 在上面添加你的代码
d3.select("body")
.append("h2")
.text(output)
</script>
</body>
```js
assert(
code.match(/\.max/g),
'Your code should use the <code>max()</code> method.'
);
```
</div>
# --solutions--
</section>
## Solution
<section id='solution'>
```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>
```
</section>

View File

@ -1,17 +1,21 @@
---
id: 587d7fa7367417b2b2512bc4
title: 使用 D3 中的数据
challengeType: 6
forumTopicId: 301497
title: 使用 D3 中的数据
---
## Description
<section id='description'>
# --description--
D3 是数据驱动的库,可以使用 D3 的方法将数组形式的数据显示在页面上。
第一步是让 D3 知道数据。<code>data</code> 方法选择连接着数据的 DOM 元素,数据集作为参数传递给该方法。
常见的方法是在文档中为数据集中的每一个数据创建一个元素,为此,你可以使用 D3 的 <code>enter()</code> 方法
<code>enter()</code><code>data()</code> 方法一起使用时,它把从页面中选择的元素和数据集中的元素作比较。如果页面中选择的元素较少则创建缺少的元素。
以下是一个选择 <code>ul</code> 元素并根据添加的数组创建新的列表项的例子。
第一步是让 D3 知道数据。`data` 方法选择连接着数据的 DOM 元素,数据集作为参数传递给该方法
常见的方法是在文档中为数据集中的每一个数据创建一个元素,为此,你可以使用 D3 的 `enter()` 方法
`enter()``data()` 方法一起使用时,它把从页面中选择的元素和数据集中的元素作比较。如果页面中选择的元素较少则创建缺少的元素。
以下是一个选择 `ul` 元素并根据添加的数组创建新的列表项的例子。
```html
<body>
@ -28,74 +32,40 @@ D3 是数据驱动的库,可以使用 D3 的方法将数组形式的数据显示
```
选择不存在的 li 元素似乎有些难以理解。事实上,这段代码先选择页面上的 ul 元素再选择所有的列表项——li它将返回空。然后data()方法接收数组作为参数并运行三次后面的代码每次对应数组中的一个对象。enter()方法发现页面中没有 li 元素,但是需要 3 个每个对应dataset中的一个对象。它将在 ul 中添加带有文本 "New item" 的 li 元素。
</section>
## Instructions
<section id='instructions'>
选择 <code>body</code> 节点,然后选择所有的 <code>h2</code> 元素。让 D3 为 <code>dataset</code> 数组中的每一个对象创建并添加文本为 "New Title" 的 <code>h2</code> 标签。你应该使用 <code>data()</code><code>enter()</code> 方法。
</section>
# --instructions--
## Tests
<section id='tests'>
选择 `body` 节点,然后选择所有的 `h2` 元素。让 D3 为 `dataset` 数组中的每一个对象创建并添加文本为 "New Title" 的 `h2` 标签。你应该使用 `data()``enter()` 方法。
```yml
tests:
- text: 你的文档应该有 9 个 <code>h2</code> 元素。
testString: assert($('h2').length == 9);
- text: "<code>h2</code> 元素中的文本应为 'New Title'。大小写和空格必须一致。"
testString: assert($('h2').text().match(/New Title/g).length == 9);
- text: 你应该使用 <code>data()</code> 方法。
testString: assert(code.match(/\.data/g));
- text: 你应该使用 <code>enter()</code> 方法。
testString: assert(code.match(/\.enter/g));
# --hints--
你的文档应该有 9 个 `h2` 元素。
```js
assert($('h2').length == 9);
```
</section>
`h2` 元素中的文本应为 'New Title'。大小写和空格必须一致。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<body>
<script>
const dataset = [12, 31, 22, 17, 25, 18, 29, 14, 9];
// 在下面添加你的代码
// 在上面添加你的代码
</script>
</body>
```js
assert(
$('h2')
.text()
.match(/New Title/g).length == 9
);
```
</div>
</section>
## Solution
<section id='solution'>
```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>
你应该使用 `data()` 方法。
```js
assert(code.match(/\.data/g));
```
</section>
你应该使用 `enter()` 方法。
```js
assert(code.match(/\.enter/g));
```
# --solutions--

View File

@ -1,99 +1,83 @@
---
id: 587d7fa7367417b2b2512bc5
title: 使用 D3 中的动态数据
challengeType: 6
forumTopicId: 301498
title: 使用 D3 中的动态数据
---
## Description
<section id='description'>
最后两个挑战涉及到使用 D3 的 <code>data()</code><code>enter()</code> 方法来动态展示数据。它们以数据集为参数,和 <code>append()</code> 方法一起使用,为数据集中的每一个元素对象创建一个 DOM 元素。
在之前的挑战中,你为 <code>dataset</code> 数组中的每一个对象创建了一个新的 <code>h2</code> 元素,但是它们的文本都是相同的 "New Title"。 这是因为你还没有使用和每个 <code>h2</code> 元素关联的数据。
<code>text()</code> 方法以字符串或者回调函数作为参数:
<code>selection.text((d) => d)</code>
上面这个例子中的参数 <code>d</code> 指关联数据集的一个对象。
以当前例子为例,第一个 <code>h2</code> 元素和 12 关联,第二个 <code>h2</code> 元素和 31 关联,第三个 <code>h2</code> 元素和 22 关联,以此类推。
</section>
# --description--
## Instructions
<section id='instructions'>
改变 <code>text()</code> 方法使得每个 <code>h2</code> 元素显示 <code>dataset</code> 数组中的对应值加上一个空格和 "USD"。例如,第一个标题应该为 "12 USD"。
</section>
最后两个挑战涉及到使用 D3 的 `data()``enter()` 方法来动态展示数据。它们以数据集为参数,和 `append()` 方法一起使用,为数据集中的每一个元素对象创建一个 DOM 元素。
## Tests
<section id='tests'>
在之前的挑战中,你为 `dataset` 数组中的每一个对象创建了一个新的 `h2` 元素,但是它们的文本都是相同的 "New Title"。 这是因为你还没有使用和每个 `h2` 元素关联的数据。
```yml
tests:
- text: "第一个 <code>h2<code> 的文本应该为 '12 USD'。"
testString: assert($('h2').eq(0).text() == "12 USD");
- text: "第二个 <code>h2<code> 的文本应该为 '31 USD'。"
testString: assert($('h2').eq(1).text() == "31 USD");
- text: "第三个 <code>h2<code> 的文本应该为 '22 USD'。"
testString: assert($('h2').eq(2).text() == "22 USD");
- text: "第四个 <code>h2<code> 的文本应该为 '17 USD'。"
testString: assert($('h2').eq(3).text() == "17 USD");
- text: "第五个 <code>h2<code> 的文本应该为 '25 USD'。"
testString: assert($('h2').eq(4).text() == "25 USD");
- text: "第六个 <code>h2<code> 的文本应该为 '18 USD'。"
testString: assert($('h2').eq(5).text() == "18 USD");
- text: "第七个 <code>h2<code> 的文本应该为 '29 USD'。"
testString: assert($('h2').eq(6).text() == "29 USD");
- text: "第八个 <code>h2<code> 的文本应该为 '14 USD'。"
testString: assert($('h2').eq(7).text() == "14 USD");
- text: "第九个 <code>h2<code> 的文本应该为 '9 USD'。"
testString: assert($('h2').eq(8).text() == "9 USD");
`text()` 方法以字符串或者回调函数作为参数:
`selection.text((d) => d)`
上面这个例子中的参数 `d` 指关联数据集的一个对象。
以当前例子为例,第一个 `h2` 元素和 12 关联,第二个 `h2` 元素和 31 关联,第三个 `h2` 元素和 22 关联,以此类推。
# --instructions--
改变 `text()` 方法使得每个 `h2` 元素显示 `dataset` 数组中的对应值加上一个空格和 "USD"。例如,第一个标题应该为 "12 USD"。
# --hints--
第一个 <code>h2<code> 的文本应该为 '12 USD'。
```js
assert($('h2').eq(0).text() == '12 USD');
```
</section>
第二个 <code>h2<code> 的文本应该为 '31 USD'。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```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>
```js
assert($('h2').eq(1).text() == '31 USD');
```
</div>
</section>
## Solution
<section id='solution'>
```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>
第三个 <code>h2<code> 的文本应该为 '22 USD'。
```js
assert($('h2').eq(2).text() == '22 USD');
```
</section>
第四个 <code>h2<code> 的文本应该为 '17 USD'。
```js
assert($('h2').eq(3).text() == '17 USD');
```
第五个 <code>h2<code> 的文本应该为 '25 USD'。
```js
assert($('h2').eq(4).text() == '25 USD');
```
第六个 <code>h2<code> 的文本应该为 '18 USD'。
```js
assert($('h2').eq(5).text() == '18 USD');
```
第七个 <code>h2<code> 的文本应该为 '29 USD'。
```js
assert($('h2').eq(6).text() == '29 USD');
```
第八个 <code>h2<code> 的文本应该为 '14 USD'。
```js
assert($('h2').eq(7).text() == '14 USD');
```
第九个 <code>h2<code> 的文本应该为 '9 USD'。
```js
assert($('h2').eq(8).text() == '9 USD');
```
# --solutions--