首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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

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

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

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

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

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

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

代码语言:javascript
复制
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 代码:

代码语言:javascript
复制
{#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 提供的模块化将复杂的图形分解为可重用的组件。

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

代码语言:javascript
复制
<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-axisd3-selectiond3-array计算可视化数据的域和范围,以及使用d3-shaped3-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

  • 发表于:
  • 本文为 InfoQ 中文站特供稿件
  • 首发地址https://www.infoq.cn/article/DqWE2g1YAdz2KOPf7jgQ
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券