D3入门——使用Canvas渲染

2,250 阅读3分钟

D3入门——基础介绍

D3入门——实现一个柱图

根据上两章的内容你就可以知道d3的的基础知识和基本使用,用这些功能可以做出很多基本的图形了,不过D3的能量远不仅仅于此。接下来我们来了解使用Canvas渲染D3绘制的图形。

D3最重要的部分就是data-join数据绑定了,使用SVG很容易把数据绑定到元素上对他进行属性的更改和更新都很容易。而Canvas画布只有像素点是无状态的。我们选择不了画布上的元素进行更新。对于Canvas的局限性,这里提出了一些解决方案。

一、数据绑定

我们习惯join数据后append对应的元素然后就逐个设置样式,如果是使用Canvas每次更新都需要直接根据全量的数据数据来绘制画布。

data.forEach(function(d) {
    context.beginPath()....
})
复制代码

但是在一些元素量非常大的情况下我们只能用Canvas来渲染,一般的解决方法是使用虚拟Dom来模拟data-join,然后我们就可以进行各种D3的操作。

const vDOm = d3.select(document.createElement("custom"));
cosnt bars = vDom.selectAll(".bar").data(data).enter()....
复制代码

这个例子就是在Canvas中模拟data-join的过程。

二、交互事件

Canvas最主要的问题是无状态,鼠标的交互只能获取在Canvas上的位置,没有元素的概念。不过也有几种方式去模拟点击元素的操作。

  1. 用四叉树来记录所有元素的位置然后根据点击的点去遍历。
  2. 在d3-force的布局中提供了.find方法,可以找到最接近鼠标点击的节点。
  3. 非常巧妙的办法,创建一个一样的画布,每个元素渲染一种颜色,通过点击到的像素点的颜色确定点击到的是那个元素。

ECharts主要也是用Canvas渲染,ECharts 使用的是 ZRender 底层渲染器。ZRender 提供了三种渲染器,分别是 Canvas,SVG 和 VML。下面是原文,总结一下就是根据鼠标位置计算出当前指向的元素。

在判断事件将被哪个图形元素响应的时候,我们会反向循环渲染列表,也就是先判断鼠标是否在位于屏幕前面的图形内。判断的时候,会先将鼠标坐标变换到图形坐标系。这是因为图形可能是经过平移旋转缩放的,甚至图形与图形之间还可能有组合的变换。将鼠标变换到图形坐标系后,我们就可以知道两者的相对关系,然后先根据包围盒做粗略的判断,再根据路径做精确的判断。如果鼠标在该图形内,则让这个图形进行事件分发与冒泡,如果不在,则对位于屏幕后方的元素一一判断。

这里有两种方式的实现demo,SVGCanvas

三、api支持

D3的大部分模块不是和Dom进行交互的比如说d3-hierarchy用来绘制层级结构的图就只是给出了每个点的位置和每条线的路径。

对于d3-selection、d3-transition模块我们可以通过操作虚拟Dom来转换成Canvas。

对于d3-axis就跟SVG强相关,他会自动帮你构建SVG的坐标轴,这就没办法了。

d3-path来绘制线图饼图地图非常有用,不过D3也允许提供一个context可以帮你绘制在Canvas画布上。demo

系列文章最后附上我的我的博客原文链接