d3 canvas
by lars verspohl
由拉斯·韦斯波尔
Let’s say you’re building a data visualization using D3 and SVG. You may hit a ceiling when you try to display several thousand elements at the same time. Your browser may start to puff under the weight of all those DOM elements.
假设您正在使用D3和SVG构建数据可视化。 当您尝试同时显示数千个元素时,可能会达到上限。 您的浏览器可能开始受所有那些DOM元素的压制 。
Well here comes HTML5 Canvas to the rescue! It’s much faster, so it can solve your browser’s puffing problems.
HTML5 Canvas来了! 它的速度要快得多,因此可以解决浏览器的膨胀问题。
But you may quickly find yourself daunted. Because D3 and Canvas works a bit differently from D3 and SVG — especially when it comes to drawing and adding interactivity.
但是您可能很快会发现自己感到恐惧。 因为D3和Canvas与D3和SVG的工作方式有些不同-尤其是在绘制和添加交互性方面。
But fear not — it’s not that complicated. Any experience you’ve had with building visuals with D3 and SVG — or approaching D3 with a different renderer — will help you tremendously.
但是不要担心-它并不那么复杂。 您使用D3和SVG构建视觉效果的任何经验(或使用其他渲染器接近D3的经验)都将极大地帮助您。
This tutorial built on the shoulders of giants who have already covered Canvas well. I learned these three tutorials by heart and I recommend you do, too:
本教程建立在已经很好地涵盖了Canvas的巨人的肩膀上。 我很认真地学习了这三个教程,我也建议您这样做:
Working with D3.js and Canvas: When and How from Irene Ros
使用D3.js和Canvas:来自Irene Ros的时间和方式
Needles, Haystacks, and the Canvas API from Yannick Assogba
Yannick Assogba的针,干草堆和Canvas API
Learnings from a D3.js addict on starting with Canvas from Nadieh Bremer
D3.js瘾君子从Nadieh Bremer 开始使用Canvas的学习
So why continue reading this, then? Well, when I want to learn something new, it helps me a great deal to look at the same subject from slightly different angles. And this tutorial is a slightly different angle.
那么,为什么还要继续阅读呢? 好吧,当我想学习新的东西时,从稍微不同的角度看同一主题对我很有帮助。 本教程是一个稍微不同的角度。
Also, this tutorial covers the three key steps: binding data, drawing elements, and adding interactivity — and it does all this in one go, with an added step-by-step manual to set you up.
此外,本教程涵盖了三个关键步骤: 绑定数据 , 图形元素和添加交互性 ,并且一步一步地完成了所有这些,并添加了逐步的手册来进行设置。
A grid of (many) squares. Their colours aren’t of any deep meaning but don’t they look pretty? The important bit is that you can update it (to cover binding and updating data), that it has many elements (up to 10,000 in order for canvas to pay out), and that you can hover over each square to show square-specific information (interactivity). You can play with it here on a full screen or here with all the code
(许多)正方形的网格。 它们的颜色没有任何深层含义,但是看起来不漂亮吗? 重要的一点是,您可以对其进行更新(以覆盖绑定和更新数据),其中包含许多元素(为了支付画布,最多可以包含10,000个),并且可以将鼠标悬停在每个正方形上以显示特定于正方形的信息(互动)。 您可以在这里全屏播放,也可以在 此处查看所有代码
Before we actually dive in, let’s quickly step back and grasp conceptually what we do when we create elements with D3 to draw them to the screen. Skip this if you just want to make things.
在我们真正涉足之前,让我们快速退后一步,从概念上掌握使用D3创建元素以将其绘制到屏幕上时的操作。 如果您只想制作东西,请跳过此步骤。
The first step when using D3 usually doesn’t involve drawing — it involves preparing all your elements you want to draw. It’s a bit like building some LEGO. You can rip open the box and start building something or you can look at the manual first and build it according to the blueprint. The manual is your mental model, a blueprint or recipe of what you want to build.
使用D3的第一步通常不涉及绘制-它涉及准备要绘制的所有元素。 这有点像建立一些乐高玩具。 您可以撕开盒子并开始制作东西,也可以先阅读手册并根据图纸进行制作。 该手册是您的心智模型,您想要构建的蓝图或配方。
What is D3’s model? Apart from the large number of helpful functions and methods that calculate positions, re-shape datasets (the layouts) and generate functions that draw, for example, paths for us, D3 has a model for how the elements’ lives should evolve on the screen. It has a certain way to think about the lifecycle of each element.
D3的型号是什么? 除了大量有用的函数和方法来计算位置,重整数据集(布局)并生成例如为我们绘制路径的函数之外,D3还提供了一个模型,用于说明元素的生活应如何在屏幕上演化。 它有一定的方式来考虑每个元素的生命周期。
Less ethereally, you inject data into a yet non-existent DOM, and D3 creates new elements of your choice as per the data you inject. Usually one element per datapoint. If you want to inject new data into the DOM you can do so and D3 identifies which elements have to be newly created, which elements are allowed to stay and which elements should pack up and leave the screen.
以较少的麻烦,您将数据注入到一个尚不存在的DOM中,并且D3根据您注入的数据创建您选择的新元素。 通常每个数据点一个元素。 如果要向DOM中注入新数据,则可以这样做,D3标识必须重新创建的元素,允许保留的元素以及应打包并离开屏幕的元素。
D3 is usually used in conjunction with SVG or sometimes with HTML-elements. In this orthodox case, you can see the data in the DOM when you choose to look at it through the console, for example. You can grab it, you can move it up or down the DOM and you can — importantly — add interactivity to each element you like to show, for example, a tooltip.
D3通常与SVG或HTML元素一起使用。 在这种传统情况下,例如,当您选择通过控制台查看数据时,便可以在DOM中看到数据。 您可以抓住它,可以在DOM上向上或向下移动它,并且可以(重要的是)向要显示的每个元素添加交互性,例如工具提示。
But — on the downside — you can’t show a lot of elements. Why? Because the more elements you push into the DOM, the harder the browser has to work to display them all. Let them also move around and the browser needs to re-calculate them constantly. The more knackered the browser gets the lower your frame rate or FPS (Frames Per Second), which measures how many frames the browser can paint each second. A frame rate of 60 is good and enables a fluid experience as long as no frames are missed — a frame rate of anything under 30 can equal a choppy ride. So when you want to show more elements, you can revert to canvas.
但是-不利的一面-您不能展示很多要素。 为什么? 由于您将更多元素放入DOM中,因此浏览器显示所有元素的难度就更大。 让它们也移动,浏览器需要不断地重新计算它们。 浏览器的技巧越多,您的帧速率或FPS(每秒帧数)就越低,该速率衡量浏览器每秒可以绘制多少帧。 只要不丢失任何帧,帧速率为60就是不错的选择,并能带来流畅的体验-帧速率低于30的任何帧都可以使您的行程更加震撼。 因此,当您想显示更多元素时,可以还原到画布。
Why canvas? Canvas is an HTML5 element which comes with its own API to paint on it. All elements drawn on the canvas element won’t manifest in the DOM and save a lot of work for the browser. They are drawn in immediate mode. This means the rendered elements won’t get saved in the DOM but your instructions draw them directly to a particular frame. The DOM only knows the one canvas element; everything on it is only in memory. If you want to change your canvas elements you have to redraw the scene for the next frame.
为什么要帆布? Canvas是HTML5元素,它带有自己的API可以在其上绘制。 canvas元素上绘制的所有元素都不会出现在DOM中,并且会为浏览器节省很多工作。 它们以立即模式绘制。 这意味着渲染的元素不会保存在DOM中,但是您的指令会将它们直接绘制到特定的框架。 DOM只知道一个canvas元素; 它上的所有内容仅在内存中。 如果要更改画布元素,则必须重新绘制下一帧的场景。
The problem with this is of course that you can’t communicate directly with these non-material elements living in memory. You have to find a way to talk to them indirectly. This is where the D3 model comes in as well as custom or ‘virtual’ DOM-elements. What you’ll do in principal is:
当然,这样做的问题是您无法直接与内存中的这些非物质元素进行通信。 您必须找到一种间接与他们交谈的方法。 这就是D3模型以及自定义或“虚拟” DOM元素出现的地方。 您将主要做的是:
Let’s do it.
我们开始做吧。
Before we start to code, let’s produce some data. Let’s say you want 5,000 datapoints. So let’s create an array with 5,000 elements, each of which is an object with just a single property value carrying the element’s index. Here’s how you create it with d3.range()
. d3.range()
is a D3 utility function, that creates an array based on its argument:
在开始编码之前,让我们产生一些数据。 假设您要5,000个数据点。 因此,让我们创建一个包含5,000个元素的数组,每个元素都是一个对象,只有一个带有元素索引的属性值。 这是使用d3.range()
创建它的方法。 d3.range()
是D3实用程序函数,它根据其参数创建一个数组:
var data = [];