简单了解d3的使用,练手个柱状图
D3.js是一个JavaScript库,其将DOM对象(HTML, SVG,或Canvas elements)和数据能很好的对应 (数据驱动),从而数据可视化非常出色。
本文简单的了解下使用,大致知道概念和能力边界,如果需要,再投入更大的精力深入研究。
选择器
类似 jQuery的选择器之后,D3的选择器直接可以设置元素属性:
<div class="box"> <p>1</p> <p>2</p> </div> <script src="https://d3js.org/d3.v7.min.js"></script> <script> console.dir(d3); d3.select('.box') .selectAll('p') .style('color', 'red') .style('background-color', '#f5f5f5'); </script>
动态属性
D3的强大之处是,动态属性设置,其可跟数据绑定,然后根据数据设置属性
d3.select('.box') .selectAll('p') // 根据索引设置颜色 .data([11, 22]) .style('color', (d, i) => (i % 2 ? '#f69' : '#69f')) .text((d) => d + 1);
网络异常,图片无法展示
|
enter 和 exit
可以用enter
为新的数据创建新的节点 ,用exit
移除不需要的节点。
enter 的例子
使用enter
的例子,假设先只有里一个 p。
<div class="box"> <p></p> </div> <script> const pEnter = d3 .select('.box') .selectAll('p') .data([11, 22, 33, 44]) // 填充的是已存在的节点 .text((d) => d) .enter() .append('p'); console.log(pEnter); // 填充的新增的节点 pEnter.text((d) => d); </script>
网络异常,图片无法展示
|
这里注意,enter 会根据数据的长度,补充新的节点,也只能控制新的节点。所以填充数据的时候,一定分清旧节点和新节点,因为都需要填充。
网络异常,图片无法展示
|
打印了下,append('p')
之后,pEnter
的组里之前的节点位置显示为empty
,所以数据填充的时候会跳过。
exit 的例子
使用exit
的例子,假设先有 3 个p
。
<div class="box"> <p></p> <p></p> <p></p> </div> <script> const pExit = d3 .select('.box') .selectAll('p') .data([11, 22]) .text((d) => d) .exit(); console.log(pExit); pExit.remove(); </script>
网络异常,图片无法展示
|
网络异常,图片无法展示
|
exit 会将数量相同的节点,在组里显示为empty
,而多余的节点正常显示,remove 的时候,去掉的就是多余结点。
神奇的 join:简化exit和enter
enter 和 exit 会根据,数据的数量增删节点的数量,但合并或者增减节点的时候,就会增加额外的逻辑。
将上面例子的逻辑,抽离出来,假设隔段时间时间变化,那么将变成如下
<div class="box"> <p></p> <p></p> <p></p> </div> <script> function show(dataset) { const p = d3.select('.box').selectAll('p').data(dataset); // 先删除多余节点,remove之后的返回的并不是原选择器节点,所以需要额外写这行 p.exit().remove(); // 已有节点填充数据 p.text((d) => d) // 新增节点填充数据 .enter() .append('p') .text((d) => d); } // 第一次数据 show([1, 2, 3, 4]); // 第二次数据 setTimeout(() => { show([11, 22, 33, 44, 55]); }, 2000); // 第三次数据 setTimeout(() => { show([44, 55]); }, 4000); </script>
用户要始终小心,数据和节点是不是一一对应,很容易出错。
join 就简化这个问题,会自动增删节点,统一节点之后,再进行统一操作。
function show(dataset) { const p = d3.select('.box').selectAll('p').data(dataset); // enter、update、exit统一了节点之后,再统一操作 p.join( (enter) => enter.append('p'), (update) => update, (exit) => exit.remove() ).text((d) => d); }
动画效果 transitions
css 的transition
同样适用于 d3。
比如让字体颜色,有个动画效果,过渡到别的颜色
<div class="box"> <p>1</p> <p>2</p> </div> <script> d3.select('.box') .selectAll('p') .transition() .duration(500) .style('color', '#f69'); </script>
写个简单的 bar
svg
我没咋学,就不秀svg
画图了,当然svg
是最合适的.
其实假设,上面的 p 的宽度就是数据的话,easy 啦
function show(dataset) { const p = d3.select('.box').selectAll('p').data(dataset); p.join( (enter) => enter.append('p'), (update) => update, (exit) => exit.remove() ) .text((d) => d) // 写样式就行 .style('width', (d) => `${d}px`) .style('height', '20px') .style('background-color', 'steelblue') .style('text-align', 'right') .style('color', '#fff') .style('font-size', '10px'); } show([111, 222, 333, 444]);
网络异常,图片无法展示
|