在Svelte中使用Flubber.js渲染GeoJSON图形报错求助
问题:Svelte + Flubber.js 图形变形报错处理
问题背景
我尝试用Svelte和Flubber.js复刻Flubber官方的GeoJSON图形变形示例,不依赖D3,参考了使用tweened实现插值的示例。
现有实现代码
<script> import { interpolate } from 'flubber'; import { feature } from 'topojson'; import { tweened } from 'svelte/motion'; import * as eases from 'svelte/easing'; import wards from '$lib/Wards/shapes/map.topo.json'; const shape = tweened(undefined, { interpolate, easing: eases.cubicInOut, duration: 400, }); let places = feature(wards, wards.objects.states).features.map(function (d) { return d.geometry.coordinates[0]; }); // 转换多边形坐标为字符串格式 places = places.map(function (d) { return d.map(function (d) { return d.join(','); }); }); let selected = 0; $: $shape = places[selected]; </script> {#each Object.keys(places) as key} <button class:selected="{selected === key}" on:click="{() => (selected = key)}" > {key} </button> {/each} <main> <svg viewBox="0 0 960 500"> <path d="{$shape}"></path> </svg> </main>
控制台报错信息
Error:
attribute d: Expected moveto path command ('M' or 'm'), "77.4618079999067…". Uncaught TypeError: All shapes must be supplied as arrays of [x, y] points or an SVG path string.
示例合法的形状格式:
[[0, 0], [10, 0], [10, 10]]
"M0,0 L10,0 L10,10Z"
错误原因与解决方法
错误原因
- Flubber参数格式不符:你把原始的
[x,y]坐标数组转成了字符串数组(如["77.46,xxx", "xxx,xxx"]),但Flubber的interpolate函数只接受二维坐标数组或完整SVG路径字符串,这种格式不被识别。 - SVG路径指令缺失:SVG的
path元素d属性必须以M(移动到起点)开头,用L等指令连接坐标点,结尾可选Z闭合路径。直接传递坐标字符串会缺少这些必要指令,导致路径解析失败。
修正后的代码
<script> import { interpolate } from 'flubber'; import { feature } from 'topojson'; import { tweened } from 'svelte/motion'; import * as eases from 'svelte/easing'; import wards from '$lib/Wards/shapes/map.topo.json'; // 将坐标数组转换为标准SVG路径字符串 const coordsToPath = (coords) => { if (!coords) return ''; return `M ${coords[0].join(' ')} ${coords.slice(1).map(p => `L ${p.join(' ')}`).join(' ')} Z`; }; const shape = tweened(undefined, { interpolate, easing: eases.cubicInOut, duration: 400, }); // 保留原始二维坐标数组,不做字符串转换 let places = feature(wards, wards.objects.states).features.map(d => d.geometry.coordinates[0]); let selected = 0; $: $shape = places[selected]; </script> {#each Object.keys(places) as key} <button class:selected="{selected === key}" on:click="{() => (selected = key)}" > {key} </button> {/each} <main> <svg viewBox="0 0 960 500"> <path d="{coordsToPath($shape)}"></path> </svg> </main>
修改说明
- 新增
coordsToPath工具函数:将Flubber插值输出的坐标数组转换为符合SVG规范的路径字符串,确保包含M起点指令、L连线指令和Z闭合指令。 - 移除坐标字符串转换代码:保留原始的
[x,y]二维数组格式,让Flubber的interpolate函数能正确处理插值逻辑。 - 动态生成路径:在
<path>的d属性中调用coordsToPath,将插值后的坐标数组转为可用的路径指令。
内容的提问来源于stack exchange,提问作者Aman
相关产品推荐
相关产品推荐

