[apache/echarts]修复:放大时所有数据映射到一列

2024-05-11 944 views
9
这个公关有什么作用?

修复仅放大一列时,所有数据都映射到该数据上的错误。

已解决的问题
  • 修复#16746
  • 修复#16852
  • 修复#17014
之前的详细信息 :问题是什么?

该问题通常发生在放大到一个类别列时,然后所有数据都映射到同一列。为什么会出现问题可以参考这里:https://github.com/apache/echarts/issues/16746#issuecomment-1100036918

16746
放大之前 放大后
之前#16746 放大前#16746
16852
放大之前 放大后
之前2#16746 before2-zoomIn#16746
之后:这个 PR 中是如何修复的?

通过在存在错误的两个地方添加条件语句来解决该问题。现在,当范围[0] =范围[1]时,Echarts将正确处理项目的位置。

16746
放大之前 放大后
之前#16746 放大后#16746
16852
放大之前 放大后
之前2#16746 after2-zoomIn#16746

回答

2

结果看起来不错。但你能解释一下这里的策略吗?

4

我很抱歉我没有在公关和评论中解释得足够多。让我向您展示数据流,然后策略就会清晰。首先,我们放大到“b”类别,并且在此图表中仅放大“b”:

之前#16746

然后,Echarts 尝试在缩放后确定图表中“a”、“b”和“c”列的位置。所以extent这里是[1, 1]https://github.com/apache/echarts/blob/a5257e38ad7776c766879c83854b1faa2771a454/src/coord/Axis.ts#L122-L133 在第125行,我们输入normalize返回相对位置(0~1)的函数根据缩放前的位置的列('a'、'b'、'c' 分别为 0、1、2): https://github.com/apache/echarts/blob/a5257e38ad7776c766879c83854b1faa2771a454/src/scale /helper.ts#L129-L132 此时请记住extentis [1, 1],所以无论 isdata是什么,函数normalize都会返回 0.5,这意味着缩放后所有三列都位于图表的中间。为了解决这个问题,我将 return 更改为val - extent[0] + 0.5.这里的“a”、“b”、“c”,缩放前分别为 0、1、2,缩放后分别为 -0.5、0.5、1.5(位于 -50%、50%、150%)。 之前#16746

另外,另一个错误使我无法区分三列。在第 132 行,我们输入函数linearMap, subRangeis 0,因为 r0 = r1 = 320,这导致return (val - d0) / subDomain * subRange + r0无论 r0val是什么,都等于 r0。这意味着所有三列仍位于 320 (0.5 640)。 https://github.com/apache/echarts/blob/a5257e38ad7776c766879c83854b1faa2771a454/src/util/number.ts#L47-L100 为了解决这个问题,我添加了一个检查是否subRange为0,如果是则返回`(val - d0) / subDomain 2 r0 . WhensubRange is 0,r0` 恰好是图表长度的一半,0.5 640 = 320(subDomain此处 = 1)。因此(val - d0) / subDomain * 2 * r0= val * ChartLength 将是相应相对位置的绝对位置。

7

感谢您的解释。

为了解决这个问题,我将返回值更改为 val -extent[0] + 0.5。这里的“a”、“b”、“c”,缩放前分别为 0、1、2,缩放后分别为 -0.5、0.5、1.5(位于 -50%、50%、150%)。

这是一个很好的观点。这里的问题是,即使值超出范围,我们仍然返回范围内的值 0.5。更预期的行为是,当 val 小于程度[0] 时返回 < 0,当 val 大于程度[1] 时返回 > 1,以确保标准化值也超出范围 [0, 1]。 val - extent[0] + 0.5可以按顺序进行,其中 val 是整数。但当涉及到小数时,就失败了。结果可能仍在[0, 1]范围内。所以我认为val < extent[0] ? -0.5 : val > extent[0] ? 1.5 : 0.5会更普遍地解决它

为了解决这个问题,我添加了一个检查 subRange 是否为 0,如果是,则返回 (val - d0) / subDomain 2 r0。当 subRange 为 0 时,r0 正好是图表长度的一半,0.5 640 = 320(此处 subDomain = 1)。因此 (val - d0) / subDomain 2 r0 = val ChartLength 将是相应相对位置的绝对位置。

似乎非常底层方法的行为已更改以匹配上层逻辑。这不是解决问题的正确方法,并且可能会影响依赖此方法的其他代码。

0

所以我认为val < extent[0] ? -0.5 : val > extent[0] ? 1.5 : 0.5会更普遍地解决它

我同意这一点,将更新 PR。

似乎非常底层方法的行为已更改以匹配上层逻辑。

对于这一部分,我想和大家谈谈我的一些想法。首先,该功能linearMap是将valin映射domain到指定的range.当val是在指定的domain并且range只是一个点时,那么 yesval应该全部映射到 中的唯一值range。但如果val不在 中domain,从逻辑上讲,它不应该映射到 中的任何位置range。因此,当我添加条件if ((val < Math.min(d0, d1)) || (val > Math.max(d0, d1))),时,val承诺不会出现在其中domain,并且返回位于此处之外的值是有意义rangeval * chartWidth。基本上,我认为这个非常底层的方法有一个微小的逻辑问题,它直接导致了这里的错误。如果我们要在同一个地方使用相同的功能,我认为该错误无法修复。不过,如果你坚持认为这个功能最好不要碰。替代方案是我们在这里使用另一个函数来解决问题。但这会增加代码的冗余,因为该函数与此函数几乎相同并且linearMap仅在此处使用。

3

我的意思并不是要保持功能相同。相反,它应该被修复,但以一般的方式。例如,当我使用linearMap将任意值映射到颜色中的 alpha 时,会有什么行为?公式(val - d0) / subDomain * 2 * r0仍然有效并且可以解释吗?

5

相反,它应该被修复,但以一般的方式。

我同意你的看法。我刚刚浏览了代码并发现linearMap所有图表中都使用了它。所以回国(val - d0) / subDomain * 2 * r0确实不妥。从逻辑上讲,不在“域”中的“val”不应映射到“范围”中的任何位置。因此,我认为做到这一点的一种方法是返回undefinedif valnot in domain。这在逻辑上是正确的,但可能会导致致命错误并使 echarts 停止。另一种方法是在linearMap运行之前处理这种特殊情况。也就是检查extent是否为1点并且val超出domain,然后直接返回想要的结果而不运行linearMaphttps://github.com/apache/echarts/blob/a5257e38ad7776c766879c83854b1faa2771a454/src/coord/Axis.ts#L122-L133

您认为哪种方式更好?

9

另一种方法是在运行 LinearMap 之前处理这种特殊情况。也就是检查extent是否是一个点并且val是否超出域,然后直接返回想要的结果而不运行 LinearMap。

我会更喜欢这种方式,以尽量减少影响。但我仍然不确定解决方案以及这里应该返回什么值。

1

所以我刚刚更新了代码,现在的条件是

  1. extent只有一点;
  2. data不在域中

只会在 axis.ts/dataToCoord 处检查,因此不会影响 function linearMap。我仍然认为函数linearMap有逻辑问题,但我不确定如何返回一个range不造成风险的值。