Canvas2D沿路径动画实现

本文介绍了如何使用Canvas2D实现在不规则多边形路径上,根据实时数据推送实现小车动画。通过判断多边形方向、拆分线段、缓存动画点位栈和实现动画队列,最终实现了一个动态链路动画。文章详细讨论了各个步骤的实现细节,包括线段查找、动画函数和异步动画队列,强调了实践和勇于尝试的重要性。
摘要由CSDN通过智能技术生成

前言

刚入职公司的时候,接手了一个canvas-2D的项目,客户要求能够实现根据实时数据的推送,canvas画布上的小车也能够根据消息在一个环路上去实时动画,尽管我们都知道这种需求是不可能实现的,如果想要实时数据推送,canvas上的图也跟着数据点位去变化,那么首先要采用WebSocket保持长连接,其次是不可能在中间动画起来的,假设小车在A,只有小车到了下一个点位B点,才能推送B点的数据给我,我是无法预知到下一个点位的,所以这种方案很明显不可取。

在一番沟通后,客户退而求其次的说道,那么就实现一个推送数据A点,推送数据B点给我,让小车开启从A到B的动画,此时实际场景中小车已经在由B点运动到C点了,等到小车到C点后,再推送给我C点的消息,也就是所谓的延迟动画,推送的数据永远比现有动画链中的数据多一条。


思考

现有的条件:

  • 不规则多边形环路
  • 环路上有很多数据点位 每个数据点位都有其所在canvas的坐标值
  • WebSocket长连接推送数据点位
  • 小车图元

作为从未接触过这个的我来说,经过一番苦思冥想后,只想到了一个笨方法:

  • 首先将这条不规则多边形环路根据数据点位和canvas绘图的逻辑点位去拆分成多条单个的线段集合
  • 用一个栈缓存每次推送的数据点位,当满足条件时,立即开启小车动画,动画结束执行回调函数出栈,维护栈的长度
  • 小车动画应该是遍历查找线段集合,找到起点和终点所在的线段序号,截取中间线段组成动画路线集合
  • 遍历动画路线集合 采用异步函数实现异步队列模式动画。

动手

判断不规则多边形方向

多边形既然是用canvas绘制出来的,那么自然是可以获取到每个绘制点的canvas点位坐标的,这里的难度就是要去判断不规则多边形的绘图顺序。既然是一个环路,那么就会有顺时针和逆时针点位排序问题出现,在处理这里的时候,因为数学功底并不是很好,于是只好去网上查找一番资料,经过点拨后我才知道:

  • 只需要遍历这些所有的绘制点位中X值最大的点,
  • 取前一个点和后一个点分别和当前点组成向量,进行向量的叉乘根据结果正负去判断即可,
  • 这种方式会有一个需要注意的就是,必须要遍历查找出凸多边形的凸点,否则取到凹点则计算出的结果是截然相反的。
    /**
     * 正常笛卡尔坐标系
     * sum>0 true 逆时针
     * sum<0 false 顺时针
     * html5 canvas的Y轴反向
     * 判断画图走向是否逆时针
     * @param {*} mainPoints
     */
    isAntiClockwise(mainPoints) {
   
        let sum = 0;
        for (let i = 0; i < mainPoints.length; i++) {
   
            let i1 = i + 1;
            if (i1 == mainPoints.length) {
   
                i1 = 0;
            }
            let p1 = mainPoints[i],
                p2 = mainPoints[i1];
            sum += (p2.x - p1.x) * (p2.y + p1.y);
        }
        return sum > 0;
    },

拆分多边形

经过上面一步,我们已经知道当前不规则多边形的绘图方向了,按照业务需求,将多边形的绘图点位进行排序
image.png

这里具体的完整代码就不贴出来了,当初写这一部分时我还是个初入行的小白,写的函数方法及其臃肿难以理解,就不放出来给大家吐槽了,😂

请大家跟着我的思路继续走下去。
到这一步已经拿到了排序过的点位,但是我们需要组成一条条的线段,那么必然是需要知道canvas上下文绘制这条线段时的绘制方式了,好在我使用的是公司的框架,已经进行了封装,可以直接获取到线段的segments参数,是线段绘制方式的集合

  • lineTo表示调用的是canvas原生的lineTo绘制的直线
  • quadTo表示调用的是canvas原生的quadraticCurveTo方法绘制的二次贝塞尔曲线
  • bezierTo表示调用的是canvas原生bezierCurveTo方法绘制的三次贝塞尔曲线

如果有同学对canvas不太熟悉的话,可以去MDN网站上进行学习基础的使用方法。

[https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D]

这里我们也需要根据业务需求进行判断对绘制方式集合进行排序。

缓存动画点位栈

实现一个AnimateManager管理对象,每次数据点位推送过来,根据小车编号不重复这一特性,实现一个缓存栈。

	/**
     *
     *添加缓存/注册缓存
     * @param {*} deviceId
     * @param {*} location
     */
    addCache: function (deviceId, data) {
   
        var cache = this.cache[deviceId];
        if (!cache) {
   
            cache = this.cache[deviceId] = [];
            cache.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值