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,58 +1,52 @@
---
id: bd7168d8c242eddfaeb5bd13
title: 用条形图可视化数据
challengeType: 3
forumTopicId: 301464
title: 用条形图可视化数据
---
## Description
<section id='description'>
<strong>目标:</strong><a href='https://codepen.io' target='_blank'>CodePen.io</a> 上实现一个功能类似 <a href='https://codepen.io/freeCodeCamp/full/GrZVaM' target='_blank'>https://codepen.io/freeCodeCamp/full/GrZVaM</a> 的 App。
在满足以下<a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>需求</a>并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <a href='https://github.com/d3/d3/blob/master/API.md#axes-d3-axis' target='_blank'>https://github.com/d3/d3/blob/master/API.md#axes-d3-axis</a> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
<strong>需求 #1</strong>我的图表应该有一个具有<code>id="title"</code>属性的标题。
<strong>需求 #2</strong>我的图表应该有一个<code>g</code>元素作为 x 轴,并具有<code>id="x-axis"</code>属性
<strong>需求 #3</strong>我的图表应该有一个<code>g</code>元素作为 y 轴,并具有<code>id="y-axis"</code>属性。
<strong>需求 #4</strong>两个轴都应包含多个刻度标签,每个标签具有<code>class="tick"</code>属性
<strong>需求 #5</strong>在我的图表里,每个数据点都应该有一个具有<code>class="bar"</code>属性的<code>rect</code>元素来展示数据。
<strong>需求 #6</strong>每一栏应该具有包含日期的<code>data-date</code>属性以及包含 GDP 值的<code>data-gdp</code>属性。
<strong>需求 #7</strong>条形元素的<code>data-date</code>属性应与提供的数据的顺序相匹配。
<strong>需求 #8</strong>条形元素的<code>data-gdp</code>属性应与提供的数据的顺序相匹配
<strong>需求 #9</strong>每个条形元素的高度应准确地表示其数据所对应的 GDP 值。
<strong>需求 #10</strong><code>data-date</code>属性和它对应的条形元素应与 x 轴上的相应的值对齐。
<strong>需求 #11</strong><code>data-gdp</code>属性和它对应的条形元素应与 y 轴上的相应的值对齐。
<strong>需求 #12</strong>我可以将鼠标悬停在某个区域上,并查看具有<code>id="tooltip"</code>属性的提示框,它会显示有关该区域的更多信息
<strong>需求 #13</strong>我的提示框应该有一个<code>data-date</code>属性,它对应了当前激活区域的<code>data-date</code>属性。
以下是完成此项目所需的数据:<code>https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json</code>
你可以 fork <a href='https://codepen.io/freeCodeCamp/pen/MJjpwO' target='_blank'>这个 CodePen pen 项目</a>来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:<code>https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js</code>.
# --description--
**目标:** 在 [CodePen.io](https://codepen.io) 上实现一个功能类似 <https://codepen.io/freeCodeCamp/full/GrZVaM> 的 App。
在满足以下[需求](https://en.wikipedia.org/wiki/User_story)并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
**需求 #1** 我的图表应该有一个具有`id="title"`属性的标题。
**需求 #2** 我的图表应该有一个`g`元素作为 x 轴,并具有`id="x-axis"`属性。
**需求 #3** 我的图表应该有一个`g`元素作为 y 轴,并具有`id="y-axis"`属性
**需求 #4** 两个轴都应包含多个刻度标签,每个标签具有`class="tick"`属性
**需求 #5** 在我的图表里,每个数据点都应该有一个具有`class="bar"`属性的`rect`元素来展示数据
**需求 #6** 每一栏应该具有包含日期的`data-date`属性以及包含 GDP 值的`data-gdp`属性。
**需求 #7** 条形元素的`data-date`属性应与提供的数据的顺序相匹配。
**需求 #8** 条形元素的`data-gdp`属性应与提供的数据的顺序相匹配。
**需求 #9** 每个条形元素的高度应准确地表示其数据所对应的 GDP 值。
**需求 #10** `data-date`属性和它对应的条形元素应与 x 轴上的相应的值对齐。
**需求 #11** `data-gdp`属性和它对应的条形元素应与 y 轴上的相应的值对齐。
**需求 #12** 我可以将鼠标悬停在某个区域上,并查看具有`id="tooltip"`属性的提示框,它会显示有关该区域的更多信息。
**需求 #13** 我的提示框应该有一个`data-date`属性,它对应了当前激活区域的`data-date`属性。
以下是完成此项目所需的数据:`https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json`
你可以 fork [这个 CodePen pen 项目](https://codepen.io/freeCodeCamp/pen/MJjpwO)来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:`https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js`.
一旦你完成了本项目并且该项目所有测试运行通过,请提交项目的 URL。
</section>
## Instructions
<section id='instructions'>
# --hints--
</section>
## Tests
<section id='tests'>
# --solutions--
```yml
tests: []
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@ -1,56 +1,51 @@
---
id: 587d7fa6367417b2b2512bbf
title: 用地区分布图可视化数据
challengeType: 3
forumTopicId: 301465
title: 用地区分布图可视化数据
---
## Description
<section id='description'>
<strong>目标:</strong><a href='https://codepen.io' target='_blank'>CodePen.io</a> 上实现一个功能类似 <a href='https://codepen.io/freeCodeCamp/full/EZKqza' target='_blank'>https://codepen.io/freeCodeCamp/full/EZKqza</a> 的 App。
在满足以下<a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>需求</a>并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <a href='https://github.com/d3/d3/blob/master/API.md#axes-d3-axis' target='_blank'>https://github.com/d3/d3/blob/master/API.md#axes-d3-axis</a> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
<strong>需求 #1</strong>我的地区分布图应该有一个具有<code>id="title"</code>属性的标题。
<strong>需求 #2</strong>我的地区分布图应该有一个具有<code>id="description"</code>属性的描述内容
<strong>需求 #3</strong>我的地区分布图应该有一些州县来展示数据,这些州县应该具有<code>class="county"</code>属性。
<strong>需求 #4</strong>这些州县至少应该有 4 种不同的填充颜色
<strong>需求 #5</strong>我的每个州县都应该具有<code>data-fips</code><code>data-education</code>属性,分别包含他们相应的 fips 值和教育值。
<strong>需求 #6</strong>在我的地区分布图中,每一个提供的数据点都应该有一个对应的州县
<strong>需求 #7</strong>各个州县应该具有与样本数据匹配的 fips 值和教育值。
<strong>需求 #8</strong>我的地区分布图应该有一个具有<code>id="legend"</code>属性的图例
<strong>需求 #9</strong>这些图例至少应该使用 4 种不同的填充颜色。
<strong>需求 #10</strong>我可以将鼠标悬停在某个区域上,并查看具有<code>id="tooltip"</code>属性的提示框,它会显示有关该区域的更多信息
<strong>需求 #11</strong>我的提示框应该有一个<code>data-education</code>属性它对应了当前激活区域的code>data-education</code>属性。
以下是完成此项目所需的数据集:<br><ul><li><strong>US Education Data: </strong><code>https://raw.githubusercontent.com/no-stack-dub-sack/testable-projects-fcc/master/src/data/choropleth_map/for_user_education.json</code></li><li><strong>US County Data: </strong><code>https://raw.githubusercontent.com/no-stack-dub-sack/testable-projects-fcc/master/src/data/choropleth_map/counties.json</code></li></ul>
你可以 fork <a href='https://codepen.io/freeCodeCamp/pen/MJjpwO' target='_blank'>这个 CodePen pen 项目</a>来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:<code>https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js</code>.
# --description--
**目标:** 在 [CodePen.io](https://codepen.io) 上实现一个功能类似 <https://codepen.io/freeCodeCamp/full/EZKqza> 的 App。
在满足以下[需求](https://en.wikipedia.org/wiki/User_story)并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
**需求 #1** 我的地区分布图应该有一个具有`id="title"`属性的标题
**需求 #2** 我的地区分布图应该有一个具有`id="description"`属性的描述内容
**需求 #3** 我的地区分布图应该有一些州县来展示数据,这些州县应该具有`class="county"`属性
**需求 #4** 这些州县至少应该有 4 种不同的填充颜色
**需求 #5** 我的每个州县都应该具有`data-fips``data-education`属性,分别包含他们相应的 fips 值和教育值。
**需求 #6** 在我的地区分布图中,每一个提供的数据点都应该有一个对应的州县。
**需求 #7** 各个州县应该具有与样本数据匹配的 fips 值和教育值。
**需求 #8** 我的地区分布图应该有一个具有`id="legend"`属性的图例。
**需求 #9** 这些图例至少应该使用 4 种不同的填充颜色。
**需求 #10** 我可以将鼠标悬停在某个区域上,并查看具有`id="tooltip"`属性的提示框,它会显示有关该区域的更多信息。
**需求 #11** 我的提示框应该有一个`data-education`属性它对应了当前激活区域的code>data-education属性。
以下是完成此项目所需的数据集:
- **US Education Data:** `https://raw.githubusercontent.com/no-stack-dub-sack/testable-projects-fcc/master/src/data/choropleth_map/for_user_education.json`
- **US County Data:** `https://raw.githubusercontent.com/no-stack-dub-sack/testable-projects-fcc/master/src/data/choropleth_map/counties.json`
你可以 fork [这个 CodePen pen 项目](https://codepen.io/freeCodeCamp/pen/MJjpwO)来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:`https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js`.
一旦你完成了本项目并且该项目所有测试运行通过,请提交项目的 URL。
</section>
## Instructions
<section id='instructions'>
# --hints--
</section>
## Tests
<section id='tests'>
# --solutions--
```yml
tests: []
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@ -1,62 +1,60 @@
---
id: bd7188d8c242eddfaeb5bd13
title: 用热图可视化数据
challengeType: 3
forumTopicId: 301466
title: 用热图可视化数据
---
## Description
<section id='description'>
<strong>目标:</strong><a href='https://codepen.io' target='_blank'>CodePen.io</a> 上实现一个功能类似 <a href='https://codepen.io/freeCodeCamp/full/JEXgeY' target='_blank'>https://codepen.io/freeCodeCamp/full/JEXgeY</a> 的 App。
在满足以下<a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>需求</a>并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <a href='https://github.com/d3/d3/blob/master/API.md#axes-d3-axis' target='_blank'>https://github.com/d3/d3/blob/master/API.md#axes-d3-axis</a> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
<strong>需求 #1</strong>我的热度图应该有一个具有<code>id="title"</code>属性的标题。
<strong>需求 #2</strong>我的热度图应该有一个具有<code>id="title"</code>属性的描述内容
<strong>需求 #3</strong>我的热度图应该有一个具有<code>id="x-axis"</code>属性的 x 轴。
<strong>需求 #4</strong>我的热度图应该有一个具有<code>id="y-axis"</code>属性的 y 轴
<strong>需求 #5</strong>我的热度图应该有一些<code>rect</code>元素来展示数据,他们具有<code>class="cell"</code>属性。
<strong>需求 #6</strong>这些单元格元素至少应该有 4 种不同的填充颜色
<strong>需求 #7</strong>每个单元格元素都有这些属性<code>data-month</code><code>data-year</code><code>data-temp</code>,包含了它们相应的月份,年份和温度值。
<strong>需求 #8</strong>每个元素的<code>data-month</code><code>data-year</code>属性应该在数据范围内
<strong>需求 #9</strong>我的热度图应该具有与 y 轴上的相应月份对齐的单元格。
<strong>需求 #10</strong>我的热度图应该具有与 x 轴上相应年份对齐的单元格
<strong>需求 #11</strong>我的热度图应该在 y 轴上有多个刻度标签,并带有完整的月份名称。
<strong>需求 #12</strong>我的热度图应该在 x 轴上有多个刻度标签,年份在 1754 到 2015 之间
<strong>需求 #13</strong>我的热度图应该有一个具有<code>id="legend"</code>属性的图例。
<strong>需求 #14</strong>我的图例应该包含一些<code>rect</code>元素
<strong>需求 #15</strong>图例中的这些<code>rect</code>元素应该至少使用 4 种不同的填充颜色。
<strong>需求 #16</strong>我可以将鼠标悬停在某个区域上,并查看具有<code>id="tooltip"</code>属性的提示框,它会显示有关该区域的更多信息
<strong>需求 #17</strong>我的提示框应该有一个<code>data-year</code>属性,它对应了当前激活区域的<code>data-year</code>属性。
以下是完成此项目所需的数据:<code>https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json</code>
你可以 fork <a href='https://codepen.io/freeCodeCamp/pen/MJjpwO' target='_blank'>这个 CodePen pen 项目</a>来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:<code>https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js</code>.
# --description--
**目标:** 在 [CodePen.io](https://codepen.io) 上实现一个功能类似 <https://codepen.io/freeCodeCamp/full/JEXgeY> 的 App。
在满足以下[需求](https://en.wikipedia.org/wiki/User_story)并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
**需求 #1** 我的热度图应该有一个具有`id="title"`属性的标题
**需求 #2** 我的热度图应该有一个具有`id="title"`属性的描述内容
**需求 #3** 我的热度图应该有一个具有`id="x-axis"`属性的 x 轴
**需求 #4** 我的热度图应该有一个具有`id="y-axis"`属性的 y 轴
**需求 #5** 我的热度图应该有一些`rect`元素来展示数据,他们具有`class="cell"`属性
**需求 #6** 这些单元格元素至少应该有 4 种不同的填充颜色
**需求 #7** 每个单元格元素都有这些属性`data-month``data-year``data-temp`,包含了它们相应的月份,年份和温度值
**需求 #8** 每个元素的`data-month``data-year`属性应该在数据范围内。
**需求 #9** 我的热度图应该具有与 y 轴上的相应月份对齐的单元格。
**需求 #10** 我的热度图应该具有与 x 轴上相应年份对齐的单元格。
**需求 #11** 我的热度图应该在 y 轴上有多个刻度标签,并带有完整的月份名称。
**需求 #12** 我的热度图应该在 x 轴上有多个刻度标签,年份在 1754 到 2015 之间。
**需求 #13** 我的热度图应该有一个具有`id="legend"`属性的图例。
**需求 #14** 我的图例应该包含一些`rect`元素。
**需求 #15** 图例中的这些`rect`元素应该至少使用 4 种不同的填充颜色。
**需求 #16** 我可以将鼠标悬停在某个区域上,并查看具有`id="tooltip"`属性的提示框,它会显示有关该区域的更多信息。
**需求 #17** 我的提示框应该有一个`data-year`属性,它对应了当前激活区域的`data-year`属性。
以下是完成此项目所需的数据:`https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/global-temperature.json`
你可以 fork [这个 CodePen pen 项目](https://codepen.io/freeCodeCamp/pen/MJjpwO)来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:`https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js`.
一旦你完成了本项目并且该项目所有测试运行通过,请提交项目的 URL。
</section>
## Instructions
<section id='instructions'>
# --hints--
</section>
## Tests
<section id='tests'>
# --solutions--
```yml
tests: []
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@ -1,60 +1,56 @@
---
id: bd7178d8c242eddfaeb5bd13
title: 用散点图可视化数据
challengeType: 3
forumTopicId: 301467
title: 用散点图可视化数据
---
## Description
<section id='description'>
<strong>目标:</strong><a href='https://codepen.io' target='_blank'>CodePen.io</a> 上实现一个功能类似 <a href='https://codepen.io/freeCodeCamp/full/bgpXyK' target='_blank'>https://codepen.io/freeCodeCamp/full/bgpXyK</a> 的 App。
在满足以下<a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>需求</a>并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <a href='https://github.com/d3/d3/blob/master/API.md#axes-d3-axis' target='_blank'>https://github.com/d3/d3/blob/master/API.md#axes-d3-axis</a> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
<strong>需求 #1</strong>我能看到一个具有<code>id="title"</code>属性的标题元素。
<strong>需求 #2</strong>我能看到一个具有<code>id="x-axis"</code>属性的 x 轴
<strong>需求 #3</strong>我能看到一个具有<code>id="y-axis"</code>属性的 y 轴。
<strong>需求 #4</strong>我可以看到一些点,每个点都有一个值为<code>dot</code>的 class 属性,它代表了被绘制的数据
<strong>需求 #5</strong>每个点都应具有<code>data-xvalue</code>属性和<code>data-yvalue</code>属性,其中包含相应的 x 和 y 值。
<strong>需求 #6</strong>每个点的<code>data-xvalue</code>属性和<code>data-yvalue</code>属性应该在实际数据的范围内,并且数据格式应该正确无误。对于<code>data-xvalue</code>属性,可以接受整数(全年)或 Date 对象进行测试评估。对于<code>data-yvalue</code>属性(分钟),请使用 Date 对象
<strong>需求 #7</strong><code>data-xvalue</code>属性和它对应的点应该和 x 轴上的点或值对齐。
<strong>需求 #8</strong><code>data-yvalue</code>属性和它对应的点应该和 y 轴上的点或值对齐
<strong>需求 #9</strong>我可以在 y 轴上看到多个时间格式为<code>%M:%S</code>的刻度标签。
<strong>需求 #10</strong>我可以在 x 轴上看到显示年份的多个刻度标签
<strong>需求 #11</strong>我可以看到 x 轴标签的范围在实际 x 轴数据的范围内。
<strong>需求 #12</strong>我可以看到 y 轴标签的范围在实际 y 轴数据的范围内
<strong>需求 #13</strong>我可以看到一个包含描述性文字的图例,它具有<code>id="legend"</code>属性。
<strong>需求 #14</strong>我可以将鼠标悬停在某个区域上,并查看具有<code>id="tooltip"</code>属性的提示框,它会显示有关该区域的更多信息
<strong>需求 #15</strong>我的提示框应该有一个<code>data-year</code>属性,它对应了当前激活区域的<code>data-xvalue</code>属性。
以下是完成此项目所需的数据:<code>https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json</code>
你可以 fork <a href='https://codepen.io/freeCodeCamp/pen/MJjpwO' target='_blank'>这个 CodePen pen 项目</a>来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:<code>https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js</code>.
# --description--
**目标:** 在 [CodePen.io](https://codepen.io) 上实现一个功能类似 <https://codepen.io/freeCodeCamp/full/bgpXyK> 的 App。
在满足以下[需求](https://en.wikipedia.org/wiki/User_story)并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
**需求 #1** 我能看到一个具有`id="title"`属性的标题元素
**需求 #2** 我能看到一个具有`id="x-axis"`属性的 x 轴
**需求 #3** 我能看到一个具有`id="y-axis"`属性的 y 轴
**需求 #4** 我可以看到一些点,每个点都有一个值为`dot`的 class 属性,它代表了被绘制的数据
**需求 #5** 每个点都应具有`data-xvalue`属性和`data-yvalue`属性,其中包含相应的 x 和 y 值
**需求 #6** 每个点的`data-xvalue`属性和`data-yvalue`属性应该在实际数据的范围内,并且数据格式应该正确无误。对于`data-xvalue`属性,可以接受整数(全年)或 Date 对象进行测试评估。对于`data-yvalue`属性(分钟),请使用 Date 对象
**需求 #7** `data-xvalue`属性和它对应的点应该和 x 轴上的点或值对齐。
**需求 #8** `data-yvalue`属性和它对应的点应该和 y 轴上的点或值对齐。
**需求 #9** 我可以在 y 轴上看到多个时间格式为`%M:%S`的刻度标签。
**需求 #10** 我可以在 x 轴上看到显示年份的多个刻度标签。
**需求 #11** 我可以看到 x 轴标签的范围在实际 x 轴数据的范围内。
**需求 #12** 我可以看到 y 轴标签的范围在实际 y 轴数据的范围内。
**需求 #13** 我可以看到一个包含描述性文字的图例,它具有`id="legend"`属性。
**需求 #14** 我可以将鼠标悬停在某个区域上,并查看具有`id="tooltip"`属性的提示框,它会显示有关该区域的更多信息。
**需求 #15** 我的提示框应该有一个`data-year`属性,它对应了当前激活区域的`data-xvalue`属性。
以下是完成此项目所需的数据:`https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/cyclist-data.json`
你可以 fork [这个 CodePen pen 项目](https://codepen.io/freeCodeCamp/pen/MJjpwO)来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:`https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js`.
一旦你完成了本项目并且该项目所有测试运行通过,请提交项目的 URL。
</section>
## Instructions
<section id='instructions'>
# --hints--
</section>
## Tests
<section id='tests'>
# --solutions--
```yml
tests: []
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

View File

@ -1,56 +1,52 @@
---
id: 587d7fa6367417b2b2512bc0
title: 用树形图可视化数据
challengeType: 3
forumTopicId: 301468
title: 用树形图可视化数据
---
## Description
<section id='description'>
<strong>目标:</strong><a href='https://codepen.io' target='_blank'>CodePen.io</a> 上实现一个功能类似 <a href='https://codepen.io/freeCodeCamp/full/KaNGNR' target='_blank'>https://codepen.io/freeCodeCamp/full/KaNGNR</a> 的 App。
在满足以下<a href='https://en.wikipedia.org/wiki/User_story' target='_blank'>需求</a>并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app。
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <a href='https://github.com/d3/d3/blob/master/API.md#axes-d3-axis' target='_blank'>https://github.com/d3/d3/blob/master/API.md#axes-d3-axis</a> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
<strong>需求 #1</strong>我的矩阵树图应该有一个具有<code>id="title"</code>属性的标题。
<strong>需求 #2</strong>我的矩阵树图应该有一个具有<code>id="description"</code>属性的描述内容
<strong>需求 #3</strong>我的矩阵树图应该有一些具有<code>class="tile"</code>属性的<code>rect</code>元素来展示数据。
<strong>需求 #4</strong>这些矩形块元素至少应该有 2 种不同的填充颜色
<strong>需求 #5</strong>每一块矩形元素应该具有<code>data-name</code><code>data-category</code>,以及<code>data-value</code>这些属性,包含了它们相应的名称,分类,以及数值。
<strong>需求 #6</strong>每个矩形块的面积和它的 data-value 属性值相对应data-value 值越大的矩形块面积越大
<strong>需求 #7</strong>我的矩阵树图应该有一个具有<code>id="legend"</code>属性的图例。
<strong>需求 #8</strong>我的图例应该有一些具有<code>class="legend-item"</code>属性的<code>rect</code>元素
<strong>需求 #9</strong>图例中的这些<code>rect</code>元素至少应该使用 2 种不同的填充颜色。
<strong>需求 #10</strong>我可以将鼠标悬停在某个区域上,并查看具有<code>id="tooltip"</code>属性的提示框,它会显示有关该区域的更多信息
<strong>需求 #11</strong>我的提示框应该有一个<code>data-value</code>属性它对应了当前激活区域的code>data-value</code>属性。
对于此项目,您可以使用以下任何数据集:<br><ul><li><strong>Kickstarter Pledges</strong> <code>https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/kickstarter-funding-data.json</code></li><li><strong>Movie Sales</strong> <code>https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/movie-data.json</code></li><li><strong>Video Game Sales</strong> <code>https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/video-game-sales-data.json</code></li></ul>
你可以 fork <a href='https://codepen.io/freeCodeCamp/pen/MJjpwO' target='_blank'>这个 CodePen pen 项目</a>来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:<code>https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js</code>.
# --description--
**目标:** 在 [CodePen.io](https://codepen.io) 上实现一个功能类似 <https://codepen.io/freeCodeCamp/full/KaNGNR> 的 App。
在满足以下[需求](https://en.wikipedia.org/wiki/User_story)并能通过所有测试的前提下,你可以根据自己的喜好来美化你的 app
你可以使用 HTML、JavaScript、CSS、以及基于 svg 的 D3 可视化库来完成这个挑战。该任务需要使用 D3 的坐标轴属性生成坐标轴,这个属性会自动生成沿轴的刻度。这些刻度是通过 D3 测试所必需的,因为它们的位置是用来确定图表元素的对齐方式。你可以在这里 <https://github.com/d3/d3/blob/master/API.md#axes-d3-axis> 获取关于生成坐标轴的信息。每次测试查询的元素都必须是非虚拟 DOM。 如果你使用了前端框架(例如 Vue那么对于动态的内容测试结果可能不准确。我们希望最终能够兼容这些框架但 D3 项目目前还不支持它们
**需求 #1** 我的矩阵树图应该有一个具有`id="title"`属性的标题
**需求 #2** 我的矩阵树图应该有一个具有`id="description"`属性的描述内容
**需求 #3** 我的矩阵树图应该有一些具有`class="tile"`属性的`rect`元素来展示数据
**需求 #4** 这些矩形块元素至少应该有 2 种不同的填充颜色
**需求 #5** 每一块矩形元素应该具有`data-name``data-category`,以及`data-value`这些属性,包含了它们相应的名称,分类,以及数值。
**需求 #6** 每个矩形块的面积和它的 data-value 属性值相对应data-value 值越大的矩形块面积越大。
**需求 #7** 我的矩阵树图应该有一个具有`id="legend"`属性的图例。
**需求 #8** 我的图例应该有一些具有`class="legend-item"`属性的`rect`元素。
**需求 #9** 图例中的这些`rect`元素至少应该使用 2 种不同的填充颜色。
**需求 #10** 我可以将鼠标悬停在某个区域上,并查看具有`id="tooltip"`属性的提示框,它会显示有关该区域的更多信息。
**需求 #11** 我的提示框应该有一个`data-value`属性它对应了当前激活区域的code>data-value属性。
对于此项目,您可以使用以下任何数据集:
- **Kickstarter Pledges** `https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/kickstarter-funding-data.json`
- **Movie Sales** `https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/movie-data.json`
- **Video Game Sales** `https://cdn.rawgit.com/freeCodeCamp/testable-projects-fcc/a80ce8f9/src/data/tree_map/video-game-sales-data.json`
你可以 fork [这个 CodePen pen 项目](https://codepen.io/freeCodeCamp/pen/MJjpwO)来构建你的项目。或者你可以在任何你喜欢的环境中使用以下 CDN 链接来运行测试:`https://gitcdn.link/repo/freeCodeCamp/testable-projects-fcc/master/build/bundle.js`.
一旦你完成了本项目并且该项目所有测试运行通过,请提交项目的 URL。
</section>
## Instructions
<section id='instructions'>
# --hints--
</section>
## Tests
<section id='tests'>
# --solutions--
```yml
tests: []
```
</section>
## Challenge Seed
<section id='challengeSeed'>
</section>
## Solution
<section id='solution'>
```js
// solution required
```
</section>

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

View File

@ -1,169 +1,50 @@
---
id: 587d7fae367417b2b2512be4
title: 访问来自 API 的 JSON 数据
challengeType: 6
forumTopicId: 301499
title: 访问来自 API 的 JSON 数据
---
## Description
<section id='description'>
# --description--
在前面的挑战中,你了解了如何从 freeCodeCamp Cat Photo API 获取 JSON 数据。
现在,你将进一步观察返回的数据来更好的了解 JSON 格式,回忆一下 JavaScript 中的一些符号:
<blockquote>[ ] -> 方括号表示数组<br>{ } -> 大括号表示对象<br>" " -> 双引号表示字符串,它们还用于表示 JSON 中的键名</blockquote>
理解 API 返回数据的结构是必需的,它将影响你如何获取你所需的值。
在右侧,点击 "Get Message" 按钮,将 freeCodeCamp Cat Photo API JSON 加载到页面中。
你看到在 JSON 数据中的第一个和最后一个字符是中括号<code>[ ]</code>这意味着返回的数据是一个数组。JSON 数据中的第二个符号是一个大括号<code>{</code>,这意味着是一个对象。再仔细看,你会发现有三个独立的对象,这个 JSON 数据是一个包含三个对象的数组,它们各自都包含了 cat photo 的信息。
之前了解了对象包含了用逗号分隔的 "键值对"。在 Cat Photo 示例中,第一个对象的<code>"id":0</code>"id" 是键0 是其对应的值,类似的,"imageLink", "altText", 和 "codeNames" 都是对应的键。每个 cat photo 对象具有相同的键,但具有不同的值
在第一个对象中有一个有趣的 "键值对" 它是<code>"codeNames":["Juggernaut","Mrs. Wallace","ButterCup"]</code>。 "codeNames" 是键,它的值是包含三个字符串的数组。对象数组以及数组作为键可以作为值
记住如何访问数组和对象中的数据,数组使用括号表示法来访问项目的特定索引,对象使用括号或点表示法来访问给定属性的值。这是打印第一张 cat photo 的“altText”的示例 - 请注意,编辑器中解析的 JSON 数据保存在名为<code>json</code>的变量中:
看到在 JSON 数据中的第一个和最后一个字符是中括号`[ ]`这意味着返回的数据是一个数组。JSON 数据中的第二个符号是一个大括号`{`,这意味着是一个对象。再仔细看,你会发现有三个独立的对象,这个 JSON 数据是一个包含三个对象的数组,它们各自都包含了 cat photo 的信息。
你之前了解了对象包含了用逗号分隔的 "键值对"。在 Cat Photo 示例中,第一个对象的`"id":0`"id" 是键0 是其对应的值,类似的,"imageLink", "altText", 和 "codeNames" 都是对应的键。每个 cat photo 对象具有相同的键,但具有不同的值
在第一个对象中有一个有趣的 "键值对" 它是`"codeNames":["Juggernaut","Mrs. Wallace","ButterCup"]`。 "codeNames" 是键,它的值是包含三个字符串的数组。对象数组以及数组作为键可以作为值
记住如何访问数组和对象中的数据,数组使用括号表示法来访问项目的特定索引,对象使用括号或点表示法来访问给定属性的值。这是打印第一张 cat photo 的“altText”的示例 - 请注意,编辑器中解析的 JSON 数据保存在名为`json`的变量中:
```js
console.log(json[0].altText);
// Prints "A white cat wearing a green helmet shaped melon on its head."
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
对于 "id" 是 2 的猫, 打印<code>codeNames</code>数组的第二个值到控制台,你应该在对象上使用括号或者点表示法(保存在变量<code>json</code>中)来访问该值。
</section>
对于 "id" 是 2 的猫, 打印`codeNames`数组的第二个值到控制台,你应该在对象上使用括号或者点表示法(保存在变量`json`中)来访问该值。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: "你的代码应该使用括号和点表示法来读取正确的代码名称,并将 'Loki' 打印到控制台。"
testString: assert(code.match(/console\s*\.\s*log\s*\(\s*json\s*\[2\]\s*(\.\s*codeNames|\[\s*('|`|")codeNames\2\s*\])\s*\[\s*1\s*\]\s*\)/g));
你的代码应该使用括号和点表示法来读取正确的代码名称,并将 'Loki' 打印到控制台。
```js
assert(
code.match(
/console\s*\.\s*log\s*\(\s*json\s*\[2\]\s*(\.\s*codeNames|\[\s*('|`|")codeNames\2\s*\])\s*\[\s*1\s*\]\s*\)/g
)
);
```
</section>
# --solutions--
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload=function(){
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
// 在这行下面添加代码
// 在这行上面添加代码
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</div>
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload=function(){
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
// Add your code below this line
console.log(json[2].codeNames[1]);
// Add your code above this line
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</section>

View File

@ -1,148 +1,35 @@
---
id: 587d7fad367417b2b2512be2
title: 通过单击事件更改文本
challengeType: 6
forumTopicId: 301500
title: 通过单击事件更改文本
---
## Description
<section id='description'>
# --description--
当点击事件发生时,你可以使用 JavaScript 更新 HTML 元素。
例如,当用户点击 "Get Message" 按钮时,它将改变类名<code>message</code>元素的文本为 "Here is the message"。
例如,当用户点击 "Get Message" 按钮时,它将改变类名`message`元素的文本为 "Here is the message"。
通过在点击事件内添加以下代码实现:
<code>document.getElementsByClassName('message')[0].textContent="Here is the message";</code>
</section>
## Instructions
<section id='instructions'>
<code>onclick</code>事件处理器中添加代码,改变<code>message</code>元素内的文字为 "Here is the message"。
</section>
`document.getElementsByClassName('message')[0].textContent="Here is the message";`
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: 你的代码应该使用<code>document.getElementsByClassName</code>方法来选择类名为<code>message</code>的元素,然后将其<code>innerHTML</code>改为给定文字。
testString: assert(code.match(/document\s*\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\s*\.textContent\s*?=\s*?('|")Here is the message\2/g));
`onclick`事件处理器中添加代码,改变`message`元素内的文字为 "Here is the message"。
# --hints--
你的代码应该使用`document.getElementsByClassName`方法来选择类名为`message`的元素,然后将其`innerHTML`改为给定文字。
```js
assert(
code.match(
/document\s*\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\s*\.textContent\s*?=\s*?('|")Here is the message\2/g
)
);
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
// 在这行下面添加代码
// 在这行上面添加代码
}
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</div>
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick = function(){
// Add your code below this line
document.getElementsByClassName('message')[0].textContent = "Here is the message";
// Add your code above this line
}
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</section>
# --solutions--

View File

@ -1,16 +1,20 @@
---
id: 587d7fae367417b2b2512be5
title: 将 JSON 数据转换为 HTML
challengeType: 6
forumTopicId: 16807
title: 将 JSON 数据转换为 HTML
---
## Description
<section id='description'>
# --description--
现在你可以从 JSON API 获取数据了,你可以在 HTML 中显示它。
既然 cat photo 对象保存在数组里,你可以使用<code>forEach</code>方法来遍历它。当你拿到每个对象时,你就可以修改 HTML 元素了。
首先,用<code>let html = "";</code>声明一个变量
接着,遍历 JSON将 HTML 添加到用<code>strong</code>标记键名的变量,后面跟着值。当循环结束后渲染它。
既然 cat photo 对象保存在数组里,你可以使用`forEach`方法来遍历它。当你拿到每个对象时,你就可以修改 HTML 元素了
首先,用`let html = "";`声明一个变量。
接着,遍历 JSON将 HTML 添加到用`strong`标记键名的变量,后面跟着值。当循环结束后渲染它。
这是执行此操作的代码:
```js
@ -25,12 +29,12 @@ json.forEach(function(val) {
});
```
<strong>注意:</strong> 在本挑战需要给页面添加一个新的 HTML 元素,不能使用 `textContent` 方法,这个方法容易遭受跨站脚本攻击,可以用 `innerHTML` 来完成挑战。
</section>
**注意:** 在本挑战需要给页面添加一个新的 HTML 元素,不能使用 `textContent` 方法,这个方法容易遭受跨站脚本攻击,可以用 `innerHTML` 来完成挑战。
# --instructions--
添加一个`forEach`循环 JSON 数据的方法,并创建 HTML 元素以显示它。
## Instructions
<section id='instructions'>
添加一个<code>forEach</code>循环 JSON 数据的方法,并创建 HTML 元素以显示它。
以下是一个 JSON 示例:
```json
@ -45,156 +49,25 @@ json.forEach(function(val) {
]
```
</section>
# --hints--
## Tests
<section id='tests'>
```yml
tests:
- text: 你的代码应该将数据保存在<code>html</code>变量中。
testString: assert(code.match(/html\s+?(\+=|=\shtml\s\+)/g));
- text: 你的代码应该使用<code>forEach</code>方法来遍历 API 中的 JSON 数据。
testString: assert(code.match(/json\.forEach/g));
- text: 你的代码应该将键名包装在<code>strong</code>标签中。
testString: assert(code.match(/<strong>.+<\/strong>/g));
你的代码应该将数据保存在`html`变量中。
```js
assert(code.match(/html\s+?(\+=|=\shtml\s\+)/g));
```
</section>
你的代码应该使用`forEach`方法来遍历 API 中的 JSON 数据。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
// 在这行下面添加代码
// 在这行上面添加代码
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(code.match(/json\.forEach/g));
```
</div>
你的代码应该将键名包装在`strong`标签中。
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
// Add your code below this line
json.forEach(function(val) {
var keys = Object.keys(val);
html += "<div class = 'cat'>";
keys.forEach(function(key) {
html += "<strong>" + key + "</strong>: " + val[key] + "<br>";
});
html += "</div><br>";
});
// Add your code above this line
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(code.match(/<strong>.+<\/strong>/g));
```
</section>
# --solutions--

View File

@ -1,16 +1,20 @@
---
id: 587d7faf367417b2b2512be8
title: 根据地理位置数据找到用户的 GPS 坐标
challengeType: 6
forumTopicId: 18188
title: 根据地理位置数据找到用户的 GPS 坐标
---
## Description
<section id='description'>
# --description--
你还能做一件很酷的事就是访问你用户当前的地理位置,每个浏览器都有内置的导航器,可以为你提供这些信息。
导航器会获取用户当前的经度和纬度。
您将看到允许或阻止此站点了解您当前位置的提示。只要代码正确,挑战就可以以任何一种方式完成。
通过选择允许,你将看到输出手机上的文本更改为你的纬度和经度
这是执行此操作的代码:
```js
@ -21,72 +25,39 @@ if (navigator.geolocation){
}
```
首先,它检查<code>navigator.geolocation</code>对象是否存在。如果是,<code>getCurrentPosition</code>则调用该对象上的方法,该方法启动对用户位置的异步请求。如果请求成功,则运行方法中的回调函数。此函数<code>position</code>使用点表示法访问对象的纬度和经度值,并更新页面。
</section>
首先,它检查`navigator.geolocation`对象是否存在。如果是,`getCurrentPosition`则调用该对象上的方法,该方法启动对用户位置的异步请求。如果请求成功,则运行方法中的回调函数。此函数`position`使用点表示法访问对象的纬度和经度值,并更新页面。
## Instructions
<section id='instructions'>
<code>script</code>标记内添加示例代码以检查用户的当前位置并将其插入 HTML
</section>
# --instructions--
## Tests
<section id='tests'>
`script`标记内添加示例代码以检查用户的当前位置并将其插入 HTML
```yml
tests:
- text: 你的代码应该用于<code>navigator.geolocation</code>访问用户的当前位置。
testString: assert(code.match(/navigator\.geolocation\.getCurrentPosition/g));
- text: 你的代码应该用于<code>position.coords.latitude</code>显示用户的纬度位置。
testString: assert(code.match(/position\.coords\.latitude/g));
- text: 你的代码应该用于<code>position.coords.longitude</code>显示用户的经度位置。
testString: assert(code.match(/position\.coords\.longitude/g));
- text: 你应该在<code>data</code>div 元素中显示用户的位置。
testString: assert(code.match(/document\.getElementById\(\s*?('|")data\1\s*?\)\.innerHTML/g));
# --hints--
你的代码应该用于`navigator.geolocation`访问用户的当前位置。
```js
assert(code.match(/navigator\.geolocation\.getCurrentPosition/g));
```
</section>
你的代码应该用于`position.coords.latitude`显示用户的纬度位置。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
// 在这行下面添加代码
// 在这行上面添加代码
</script>
<h4>You are here:</h4>
<div id="data">
</div>
```js
assert(code.match(/position\.coords\.latitude/g));
```
</div>
你的代码应该用于`position.coords.longitude`显示用户的经度位置。
```js
assert(code.match(/position\.coords\.longitude/g));
```
你应该在`data`div 元素中显示用户的位置。
</section>
```js
assert(
code.match(/document\.getElementById\(\s*?('|")data\1\s*?\)\.innerHTML/g)
);
```
## Solution
<section id='solution'>
# --solutions--
```html
<script>
// Add your code below this line
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
document.getElementById('data').innerHTML = "latitude: " + position.coords.latitude + "<br>longitude: " + position.coords.longitude;
});
}
// Add your code above this line
</script>
<h4>You are here:</h4>
<div id="data">
</div>
</section>

View File

@ -1,14 +1,15 @@
---
id: 5ccfad82bb2dc6c965a848e5
title: 使用 JavaScript 的 fetch 方法获取 JSON
challengeType: 6
forumTopicId: 301501
title: 使用 JavaScript 的 fetch 方法获取 JSON
---
## Description
<section id='description'>
请求外部数据的另一个方法是使用 JavaScript 的 <code>fetch()</code> 方法。它的作用和 XMLHttpRequest 一致,但是语法更易理解。
下面是使用 GET 请求 <code>/json/cats.json</code> 数据的例子。
# --description--
请求外部数据的另一个方法是使用 JavaScript 的 `fetch()` 方法。它的作用和 XMLHttpRequest 一致,但是语法更易理解。
下面是使用 GET 请求 `/json/cats.json` 数据的例子。
```js
@ -19,149 +20,54 @@ fetch('/json/cats.json')
})
```
逐行解释一下代码。
第一行是发起请求。也就是说,<code>fetch(URL)</code> 向指定的 URL 发起 GET 请求。方法返回一个 Promise。
第一行是发起请求。也就是说,`fetch(URL)` 向指定的 URL 发起 GET 请求。方法返回一个 Promise。
当 Promise 返回后,如果请求成功,会执行 <code>then</code> 方法,该方法把响应转换为 JSON 格式。
当 Promise 返回后,如果请求成功,会执行 `then` 方法,该方法把响应转换为 JSON 格式。
<code>then</code> 方法返回的也是 Promise会被下一个 <code>then</code> 方法捕获。第二个 <code>then</code> 方法传入的参数就是最终的 JSON 对象。
`then` 方法返回的也是 Promise会被下一个 `then` 方法捕获。第二个 `then` 方法传入的参数就是最终的 JSON 对象。
接着,使用 <code>document.getElementById()</code> 选择将要接收数据的元素。然后插入请求返回的 JSON 对象创建的字符串修改元素的 HTML 代码。
</section>
接着,使用 `document.getElementById()` 选择将要接收数据的元素。然后插入请求返回的 JSON 对象创建的字符串修改元素的 HTML 代码。
## Instructions
<section id='instructions'>
更新代码,创建一个 "GET" 请求向 freeCodeCamp Cat Photo API 请求数据。这次使用 <code>fetch</code> 方法而不是 <code>XMLHttpRequest</code>
</section>
# --instructions--
## Tests
<section id='tests'>
更新代码,创建一个 "GET" 请求向 freeCodeCamp Cat Photo API 请求数据。这次使用 `fetch` 方法而不是 `XMLHttpRequest`
```yml
tests:
- text: 应该使用 <code>fetch</code> 来发起 GET 请求。
testString: assert(code.match(/fetch\s*\(\s*('|")\/json\/cats\.json\1\s*\)/g));
- text: 应该在 <code>then</code> 里面将响应转换为 JSON。
testString: assert(code.match(/\.then\s*\(\s*(response|\(\s*response\s*\))\s*=>\s*response\s*\.json\s*\(\s*\)\s*\)/g))
- text: 应该使用另一个 <code>then</code> 接收 <code>then</code> 转换的 JSON。
testString: assert(code.match(/\.then\s*\(\s*(data|\(\s*data\s*\))\s*=>\s*{[^}]*}\s*\)/g))
- text: 代码应该选择 id 为 <code>message</code> 的元素然后把它的内部 HTML 改成 JSON data 的字符串。
testString: assert(code.match(/document\s*\.getElementById\s*\(\s*('|")message\1\s*\)\s*\.innerHTML\s*=\s*JSON\s*\.\s*stringify\s*\(\s*data\s*\)/g));
# --hints--
应该使用 `fetch` 来发起 GET 请求。
```js
assert(code.match(/fetch\s*\(\s*('|")\/json\/cats\.json\1\s*\)/g));
```
</section>
应该在 `then` 里面将响应转换为 JSON。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick= () => {
// Add your code below this line
// Add your code above this line
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p id="message" class="box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(
code.match(
/\.then\s*\(\s*(response|\(\s*response\s*\))\s*=>\s*response\s*\.json\s*\(\s*\)\s*\)/g
)
);
```
</div>
应该使用另一个 `then` 接收 `then` 转换的 JSON。
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick= () => {
fetch('/json/cats.json')
.then(response => response.json())
.then(data => {
document.getElementById('message').innerHTML=JSON.stringify(data);
})
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p id="message" class="box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(code.match(/\.then\s*\(\s*(data|\(\s*data\s*\))\s*=>\s*{[^}]*}\s*\)/g));
```
</section>
代码应该选择 id 为 `message` 的元素然后把它的内部 HTML 改成 JSON data 的字符串。
```js
assert(
code.match(
/document\s*\.getElementById\s*\(\s*('|")message\1\s*\)\s*\.innerHTML\s*=\s*JSON\s*\.\s*stringify\s*\(\s*data\s*\)/g
)
);
```
# --solutions--

View File

@ -1,18 +1,24 @@
---
id: 587d7fae367417b2b2512be3
title: 使用 XMLHttpRequest 方法获取 JSON
challengeType: 6
forumTopicId: 301502
title: 使用 XMLHttpRequest 方法获取 JSON
---
## Description
<section id='description'>
# --description--
你还可以从外部链接请求数据,这就是 API 发挥作用的地方。
请记住API或叫应用程序编程接口是计算机用来互相通信的工具。你将学习如何通过 AJAX技术 从 API 获得的数据来更新 HTML。
大部分 web APIs 以 JSON 格式传输数据。JSON 是 JavaScript Object Notation 的简写。
JSON 语法与 JavaScript 对象字面符号非常相似JSON 具有对象属性以及其当前值,夹在<code>{</code><code>}</code>之间。
JSON 语法与 JavaScript 对象字面符号非常相似JSON 具有对象属性以及其当前值,夹在`{``}`之间。
这些属性及其值通常称为 "键值对"。
但是JSON 是由 API 以<code>bytes</code> 形式传输的,你的程序以<code>string</code>接受它。它们能转换成为 JavaScript 对象,但默认情况下它们不是 JavaScript 对象。 <code>JSON.parse</code>方法解析字符串并构造它描述的 JavaScript 对象。
但是JSON 是由 API 以`bytes` 形式传输的,你的程序以`string`接受它。它们能转换成为 JavaScript 对象,但默认情况下它们不是 JavaScript 对象。 `JSON.parse`方法解析字符串并构造它描述的 JavaScript 对象。
你可以从 freeCodeCamp 的 Cat Photo API 请求 JSON以下是你可以在点击事件中添加的代码
```js
@ -25,154 +31,59 @@ req.onload = function(){
};
```
这里介绍每行代码的作用JavaScript <code>XMLHttpRequest</code> 对象具有许多用于传输数据的属性和方法。首先,创建一个<code>XMLHttpRequest</code>对象实例,并保存在<code>req</code>变量里
接着, <code>open</code> 方法初始化请求 - 此示例从 API 请求数据,因此是个 "GET" 请求。第二个参数 <code>open</code> 是你要从中请求数据的 API 的 URL。第三个参数是一个布尔值 <code>true</code>使其成为异步请求。
<code>send</code>方法发送请求,最后,<code>onload</code>事件处理程序解析返回的数据并应用该<code>JSON.stringify</code>方法将JavaScript对象转换为字符串然后将此字符串作为消息文本插入。
</section>
这里介绍每行代码的作用JavaScript `XMLHttpRequest` 对象具有许多用于传输数据的属性和方法。首先,创建一个`XMLHttpRequest`对象实例,并保存在`req`变量里 。 接着, `open` 方法初始化请求 - 此示例从 API 请求数据,因此是个 "GET" 请求。第二个参数 `open` 是你要从中请求数据的 API 的 URL。第三个参数是一个布尔值 `true`使其成为异步请求。 该`send`方法发送请求,最后,`onload`事件处理程序解析返回的数据并应用该`JSON.stringify`方法将JavaScript对象转换为字符串然后将此字符串作为消息文本插入
# --instructions--
## Instructions
<section id='instructions'>
更新代码以创建并向 freeCodeCamp Cat Photo API 发送 "GET" 请求。然后点击 "Get Message" 按钮,你的 AJAX 函数将使用 API 的原生 JSON 替换 "The message will go here" 的文本。
</section>
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: 你的代码应该创建一个新的<code>XMLHttpRequest</code>。
testString: assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
- text: "你的代码应使用该<code>open</code>方法初始化对 freeCodeCamp Cat Photo API 的 'GET' 请求。"
testString: assert(code.match(/\.open\(\s*?('|")GET\1\s*?,\s*?('|")\/json\/cats\.json\2\s*?,\s*?true\s*?\)/g));
- text: 你的代码应使用该<code>send</code>方法发送请求。
testString: assert(code.match(/\.send\(\s*\)/g));
- text: 你的代码应该有一个<code>onload</code>设置为函数的事件处理程序。
testString: assert(code.match(/\.onload\s*=\s*(function|\(\s*?\))\s*?(\(\s*?\)|\=\>)\s*?{/g));
- text: 你的代码应该使用该<code>JSON.parse</code>方法来解析<code>responseText</code>。
testString: assert(code.match(/JSON\s*\.parse\(\s*.*\.responseText\s*\)/g));
- text: 你的代码应该用<code>message</code>获取元素,并将其内部 HTML 转换为 JSON 数据字符串。
testString: assert(code.match(/document\s*\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\s*\.innerHTML\s*?=\s*?JSON\.stringify\(.+?\)/g));
你的代码应该创建一个新的`XMLHttpRequest`
```js
assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
```
</section>
你的代码应使用该`open`方法初始化对 freeCodeCamp Cat Photo API 的 'GET' 请求。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
// 在这行下面添加代码
// 在这行上面添加代码
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(
code.match(
/\.open\(\s*?('|")GET\1\s*?,\s*?('|")\/json\/cats\.json\2\s*?,\s*?true\s*?\)/g
)
);
```
</div>
你的代码应使用该`send`方法发送请求。
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded',function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open('GET', '/json/cats.json', true);
req.send();
req.onload = () => {
const json = JSON.parse(req.responseText);
document.getElementsByClassName('message')[0].innerHTML = JSON.stringify(json);
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(code.match(/\.send\(\s*\)/g));
```
</section>
你的代码应该有一个`onload`设置为函数的事件处理程序。
```js
assert(
code.match(/\.onload\s*=\s*(function|\(\s*?\))\s*?(\(\s*?\)|\=\>)\s*?{/g)
);
```
你的代码应该使用该`JSON.parse`方法来解析`responseText`
```js
assert(code.match(/JSON\s*\.parse\(\s*.*\.responseText\s*\)/g));
```
你的代码应该用`message`获取元素,并将其内部 HTML 转换为 JSON 数据字符串。
```js
assert(
code.match(
/document\s*\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\s*\.innerHTML\s*?=\s*?JSON\.stringify\(.+?\)/g
)
);
```
# --solutions--

View File

@ -1,13 +1,13 @@
---
id: 587d7fad367417b2b2512be1
title: 使用 onclick 属性处理点击事件
challengeType: 6
forumTopicId: 301503
title: 使用 onclick 属性处理点击事件
---
## Description
<section id='description'>
你希望代码仅在页面完成加载后执行。为此,你可将名为<code>DOMContentLoaded</code>的 JavaScript 事件附加到文档中。以下是实现的代码:
# --description--
你希望代码仅在页面完成加载后执行。为此,你可将名为`DOMContentLoaded`的 JavaScript 事件附加到文档中。以下是实现的代码:
```js
document.addEventListener('DOMContentLoaded', function() {
@ -15,138 +15,29 @@ document.addEventListener('DOMContentLoaded', function() {
});
```
你可以在<code>DOMContentLoaded</code>函数内部添加事件处理方法。你可以添加<code>onclick</code>事件处理器,当用户点击 id 为<code>getMessage</code>的元素时会触发事件。添加以下代码:
你可以在`DOMContentLoaded`函数内部添加事件处理方法。你可以添加`onclick`事件处理器,当用户点击 id 为`getMessage`的元素时会触发事件。添加以下代码:
```js
document.getElementById('getMessage').onclick = function(){};
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
<code>DOMContentLoaded</code>函数内为 id 为<code>getMessage</code>的元素添加一个 click 事件处理器。
</section>
`DOMContentLoaded`函数内为 id 为`getMessage`的元素添加一个 click 事件处理器。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: 你的代码应该用<code>document.getElementById</code>方法来选择<code>getMessage</code>元素。
testString: assert(code.match(/document\s*\.getElementById\(\s*?('|")getMessage\1\s*?\)/g));
- text: 你的代码应该添加<code>onclick</code>事件处理器。
testString: assert(typeof document.getElementById('getMessage').onclick === 'function');
你的代码应该用`document.getElementById`方法来选择`getMessage`元素。
```js
assert(code.match(/document\s*\.getElementById\(\s*?('|")getMessage\1\s*?\)/g));
```
</section>
你的代码应该添加`onclick`事件处理器。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
// 在这行下面添加代码
// 在这行上面添加代码
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(typeof document.getElementById('getMessage').onclick === 'function');
```
</div>
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
// Add your code below this line
document.getElementById('getMessage').onclick = function(){ };
// Add your code above this line
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</section>
# --solutions--

View File

@ -1,14 +1,15 @@
---
id: 587d7faf367417b2b2512be9
title: 使用 XMLHttpRequest 方法发送数据
challengeType: 6
forumTopicId: 301504
title: 使用 XMLHttpRequest 方法发送数据
---
## Description
<section id='description'>
# --description--
在前面的示例中,你在外部资源获取数据,你也可以将数据发送到外部资源,只要该资源支持 AJAX 请求并且你知道 URL。
JavaScript 的<code>XMLHttpRequest</code>方法也用于将数据发布到服务器,这是个例子:
JavaScript 的`XMLHttpRequest`方法也用于将数据发布到服务器,这是个例子:
```js
const xhr = new XMLHttpRequest();
@ -24,172 +25,57 @@ const body = JSON.stringify({ userName: userName, suffix: ' loves cats!' });
xhr.send(body);
```
你在之前见过其中几种方法。这里<code>open</code>方法将请求初始化为对外部资源的给定 URL 的 "POST",并使用<code>true</code>布尔值使其异步
<code>setRequestHeader</code>方法设置HTTP请求标头的值该标头包含有关发送人和请求的信息。它必须在<code>open</code>方法之后调用,但在<code>send</code>方法之前调用。这两个参数是标题的名称和要设置为该标题正文的值。
接下来,<code>onreadystatechange</code>事件侦听器处理请求状态的更改。<code>readyState</code>为 4 表示操作完成,<code>status</code>200表示操作成功。文档的HTML可以更新。
最后,该<code>send</code>方法发送带有<code>userName</code>值的请求,该值由用户在<code>input</code>字段中给出。
</section>
你在之前见过其中几种方法。这里`open`方法将请求初始化为对外部资源的给定 URL 的 "POST",并使用`true`布尔值使其异步。 `setRequestHeader`方法设置HTTP请求标头的值该标头包含有关发送人和请求的信息。它必须在`open`方法之后调用,但在`send`方法之前调用。这两个参数是标题的名称和要设置为该标题正文的值。 接下来,`onreadystatechange`事件侦听器处理请求状态的更改。`readyState`为 4 表示操作完成,`status`200表示操作成功。文档的HTML可以更新。 最后,该`send`方法发送带有`userName`值的请求,该值由用户在`input`字段中给出
# --instructions--
## Instructions
<section id='instructions'>
更新代码以创建并发送 "POST" 请求。然后在输入框中输入你的姓名,你的 AJAX 函数会用服务器返回的数据替换 "Reply from Server will be here"。在这种情况下,你的名字附加 " loves cats"。
</section>
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: 你的代码应该创建一个新的<code>XMLHttpRequest</code>。
testString: assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
- text: "你的代码应该使用该<code>open</code>方法初始化到服务器的 'POST' 请求。"
testString: assert(code.match(/\.open\(\s*?('|")POST\1\s*?,\s*?url\s*?,\s*?true\s*?\)/g));
- text: 你的代码应该使用该<code>setRequestHeader</code>方法。
testString: assert(code.match(/\.setRequestHeader\(\s*?('|")Content-Type\1\s*?,\s*?('|")application\/json;\s*charset=UTF-8\2\s*?\)/g));
- text: 你的代码应该有一个<code>onreadystatechange</code>设置为函数的事件处理程序。
testString: assert(code.match(/\.onreadystatechange\s*?=/g));
- text: 你的代码应该使用类获取元素<code>message</code>并将其内部HTML更改为<code>responseText</code>。
testString: assert(code.match(/document\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\.textContent\s*?=\s*?.+?\.userName\s*?\+\s*?.+?\.suffix/g));
- text: 你的代码应该使用该<code>send</code>方法。
testString: assert(code.match(/\.send\(\s*?body\s*?\)/g));
```
</section>
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('sendMessage').onclick = function(){
const userName = document.getElementById('name').value;
const url = 'https://jsonplaceholder.typicode.com/posts';
// 在这行下面添加代码
// 在这行上面添加代码
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Friends</h1>
<p class="message box">
Reply from Server will be here
</p>
<p>
<label for="name">Your name:
<input type="text" id="name"/>
</label>
<button id="sendMessage">
Send Message
</button>
</p>
```
</div>
</section>
## Solution
<section id='solution'>
你的代码应该创建一个新的`XMLHttpRequest`
```js
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('sendMessage').onclick = function(){
const userName = document.getElementById('name').value;
const url = 'https://jsonplaceholder.typicode.com/posts';
// Add your code below this line
const xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 201){
const serverResponse = JSON.parse(xhr.response);
document.getElementsByClassName('message')[0].textContent = serverResponse.userName + serverResponse.suffix;
}
};
const body = JSON.stringify({ userName: userName, suffix: ' loves cats!' });
xhr.send(body);
// Add your code above this line
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<p class="message">
Reply from Server will be here
</p>
<p>
<label for="name">Your name:
<input type="text" id="name"/>
</label>
<button id="sendMessage">
Send Message
</button>
</p>
assert(code.match(/new\s+?XMLHttpRequest\(\s*?\)/g));
```
</section>
你的代码应该使用该`open`方法初始化到服务器的 'POST' 请求。
```js
assert(code.match(/\.open\(\s*?('|")POST\1\s*?,\s*?url\s*?,\s*?true\s*?\)/g));
```
你的代码应该使用该`setRequestHeader`方法。
```js
assert(
code.match(
/\.setRequestHeader\(\s*?('|")Content-Type\1\s*?,\s*?('|")application\/json;\s*charset=UTF-8\2\s*?\)/g
)
);
```
你的代码应该有一个`onreadystatechange`设置为函数的事件处理程序。
```js
assert(code.match(/\.onreadystatechange\s*?=/g));
```
你的代码应该使用类获取元素`message`并将其内部HTML更改为`responseText`
```js
assert(
code.match(
/document\.getElementsByClassName\(\s*?('|")message\1\s*?\)\[0\]\.textContent\s*?=\s*?.+?\.userName\s*?\+\s*?.+?\.suffix/g
)
);
```
你的代码应该使用该`send`方法。
```js
assert(code.match(/\.send\(\s*?body\s*?\)/g));
```
# --solutions--

View File

@ -1,14 +1,16 @@
---
id: 587d7fae367417b2b2512be7
title: 预先过滤 JSON 以获得所需的数据
challengeType: 6
forumTopicId: 18257
title: 预先过滤 JSON 以获得所需的数据
---
## Description
<section id='description'>
# --description--
如果你不希望渲染每张从 freeCodeCamp Cat Photo API 取回的猫照片,你可以在循环先预先过滤 JSON 数据。
鉴于 JSON 数据都存储在数组中,你可以使用<code>filter</code>方法过滤掉 "id" 键值为 1 的猫。
鉴于 JSON 数据都存储在数组中,你可以使用`filter`方法过滤掉 "id" 键值为 1 的猫。
这是执行此操作的代码:
```js
@ -17,169 +19,17 @@ json = json.filter(function(val) {
});
```
</section>
# --instructions--
## Instructions
<section id='instructions'>
<code>filter</code>代码添加到 JSON 数据中来移除 "id" 值为 1 的猫。
</section>
`filter`代码添加到 JSON 数据中来移除 "id" 值为 1 的猫。
## Tests
<section id='tests'>
# --hints--
```yml
tests:
- text: 你的代码应该使用<code>filter</code>方法。
testString: assert(code.match(/json\.filter/g));
你的代码应该使用`filter`方法。
```js
assert(code.match(/json\.filter/g));
```
</section>
# --solutions--
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload=function(){
let json = JSON.parse(req.responseText);
let html = "";
// 在这行下面添加代码
// 在这行上面添加代码
json.forEach(function(val) {
html += "<div class = 'cat'>"
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>"
html += "</div>"
});
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</div>
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json', true);
req.send();
req.onload = function(){
let json = JSON.parse(req.responseText);
let html = "";
// Add your code below this line
json = json.filter(function(val) {
return (val.id !== 1);
});
// Add your code above this line
json.forEach(function(val) {
html += "<div class = 'cat'>"
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>"
html += "</div>"
});
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</section>

View File

@ -1,170 +1,37 @@
---
id: 587d7fae367417b2b2512be6
title: 渲染数据源的图像
challengeType: 6
forumTopicId: 18265
title: 渲染数据源的图像
---
## Description
<section id='description'>
前几个挑战中表明JSON 数组中的每个对象都包含一个<code>imageLink</code>键,其值为猫图像的 URL。
当你遍历这些对象的时候,你可以使用<code>imageLink</code>属性在<code>img</code>元素中显示此图像。
# --description--
前几个挑战中表明JSON 数组中的每个对象都包含一个`imageLink`键,其值为猫图像的 URL。
当你遍历这些对象的时候,你可以使用`imageLink`属性在`img`元素中显示此图像。
这是执行此操作的代码:
<code>html += "&lt;img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'&gt;";</code>
</section>
## Instructions
<section id='instructions'>
添加代码以在<code>img</code>标签中使用<code>imageLink</code><code>altText</code>属性。
</section>
`html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>";`
## Tests
<section id='tests'>
# --instructions--
```yml
tests:
- text: 你应该使用<code>imageLink</code>属性来显示图像。
testString: assert(code.match(/val\.imageLink/g));
- text: 应该用 <code>altText</code> 做为图片的 alt 属性。
testString: assert(code.match(/val\.altText/g));
添加代码以在`img`标签中使用`imageLink``altText`属性。
# --hints--
你应该使用`imageLink`属性来显示图像。
```js
assert(code.match(/val\.imageLink/g));
```
</section>
应该用 `altText` 做为图片的 alt 属性。
## Challenge Seed
<section id='challengeSeed'>
<div id='html-seed'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req=new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
json.forEach(function(val) {
html += "<div class = 'cat'>";
// 在这行下面添加代码
// 在这行上面添加代码
html += "</div><br>";
});
document.getElementsByClassName('message')[0].innerHTML=html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message box">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```js
assert(code.match(/val\.altText/g));
```
</div>
# --solutions--
</section>
## Solution
<section id='solution'>
```html
<script>
document.addEventListener('DOMContentLoaded', function(){
document.getElementById('getMessage').onclick = function(){
const req = new XMLHttpRequest();
req.open("GET",'/json/cats.json',true);
req.send();
req.onload = function(){
const json = JSON.parse(req.responseText);
let html = "";
json.forEach(function(val) {
html += "<div class = 'cat'>";
// Add your code below this line
html += "<img src = '" + val.imageLink + "' " + "alt='" + val.altText + "'>";
// Add your code above this line
html += "</div><br>";
});
document.getElementsByClassName('message')[0].innerHTML = html;
};
};
});
</script>
<style>
body {
text-align: center;
font-family: "Helvetica", sans-serif;
}
h1 {
font-size: 2em;
font-weight: bold;
}
.box {
border-radius: 5px;
background-color: #eee;
padding: 20px 5px;
}
button {
color: white;
background-color: #4791d0;
border-radius: 5px;
border: 1px solid #4791d0;
padding: 5px 10px 8px 10px;
}
button:hover {
background-color: #0F5897;
border: 1px solid #0F5897;
}
</style>
<h1>Cat Photo Finder</h1>
<p class="message">
The message will go here
</p>
<p>
<button id="getMessage">
Get Message
</button>
</p>
```
</section>