javascript - 如何更新可重复使用的嵌套圆环图?
问题描述
我有一个具有数据更新功能的可重复使用图表——遵循 Rob Moore 的这篇文章的建议:https: //www.toptal.com/d3-js/towards-reusable-d3-js-charts——我是叫披萨。
Pizza 是一个嵌套的甜甜圈图。它看起来像一个带有同心圆环的饼图。我想添加一个交互,用户可以点击饼图的一个切片,所选切片将展开以填充整个饼图。
该图表有两个 setter 函数:.data() 和 .numberOfRings()。
Pizza.data( dataArray ).numberOfRings( n ) 生成具有n 个同心环和dataArray.length多个切片的图表,其中dataArray是整数数组。
n个dataArray副本被传递给 d3.pie() 以确定n 个切片中每个最终弧的 startAngle 和 endAngle 。然后 pie 返回的对象根据它们的索引分配有 outerRadius、innerRadius 和其他一些有用的属性:
const ringSet = [...Array(numberOfRings).keys()].reverse()
const sliceGenorator = Object.fromEntries(ringSet.map((x, i) => [i,
data]))
const pie = d3.pie().sort(null)
const arc = d3.arc()
let arcs = d3.values(sliceGenorator).map((d, i) =>
pie(d).map((x, v) =>
({
...x,
arcSlice: 'slice_' + v,
arcRing: 'ring_' + i,
innerRadius: cWidth * i,
outerRadius: cWidth * (i + 1),
id: 'ring' + i + '_' + 'slice' + v
})));
然后将这些对象传递给弧生成器并附加到 svg 组。
const flatArcs = arcs.flat()
const paths = svg.selectAll('path.arc')
.data(flatArcs)
.enter()
.append('path')
.attr('class', 'arc')
.attr('d',d => arc(d))
.attr('id', d => d.id)
.attr('fill', d => function that colors slices)
我的想法是用索引数组来更新图表数据,如下图:
let data = [30, 22, 8, 10]
//create an instance of the chart. call it 'pizza'
const pizza = pizzaChart()
.numberOfRings(5)
.data(data);
//render the pizza into the div
d3.select('#container')
.call(pizza)
//returns an index array
function selected(d) {
let zeros = new Array(data.length).fill(0);
zeros[d.index] = 1;
return zeros}
//pass an index array to pizza as the data update
d3.selectAll('path.arc')
.on('click', d => pizza.data(selected(d)))
假设用户选择切片 1,然后将indexArray = [0, 1, 0, 0] 传递给比萨饼的 updateData 函数,该函数运行与上述相同的过程,生成一个新的弧形对象数组,其起始角度和结束角度已被计算从indexArray中的值。
然后路径以弧 id 作为键更新图表,以证明对象的恒定性。
// update the data and pass in the arc id's as a key
const updatePaths = d3.selectAll('path.arc')
.data(updateArcs.flat(), d => d.id)
updatePaths.enter()
.append('path')
.attr('class', 'arc')
.attr('d',d => arc(d))
.attr('stroke', '#334646')
.attr('id', d => d.id)
.attr('fill', d => function to color code by slice)
updatePaths.exit().remove();
我希望所选切片中的弧将使用 startAngle = 0 和 endAngle = 2*PI 重新渲染,而其他弧将使用 StartAngle = 0 和 endAngle = 0 重新渲染。因此所选切片将填充图表,而其他切片将折叠。但什么也没有发生。
我最终会添加一个动画过渡,但我只想在我从图表中得到预期的行为后才这样做。
如果我console.log(updatePaths.data())
看到预期的数据。
我在错误的轨道上吗?我错过了一些明显的东西吗?
任何帮助将不胜感激
这是我的完整代码的链接:
解决方案
您根本没有更新现有项目 - 您的所有操作都是在选择新项目时进行的updatePaths.enter()
,而在任何操作时都没有updatePaths
。
我添加了一个合并,它开始做我认为你想要的事情
updatePaths.enter()
.append('path')
//actions for only new items; things that never change
.attr('class', 'arc')
.attr('stroke', '#334646')
.attr('id', d => d.id)
.merge(updatePaths)
//actions for both new and existing items
.attr('d',d => arc(d))
.attr('fill', d => sliceColor.range(pallet[d.index])(arcRingValue(d)))
推荐阅读
- iis - 发生指定错误日志时如何自动回收应用程序池?
- java - RecyclerView 在整个 View 中只显示一个值
- javascript - 如何通过 pubsub 在 shell 应用程序和微应用程序(前端)之间安全通信
- python - 将第一段从 infile 打印到 outfile
- java - 将格式错误的 JSON 列表解析为对象:使用 Java 解析的最佳实践
- r - 当点根据类别着色时,在散点图中使用 plotlyProxy 重新设置跟踪的样式是不稳定的
- azure - 允许用户指定偏移量/时间戳来配置事件中心的起点
- asp.net-core - 如何从 asp.net API 请求 Google Drive 访问权限
- oracle - AUTO-Synhronize 基于视图的表 - ORACLE DATABASES
- api - MarkLogic - API 请求和恢复数据库