AAChartKit-Swift icon indicating copy to clipboard operation
AAChartKit-Swift copied to clipboard

刷新数据的动画时间

Open watermelon520 opened this issue 7 months ago • 15 comments

我现在做折线图,维护一个 20 个元素(x, y)的队列,定时更新 x +1 的新数据来做滚动动画 chartView.aa_onlyRefreshTheChartDataWithChartModelSeries(elements, animation: true)

有没有办法控制这个滚动的动画时间呢? 我跟进去源码看到这里,我想着手动设置时间,发现并不可行,会让整条 y 轴都在蠕动 aaGlobalChart.update({ series: receivedSeriesArr }, true, false, { duration: 2000 } );

watermelon520 avatar Jul 21 '25 10:07 watermelon520

demo 中不是有专门的滚动刷新的使用示例吗? 参考一下看看

AAChartModel avatar Jul 21 '25 11:07 AAChartModel

我已经实现了滚动刷新功能,并且有动画。我现在希望更改滚动的动画时间

watermelon520 avatar Jul 22 '25 08:07 watermelon520

Highcharts 的内置的滚动刷新方法, 应该是支持设置动画时间的.

参考:

  • https://api.highcharts.com/class-reference/Highcharts.Series#addPoint

关键内容:

animation boolean | Partial.<Highcharts.AnimationOptionsObject>

只不过现在 AAChartKit-Swift 没有支持这个功能. 你可以模仿 AAChartView 的这个方法:

/// Add a new point to the data column after the chart has been rendered.
    /// The new point can be the last point, or it can be placed in the corresponding position given the X value (first, middle position, depending on the x value)
    /// Refer to https://api.highcharts.com/highcharts#Series.addPoint
    ///
    /// - Parameter elementIndex: The specific series element
    /// - Parameter options: The configuration of the data point can be a single value, indicating the y value of the data point; it can also be an array containing x and y values; it can also be an object containing detailed data point configuration. For detailed configuration, see series.data.
    /// - Parameter redraw: The default is true, whether to redraw the icon after the operation is completed. When you need to add more than one point, it is highly recommended to set redraw to false and manually call chart.redraw() to redraw the chart after all operations have ended.
    /// - Parameter shift: The default is false. When this property is true, adding a new point will delete the first point in the data column (that is, keep the total number of data points in the data column unchanged). This property is very useful in the inspection chart
    /// - Parameter animation: The default is true, which means that when adding a point, it contains the default animation effect. This parameter can also be passed to the object form containing duration and easing. For details, refer to the animation related configuration.
    public func aa_addPointToChartSeriesElement(
        elementIndex: Int,
        options: Any,
        redraw: Bool,
        shift: Bool,
        animation: Bool
    ) {
        var optionsStr = ""
        if options is Int || options is Float || options is Double {
            optionsStr = "\(options)"
        } else if options is [Any] {
            optionsStr = getJSONStringFromArray(array: options as! [Any])
        } else {
            let aaOption: AAObject = options as! AAObject
            optionsStr = aaOption.toJSON()
        }
        
        let javaScriptStr = "addPointToChartSeries('\(elementIndex)','\(optionsStr)','\(redraw)','\(shift)','\(animation)')"
        safeEvaluateJavaScriptString(javaScriptStr)
    }

AAChartView 类添加一个拓展方法, 来实现支持设置动画时间的功能.

AAChartModel avatar Jul 23 '25 01:07 AAChartModel

应该是我最开始的表述不够清楚。我重新表达一下,我已经找到了设置动画时间的方法 我从这个方法跟进去了

`

// 第一步
aa_onlyRefreshTheChartDataWithChartOptionsSeries

// 第二步
let jsStr = "onlyRefreshTheChartDataWithSeries('\(str)','\(animation)');"
safeEvaluateJavaScriptString(jsStr)

// 第三步
function onlyRefreshTheChartDataWithSeries(receivedSeries, animation) {
    let receivedSeriesArr = JSON.parse(receivedSeries);
    let animationBool = (animation === "true");

    aaGlobalChart.update({
        series: receivedSeriesArr
        },
        true, false, animationBool
    );
}

`

我只需要将 animationBool 修改为 { 'duration': 动画时间 } 就可以设置动画时间 但是不知道是不是 Highcharts 动画有 bug。我做折线图,一般当同屏显示的点的个数超过15,我更新点的时间,和做动画的时间,如果是一样的或者非常接近。比如说 3000 毫秒更新一个点,动画时间是 2800-3000 毫秒,这时候,折线在滚动的同时,就会出现奇怪的蠕动动画效果。 当我把动画时间设的小于更新时间多一点就不会出现这个蠕动效果,比如 2000-2500。 我自己的代码或者是直接修改 demo 中的滚动样例,都会出现这个问题。 具体效果我这里有视频文件 https://github.com/user-attachments/assets/00b3d7cd-4fea-4bbb-a3c6-8eb4ab723d8a

另外还有一个动画的优化问题,我是用 areaspline 模式,折线下方填充渐变色,当折线进行动画移动的时候,这个渐变色填充会存在滞后跟线移动的问题。 显示效果,我也弄了个视频文件 https://github.com/user-attachments/assets/3a665cc6-db75-4dcb-86cd-ade0d24bbdf3

不知道这两个问题能不能得到解决,谢谢

watermelon520 avatar Jul 25 '25 08:07 watermelon520

比如说 3000 毫秒更新一个点,动画时间是 2800-3000 毫秒,这时候,折线在滚动的同时,就会出现奇怪的蠕动动画效果。

这个看起来应该是 Y 轴坐标系一致在变化, 导致图表的坐标点也一直反复更新重绘, 最终导致的视觉上的蠕动的效果.

固定 Y 轴坐标不变应该能解决这个问题.

  • 示例代码如下:
        let aaOptions = aaChartModel.aa_toAAOptions()

        aaOptions.yAxis?
            .min(0)
            .max(100)

AAChartModel avatar Jul 29 '25 03:07 AAChartModel

另外还有一个动画的优化问题,我是用 areaspline 模式,折线下方填充渐变色,当折线进行动画移动的时候,这个渐变色填充会存在滞后跟线移动的问题。

这个问题我在 demo 中没复现出来.

AAChartModel avatar Jul 29 '25 03:07 AAChartModel

比如说 3000 毫秒更新一个点,动画时间是 2800-3000 毫秒,这时候,折线在滚动的同时,就会出现奇怪的蠕动动画效果。

这个看起来应该是 Y 轴坐标系一致在变化, 导致图表的坐标点也一直反复更新重绘, 最终导致的视觉上的蠕动的效果.

固定 Y 轴坐标不变应该能解决这个问题.

  • 示例代码如下:

      let aaOptions = aaChartModel.aa_toAAOptions()
    
      aaOptions.yAxis?
          .min(0)
          .max(100)
    

我试过了,这不能解决问题,只要时间接近, y 轴不动他也会蠕动

watermelon520 avatar Jul 29 '25 11:07 watermelon520

ChartDemo.zip

我写了一个简单的 demo。DataManager 有一个 3s 的定时器一直产生新数据,然后在 DataChartView 的 reloadData 方法里去刷新数据,我已经将 onlyRefreshTheChartDataWithSeries 方法内部的动画替换为时间 { 'duration': 3000 }

我上面发的两个问题都能出现,如果你把时间改为 2500 则蠕动效果就不会出现。

watermelon520 avatar Jul 31 '25 03:07 watermelon520

Highcharts 的内置的滚动刷新方法, 应该是支持设置动画时间的.

参考:

  • https://api.highcharts.com/class-reference/Highcharts.Series#addPoint

你的 demo 我测试了一下, 主要问题应该是没有使用我上面提到的, Highcharts 专门提供的用于滚动刷新的方法.

我在 AAChartKit-Swift 的 demo 中, 已经根据你的 demo, 添加了新的滚动刷新示例(使用 Highcharts 专门提供的用于滚动刷新的方法). 示例所实现的功能, 和你的目标需求应该是一致的.

参考我此次提交内容:

  • https://github.com/AAChartModel/AAChartKit-Swift/commit/c25d67264c2b2489f742b7ad580e07054bd4003a

AAChartModel avatar Aug 01 '25 03:08 AAChartModel

关于蠕动的问题, 我测试了这个官方的专门滚动刷新的方法, 如果滚动更新的速度过快, 也一样会有蠕动的效果.

参考官方在线示例:

  • https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/members/series-addpoint-append-and-shift/

在这个在线示例中, 如果你点击Add Point测试按钮速度过快(小于 0.6s 左右)的话, 也一样会蠕动, 这个问题目前无解(除非直接关闭滚动刷新的动画效果).

但是滚动更新时间间隔只要超过 1s, 基本上就是完全正常的.

AAChartModel avatar Aug 01 '25 03:08 AAChartModel

但是滚动更新时间间隔只要超过 1s, 基本上就是完全正常的.

我又仔细测试了一下, 在使用官方默认的滚动动画效果的情况下, 避免蠕动效果的临界值大概就是 0.52s 左右, 等于 0.52s 刚好可以不发生蠕动效果, 小于 0.52s 则会产生蠕动效果.

AAChartModel avatar Aug 01 '25 03:08 AAChartModel

在这个在线示例中, 如果你点击Add Point测试按钮速度过快(小于 0.6s 左右)的话, 也一样会蠕动, 这个问题目前无解(除非直接关闭滚动刷新的动画效果).

仔细测试发现其实修改滚动刷新动画效果的 duration, 使之尽可能的小, 也是能够避免蠕动效果的. 但是目前在 AAChartKit-Swift中, 滚动刷新的 API 还没有支持自定义动画效果的 duration.

目前情况下, 只要设置滚动刷新的更新时间大于等于 0.52s, 就可以正常实现需求了.

AAChartModel avatar Aug 01 '25 03:08 AAChartModel

Highcharts 的内置的滚动刷新方法, 应该是支持设置动画时间的. 参考:

  • https://api.highcharts.com/class-reference/Highcharts.Series#addPoint

你的 demo 我测试了一下, 主要问题应该是没有使用我上面提到的, Highcharts 专门提供的用于滚动刷新的方法.

我在 AAChartKit-Swift 的 demo 中, 已经根据你的 demo, 添加了新的滚动刷新示例(使用 Highcharts 专门提供的用于滚动刷新的方法). 示例所实现的功能, 和你的目标需求应该是一致的.

参考我此次提交内容:

感谢大佬,参考 Demo 修改了实现,现在渐变色填充动画不会有不跟线的问题了。 使用的时候对 AAObject 的 classNameString 实现有些建议已经提了 merge

watermelon520 avatar Aug 01 '25 09:08 watermelon520

在这个在线示例中, 如果你点击Add Point测试按钮速度过快(小于 0.6s 左右)的话, 也一样会蠕动, 这个问题目前无解(除非直接关闭滚动刷新的动画效果).

仔细测试发现其实修改滚动刷新动画效果的 duration, 使之尽可能的小, 也是能够避免蠕动效果的. 但是目前在 AAChartKit-Swift中, 滚动刷新的 API 还没有支持自定义动画效果的 duration.

目前情况下, 只要设置滚动刷新的更新时间大于等于 0.52s, 就可以正常实现需求了.

看来这个问题只能通过控制时间来兼容了。不知道有没有计划让 API 支持设置 duration。我看了一下,应该是涉及到三个接口,要是没空我来改也行哈哈哈

watermelon520 avatar Aug 01 '25 09:08 watermelon520

还有一个问题,现在从 aa_addPointToChartSeriesElement 换成了 aa_addPointToChartSeriesElement ,如果我还需要在表格上添加一条虚线,并且这条虚线跟着定时器新数据过来会去移动 y 轴的位置,能实现吗

let lineData = Array(repeating: AADataElement().y(100), count: maxcount)
let lineElement = AASeriesElement()
    .type(.line)
    .data(lineData)
    .color("#FFAA00")
    .lineWidth(1)
    .dashStyle(.dash)

watermelon520 avatar Aug 01 '25 09:08 watermelon520