我试图用svelte reactive语句制作一个简单的d3力定向图,但显然,它不起作用。
第一个例子,这是我制作图(working REPL)的最简单方法:
<script>
import * as d3 from 'd3'
import { onMount } from 'svelte'
import data from './data.json'
let svg,
width = 500,
height = 400,
links, nodes
let simulation = d3.forceSimulation(data)
</script>
<svg
bind:this={svg}
width={width}
height={height}
viewBox="{-width/2} {-height/2} {width} {height}"
>
{#each data as node}
<g class="g-nodes" >
<circle bind:this={nodes}
fill="cornflowerblue"
r="5"
cx={node.x}
cy={node.y}
></circle>
</g>
{/each}
</svg>
第二个例子,我想用reactive语句添加一些force,比如说forceX,它不起作用,直到我在.tick()(working REPL)中添加simulation.tick(100)
或任何> 0的数字:
<script>
// the before part is still the same
let simulation = d3.forceSimulation(data)
$: simulation.force("x", d3.forceX(0)) // not working, the circle stay at the initial position
$: simulation.tick(100) // the force worked, but not animating from the initial position
</script>
<!-- the rest of svg is still the same -->
第三个例子,我尝试了.on(“tick”)函数。函数被触发(我只给予了一个console.log
来测试tick
是否工作),但我不知道如何将修改后的数据传递给{#each}
块。查看update函数中的console.log(data),x
和y
的数据在每一个tick都在改变,但并没有更新实际的circle
位置。(working REPL):
<script>
// the before part is still the same
let simulation = d3.forceSimulation(data)
function update() {
console.log(data)
return data // I don't know if it's the correct way, but still not working tho
}
$: simulation.force("x", d3.forceX(0))
$: simulation.on("tick", update)
</script>
<!-- the rest of svg is still the same -->
data.json
[
{value: 10},
{value: 12},
{value: 15},
{value: 8},
{value: 7},
{value: 12},
{value: 25},
{value: 20},
{value: 16},
{value: 13},
{value: 5},
{value: 7},
{value: 8},
{value: 10},
{value: 12},
{value: 14},
{value: 24},
{value: 23},
{value: 22},
{value: 11},
]
1条答案
按热度按时间stszievb1#
解决步骤3中问题的最简单方法是声明一个
displayData
数组,在update函数中将data
复制到displayData
中,并在displayData
上迭代#each
块。data
是一个导入变量,你不能直接重新分配给它,因为你不能重新分配给它,它不是React性的,data
更新不会触发重新渲染。通过在
update
函数中将data
赋值给displayData
(该函数将在每个tick上运行),您将触发#each
块的重新渲染(假设您现在迭代displayData
)。Working REPL