写点什么

用 Svelte 实现响应式、反应式的动画数据可视化

  • 2020-11-21
  • 本文字数:2105 字

    阅读完需:约 7 分钟

Tom Fevrier 和 Matthias Stahl 最近向 Svelte 社区介绍了使用 Svelte 实现响应性、交互式和动画数据可视化的技术。

在 Svelte Society 组织的一次演讲中(基于数据的Svelte和D3可视化),Tom Fevrier,法国金融报纸《回声报》的图片记者,用 Svelte 从无开始实现了两个动画响应式图形。

他演示的响应式曲线可以在这里看到:

图形动画可以在这里看到:

Fevrier 解释说,背后的核心思想是利用了 D3 和 Svelte。D3 有一组用于图形可视化的函数,用来计算尺度、插值、形状等。另一方面,Svelte 负责处理图形可视化的模块化(通过组件)、交互性(事件处理)、反应性和响应性(通过数据绑定)。

Fevrier 进一步解释说,开发人员可以借助 Svelte 将命令式 D3 代码转换成声明式 Svelte 代码。Fevrier 通过以下的 D3 代码来说明他的想法:

d3.selectAll('circle')  .data(data).enter()  .append('circle')  .attr('cx', d => xScale(d.a))  .attr('cy', d => xScale(d.b))  .attr('r', d => radiusScale(d.c))  .attr('fill', 'rebeccapurple')
复制代码

转成 Svelte 代码:

{#each data as d}  <circle    cx = {xScale(d.a)}   cy = {xScale(d.b)}   r = {radiusScale(d.c)}   fill = 'rebeccapurple'   >{/each}
复制代码

虽然 D3 可以处理自己的动画和交互,并对可视化数据中的变化作出反应,但 Fevrier 表示,相应的 D3 API(例如update)的复杂性比 Svelte 的更高。

窗口大小的响应能力可以通过灵活的 Svelte 数据绑定轻松实现。开发者可以使用 Svelte 内置的动画、运动和转换API 来实现流畅的动画,这些动画利用 CSS 而不是 JavaScript——它们不会阻塞主线程。开发人员还可以利用 Svelte 提供的模块化将复杂的图形分解为可重用的组件。

上面的代码生成的气泡图是由散点图组件和可重用轴组件组成的。散点图组件的代码如下:

<script>	import { scaleLinear, scaleLog, scaleSqrt } from 'd3-scale';	import { extent } from 'd3-array';	import { select } from 'd3-selection';	import Axis from './Axis.svelte';	export let data;	const height = 400;	const margin = 40;	let width;	$: xScale = scaleLog()		.domain(extent(data, d => +d.gdp / +d.population))		.range([margin, width - margin]);	$: yScale = scaleLinear()		.domain(extent(data, d => +d.life_expectancy))		.range([height - margin, margin]);	$: radiusScale = scaleSqrt()		.domain(extent(data, d => +d.population))		.range([2, 50]);	const reveal = (node, { duration }) => {		const radius = select(node).attr('r');		return {			duration,			tick: (t) => select(node).attr('r', t * radius)		};	}</script><div class='scatter-plot' bind:clientWidth={width}>	{#if width}		<svg width={width} height={height}>			<Axis {width} {height} {margin} scale={xScale} position='bottom' />			<Axis {width} {height} {margin} scale={yScale} position='left' />			{#each data as d}				<circle					cx={xScale(+d.gdp / +d.population)}					cy={yScale(+d.life_expectancy)}					r={radiusScale(+d.population)}					fill='rebeccapurple'					in:reveal={{ duration: 1000 }}				/>			{/each}		</svg>	{/if}</div><style>	circle {		opacity: 0.9;	}</style>`
复制代码

在上面的代码示例中,bind:clientWidth 确保宽度变量始终随图形元素的大小而变化,从而可以在窗口的大小发生变化时更新图形(响应性)。 SVG 原语的 in:reveal 参数实现了相应的动画效果。这里使用 D3 来计算数据的域、轴的比例以及选择图形 DOM 节点。

代码中使用了d3-fetch来导入 CSV 格式的数据,使用d3-axis、d3-selection、d3-array计算可视化数据的域和范围,以及使用d3-shape和d3-scale来计算线性尺度、对数尺度和平方尺度。

该演示可以在线获得,实现代码可以在GitHub上找到。读者可以观看包含大量额外技术细节的完整演讲。

在2020年Svelte峰会的一次演讲中,Matthias Stahl 提供了一个使用 Svelte 实现高级数据可视化的示例——这次没有使用 D3。

虽然这次的可视化更加高级,但 Stahl 也只是使用了类似的 Svelte API 和技术。Stahl 的可视化示例还具有交互性,因为当用户在图形给定实体上移动鼠标或单击鼠标时,它会做出反应。Stahl 还使用了 Svelte 组件(一个 Slider 组件)来实现可重用性和模块化,即 Svelte 动画和转换 API。Stahl 还使用事件分派实现组件之间的通信和 Svelte 的 use 指令。

这个可视化项目,叫作外部干扰属性跟踪器(Foreign Interference Attribution Tracker),也可以在线访问。实现代码可以在GitHub上找到。Stahl 使用 Svelte 和 D3 创建的高级可视化示例(例如机票价格或儿童死亡率)也可以在线上找到。

对使用 Svelte 进行数据可视化感兴趣的开发人员也可以看一下Pancake,这是一个 Svelte 实验性图表库,由 Svelte 的作者 Rich Harris 创建。Pancake 致力于在不使用 JavaScript 的情况下实现响应式图表。

Svelte 峰会是一个关于 Svelte 的虚拟会议。2020 年的峰会于 10 月在网上举行。完整的演讲清单将在 Youtube 的Svelte Scociety频道发布。

原文链接:

Animated, Responsive, and Reactive Data Visualization with Svelte