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></style>`
在上面的代码示例中,bind:clientWidth 确保宽度变量始终随图形元素的大小而变化,从而可以在窗口的大小发生变化时更新图形(响应性)。<circle> 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
领取专属 10元无门槛券
私享最新 技术干货