使用 Vue 和 D3 进行数据可视化:数星星(第 2 部分)
您可以在此处找到本文的第一部分。
如果你跳过了第 1 部分,这里是开始的代码 😉
我们要建造什么?
在本文中,我们将使用 D3 数据缩放功能改进我们的星型示例。缩放函数是 JavaScript 函数,其功能如下:
- 接受输入(通常是数字、日期或类别)并
- 返回一个值(例如坐标、颜色、长度或半径)。
它们通常用于将map
数据值转换(或)为可视变量(例如位置、长度和颜色)。这样,我们可以快速将任何初始数据集“绘制”为 SVG。
因此,我们将把星星的“视觉效果”映射到具体的数据值。在文章的结尾,我们的星星看起来会是这样的:
缩放星半径
第一个显而易见的问题是:为什么我们需要缩放半径?我们不能像上一篇文章中对射线那样,直接使用不经过缩放的值吗?
原因是我们希望限制星形的外半径,而输入数据值的变化范围却很大。D3 会计算比例,并按比例缩放星形半径。
第一次迭代中,假设输入值从 10 到 1000,但我们希望显示一个最大半径为 250px 的星星。为了执行计算,我们将使用 D3scaleLinear
方法。
scaleLinear
根据指定的定义域和值域构建一个新的连续比例尺。每个值域值 y 可以表示为定义域值 x 的函数:y = mx + b。(D3 Wiki)
首先,让我们删除硬编码outerRadius
,data
并创建一个新computed
属性来计算它。相反,我们将向radius
数据添加一个属性;它将作为我们的输入值。
data() {
return {
radius: 300,
rays: 8,
};
},
computed: {
outerRadius() {
return this.radius
},
...
},
所以,目前outerRadius
只返回我们输入的内容radius
。现在,让我们添加一些缩放比例!首先,我们需要scaleLinear
从 D3 导入方法:
import { lineRadial } from 'd3-shape';
import { scaleLinear } from 'd3-scale';
我们需要使用scaleLinear
方法定义一个缩放函数,然后我们需要使用输入radius
作为参数来调用该函数:
computed: {
outerRadius() {
const scale = scaleLinear()
.domain([10, 1000])
.range([5, 250]);
return this.radius
},
...
},
这里发生了什么?我们提供了一个domain
,scaleLinear
它是我们输入值将要变化的范围。至于range
,它就是我们作为 所拥有的output
:我们期望我们的outerRadius
会在 5px 到 250px 的范围内变化。
现在我们可以传递radius
给scale
函数:
computed: {
outerRadius() {
const scale = scaleLinear()
.domain([10, 1000])
.range([5, 250]);
return scale(this.radius)
},
...
},
结果,我们将得到如下结果:
尝试将radius
属性更改为 500 或 1000,您将看到星星的大小如何增长。
现在,类似于射线,让我们添加一个输入来动态更改星形半径。在我们的 中template
,让我们添加
<div class="range-input">
<label for="radius">Radius</label>
<input name="radius" type="range" min="10" max="1000" v-model="radius" />
</div>
这样,我们就将radius
数据属性绑定到了输入字段值。
设计应用程序
现在我们可以改变恒星的半径和射线量,但它仍然保持着暗绿色。如果我们能改进一下呢?如果我们的恒星是一颗真正的恒星,它的颜色会根据温度成比例地从红色变为蓝色。我们能创建一个能实现同样效果的刻度尺吗?有了 D3,答案显而易见😊。
但在开始之前,我们先来设计一下应用程序的样式。首先,我们将滑块移动到图片的右侧。为此,我们需要稍微修改一下模板:
<template>
<section class="wrapper">
<svg width="500" height="500">
<path
class="radial"
:d="radialData"
transform="translate(250, 250)"
fill="green"
></path>
</svg>
<aside>
<div class="range-input">
<input name="rays" type="range" min="4" max="60" v-model="rays" />
<label for="rays">Rays</label>
</div>
<div class="range-input">
<input
name="radius"
type="range"
min="10"
max="1000"
v-model="radius"
/>
<label for="radius">Radius</label>
</div>
</aside>
</section>
</template>
让我们为该style
部分添加一些样式:
<style lang="scss">
.wrapper {
display: flex;
align-items: center;
}
aside {
padding-left: 20px;
.range-input {
display: flex;
align-items: center;
margin-bottom: 10px;
input {
margin-right: 10px;
}
}
}
</style>
现在我们的应用程序看起来更加结构化:
另外,我们希望我们的星星颜色更浅一些,就像……嗯,像真正的星星一样!我们先用深蓝色的矩形给它加上深色背景,然后暂时把星星的颜色改成白色。
<svg width="500" height="500">
<rect width="100%" height="100%" fill="#0e0432" />
<path
class="radial"
:d="radialData"
transform="translate(250, 250)"
fill="white"
></path>
</svg>
现在我们可以玩改变星星颜色的游戏了!
创建星星颜色的自定义比例
虽然 D3内置了颜色插值器,但我们想构建一个简单的。我们将接受 0 到 100 之间的输入值,并分别定义 0、25、50、75 和 100 分的颜色。D3 足够智能,可以为介于 0 和 100 分之间的值插入颜色。
第一步,让我们创建一个新data
属性 -heat
并将其设置为 5:
data() {
return {
radius: 300,
rays: 8,
heat: 5,
};
},
接下来,让我们创建一个computed
用于星星颜色计算的新属性:
starColor() {
return this.heat
},
最后我们准备创建一个新的量表:
starColor() {
const myColor = scaleLinear()
.domain([0, 25, 50, 75, 100])
.range(['#ff7665', '#ffb469', '#ffe876', '#fff', '#99cdff']);
return myColor(this.heat);
},
现在,我们已经准备好将星形颜色添加到 SVGpath
fill
属性中,而不是静态white
颜色。让我们在那里创建一个动态绑定:
<path
class="radial"
:d="radialData"
transform="translate(250, 250)"
:fill="starColor"
></path>
我们的星星变了颜色!
我们尝试将heat
数据属性改为 90,星星就会变成浅蓝色。为了看起来更美观,我们可以创建一个从白色到当前星星颜色的渐变色:
<svg width="500" height="500">
<defs>
<radialGradient id="starGradient">
<stop offset="2%" stop-color="white" />
<stop offset="95%" :stop-color="starColor" />
</radialGradient>
</defs>
...
</svg>
现在我们可以用渐变色来填充星星,而不是纯色:
<svg width="500" height="500">
<defs>
<radialGradient id="starGradient">
<stop offset="2%" stop-color="white" />
<stop offset="95%" :stop-color="starColor" />
</radialGradient>
</defs>
<rect width="100%" height="100%" fill="#0e0432" />
<path
class="radial"
:d="radialData"
transform="translate(250, 250)"
fill="url(#starGradient)"
></path>
</svg>
现在我们的明星看起来真的很好看:
剩下的最后一件事是添加与之前射线和半径相同的输入滑块:
<div class="range-input">
<input name="heat" type="range" min="0" max="100" v-model="heat" />
<label for="heat">Heat</label>
</div>
好了,我们准备开始吧!你可以在这里找到图表组件的最终代码。
下一步是什么?
在第三部分中,我们将创建整个星座,而不是单颗星星!并且我们将可视化一个真实的 Vue 仓库数据集:
文章来源:https://dev.to/n_tepluhina/data-visualizations-with-vue-and-d3-counting-stars-part-2-10ig