gpt4 book ai didi

d3.js - 带间隙的路径转换 - 怎么做?

转载 作者:行者123 更新时间:2023-12-04 17:22:13 25 4
gpt4 key购买 nike

我画了一些有一些“差距”的折线图(路径)。我在间隙之间使用了一个技巧,然后插值不会出现在我的数据间隙之间。

例子:

pos, value
1,10
2,15
3,20
8,5
9,6
10,20

如您所见,我在位置 3 和 8 之间有一个间隙。这里我要做的是创建一个值为 0 的位置 4,以及一个值为 0 的位置 7。然后,每当我绘制折线图时,我都会得到正确的图表与我的差距。

现在,我需要在此折线图上进行转换。鉴于我有这个“差距黑客”,我的过渡并不漂亮:(
它以一种我不喜欢的方式移动线条。

我该怎么办 ?
在这种情况下,是否可以在不需要在我的间隙之间有很多 0 值的情况下进行转换?

我不想为我不需要表示的位置添加 0 值,否则我的数据库会增加很多并且我的可视化会很慢。

任何见解都受到高度赞赏。

最佳答案

在 update 函数中你需要做的第一件事是创建一个新的数据数组,填充位置变量的缺失值,同时保持值变量未定义。就像是:

var data = [/* Your original data table */];
//results of d3.tsv or whatever you use

var posRange = d3.max(data, function(d){return d.pos;});
//get the max and min pos values as a two-element array
var dataWithGaps = new Array(posRange[1] + 1 - posRange[0] );
//i.e., length of the array is the difference in position,
//plus 1 to include the last position
//(eg for positions 2-5 you need 4 elements 2,3,4,5, which is 5+1-2

var j=dataWithGaps.length;
while (j--){ //count down the length of the new array
dataWithGaps[j] = {pos:posRange[0]+j, value:NaN};
//create a valid position and undefined value
}
j=data.length;
while (j--){//scan through the data and copy over
d = data[j];
dataWithGaps[d.pos-posRange[0]].value = d.value;
//find the correct index in the new array, and set it's value
}

如果您的仓位是从 0 或 1 开始计数的整数,那么此代码可以大大简化,只需使用数组的索引作为您的仓位值。如果您的位置是时间戳或其他东西,则代码会变得更加复杂。

无论哪种方式,当您更新数据时,请务必检查范围是否已更改,因此是否需要填充 dataWithGaps 的开头或结尾。具有更多位置值的数组(带有 pushunshift )。然后重复最后两个循环。

现在到图形...

以下示例均以包含 NaN 的数字数组开头(not-a-number) 值作为间隙,其中数组的索引用作 x 坐标。

第一个例子,也许你已经这样做了,就是使用 d3 路径生成器函数的 .defined(function(d){}) method .这允许您指出哪些数据点应该是未定义的,d3 会自动将您的线分成围绕未定义点的线段。

达达! http://fiddle.jshell.net/9jTk4/2/ )

神奇的代码是这个链中的最后一条语句:
var drawLine = d3.svg.line()
.x(function(d,i) { return xScale(i); })
.y(function(d) { return yScale(d); })
.defined(function(d) {return !isNaN(d)});
//the line should be only be defined at points where the data value is not NaN
//use !isNaN(d.value) if your data values are objects

请注意,数据点是使用 SVG line markers 制作的。这样即使它们没有连接到任何东西,您也可以看到点,因为它们的邻居是未定义的。

(忏悔时间:我只在 之后才发现这个 我花了几个小时想出了一个自定义解决方案。幸运的是,我的额外时间没有浪费,因为 d3 默认方法存在缺陷......)

问题是当您添加过渡时。

Dum-da-DUM(不祥风琴和弦) http://fiddle.jshell.net/9jTk4/1/

D3 不能不知道从哪里开始过渡的新线段。如果您只在两个现有点之间添加一个新点,它会从前一个点平滑过渡。但是,如果您将多个点添加到间隙中,则它们会从数组中最后一个元素的位置开始——当您添加到行尾时,这可能会很好用,但看起来如果你要填补空白,那就太丑了。

过渡可能可以通过自定义 tween 修复函数,但是从头开始编写不会很简单。 (不过,如果有人确实想创建一个,可能值得将其作为一个拉取请求添加到 d3 标准库中。)

同时,看看我创建的这个替代方法(在我仔细阅读 d3 API 以发现它们已经解决了差距之前)。

达达!和 AlaKaZAM !!! http://fiddle.jshell.net/pwmA3/3/

除了平滑过渡外,它看起来与上一个版本非常相似,但实际上在构造上非常不同。它不是使用单个路径来表示整条线,而是使用一系列 svg:line元素,每个元素都绘制从前一个点(如果存在)到数据点的路径。

如果一个数据点不存在,它的绘图位置被插值,它的类被设置为触发 CSS 使线条消失,然后在给定有效数据时平滑过渡。行标记再次显示所有有效数据点,即使没有任何可链接的数据点。这是我为没有数据的点添加了“问号”线标记的版本,显示了它们的位置是如何插值的:
http://fiddle.jshell.net/pwmA3/4/

需要注意的一件事:为每个数据点使用线段而不是路径意味着浏览器需要跟踪更多的 DOM 对象。如果您有数百个数据点,这可能会减慢速度,所有用于插入缺失点的额外计算也可能会减慢速度。如果这成为一个问题,我建议使用带有 defined() 的 d3 折线图方法。选项(如第一个示例中所示),然后跳过转换。

关于d3.js - 带间隙的路径转换 - 怎么做?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20791251/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com