函数本身作为数据绑定到图形
在处理复杂数据时,我们往往得不到最终的数据数组,D3支持将函数本身作为数据绑定到图形元素上。看下面的例子:
const someData = []
// 通过一个方法生成数据
const datum = (x) => 10 + x * x;
// 每个数据都是一个函数,并作为someData的元素
const newData = () => {
someData.push(datum)
return someData
}
代码中,datum 是一个生成单个数据的函数,newData 是多个函数的集合,我们把这个集合作为最终的数据绑定到图形上,如下:
const render = () => {
const divs = d3.select('#d3Container')
.selectAll('div')
.data(newData)
divs.enter().append('div').append('span')
divs.attr('class', 'v-bar')
.style('height', (d, i) => d(i) + 'px')
.select('span').text((d, i) => d(i))
divs.exit().remove()
}
重点关注 selectAll('div').data(newData) 和 (d, i) => d(i) ...
selectAll('div').data(newData) 实际上是图形集合调用 data() 方法 selection.data(Data)
这一步我们将数据和图形建立关系,newData 中的每一个元素都会在图形中得到引用。
接着在设置样式的方法中和设置文本内容的方法中,我们都用了一个函数
(d, i) => d(i) 第一个 d 参数是 newData 中的每一个元素,第二个参数 i 是 d 所在 newData 中的位置索引,很像 js中的 map 方法
但是 newData 中的每个元素都是一个函数 (x) => 10 + x * x ,所以在(d, i) => d(i) 中我们返回了一个函数,并传入了 i 作为参数, 当 i = 0 时, d(0) = 10 + 0 * 0 = 10,当 i = 1 时, d(1) = 10 + 1 * 1 = 11,当 i = 2 时, d(2) = 10 + 2 * 2 = 14,依此类推......
下面是全部代码以及最终的渲染效果,我在末尾加了 setInterval 模拟数据的不断增加,注意这里没有边界设定,重点演示D3中将函数作为数据绑定到图形上的过程。
D3.js 中函数本身作为数据绑定到图形元素上的例子
<script setup>
import { onMounted } from "vue";
import * as d3 from "d3";
const someData = []
const datum = (x) => 10 + x * x;
const newData = () => {
someData.push(datum)
return someData
}
const render = () => {
const divs = d3.select('#d3Container')
.selectAll('div')
.data(newData)
divs.enter().append('div').append('span')
divs.attr('class', 'v-bar')
.style('height', (d, i) => d(i) + 'px')
.select('span').text((d, i) => d(i))
divs.exit().remove()
}
onMounted(() => {
setInterval(() => {
render()
}, 1500)
})
</script>
<template>
<div id="d3Container" class="container">
</div>
</template>
<style lang="scss">
.container {
padding: 30px;
font-size: 20px;
width: 50vw;
height: 500px;
margin:auto;
background-color: #fbe9d5;
.v-bar {
display: inline-block;
width: 24px;
background-color: #4c6bf8;
font-size: 12px;
color: #fff;
margin-right: 12px;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
}
}
</style>