情人节表白代码——js实现手写字路径动画( 一)| 青训营笔记

118 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 18 天

  1. 先展示一下效果,中间一个爱心图标,两侧是ldm和zyy的手写字母 lheartz.gif
  2. 实现思路:
  • 首先前端方面采用的是js的canvas控件,使用canvas控件创建画布<canvas id="canvas"><canvas>
  • 使用js实现画布的属性变化以及一些画布的方法函数
  • 初始化,其中this.ldm和this.zyy代表手写路径的坐标变化点阵,即后一个点对于前一个点的相对位移点阵
    init() {
        this.canvas = document.getElementById("canvas");
        this.ctx = this.canvas.getContext("2d"); // 获取一个画布,赋值给 this.ctx
        window.addEventListener("resize", this.reset.bind(this));
        this.ldm = [[15,-28],[15,-28],[15,-28],[15,-28],[15,-28],[15,-28],[15,-28],[15,-28],[15,-28],[-13,34],[-13,34],[-13,34],[-13,34],[-7,34],[-7,34],[-7,34],[-1,30],[-1,30],[-1,30],[-1,30],[1,39],[1,39],[1,39],[12,-36],[12,-36],[12,-36],[9,-31],[9,-31],[9,-31],[9,-31],[25,-25],[25,-25],[49,-30],[-22,22],[-22,22],[-22,22],[0,33],[0,33],[45,10],[13,-39],[13,-39],[9,-34],[9,-34],[9,-34],[9,-34],[9,-34],[9,-34],[-12,31],[-12,31],[-12,31],[-1,30],[-1,30],[-1,30],[-1,30],[0,36],[0,36],[9,-30],[9,-30],[9,-30],[27,-16],[1,46],[-7,42],[-7,42],[-3,34],[-3,34],[6,-31],[6,-31],[9,-43],[6,-30],[6,-30],[16,-27],[16,-27],[24,-21],[24,-21],[4,33],[4,33],[-9,43],[-9,43],[-3,31],[-3,31],[-3,31],[4,-36],[4,-36],[4,-36],[12,-31],[12,-31],[12,-31],[12,-31],[12,-31],[3,37],[3,37],[3,37],[-1,36],[-1,36],[-1,36],[16,-33],[16,-33],[16,-33]];
        this.zyy = [[33,-34],[31,-21],[31,-21],[31,-21],[33,-9],[33,-9],[-22,28],[-22,28],[-22,28],[-16,28],[-16,28],[-16,28],[-16,28],[43,0],[22,-19],[22,-19],[22,-19],[22,-19],[22,-19],[12,-30],[25,-19],[25,-19],[25,-19],[-7,37],[-7,37],[6,54],[24,-31],[24,-31],[12,-28],[12,-28],[12,-28],[-3,36],[-3,36],[-3,36],[-3,36],[-10,49],[-16,33],[-16,33],[19,-25],[19,-25],[19,-25],[19,-25],[25,-43],[27,-16],[13,-27],[27,-21],[27,-21],[27,-21],[-6,33],[-6,33],[-3,57],[15,-27],[15,-27],[18,-36],[18,-36],[-1,30],[-1,30],[-1,30],[-1,30],[-3,33],[-25,39],[-42,33],[18,-25],[18,-25],[18,-25],[18,-25],[18,-25],[34,-33]];
        this.render();
    }
  • 上述代码中的this.render是程序起始的函数,其中包含reset和step两个函数
    render() {
        this.reset();
        this.step();
    }
  • reset函数是重置代码参数的,即清空屏幕的内容,并将画笔置于屏幕最左侧的起始位置
  • step函数是一个循环函数,step内部使用requestAnimationFrame函数定义一个动画
  • 动画基本思想是采用canvas的线条绘制函数,根据有序点集绘制线条路径
  • 最后就实现了上面的效果
  1. 中间爱心的绘制
  • 中间的爱心采用数学计算的方法,生成爱心路径函数形式如下:
  • 最终的计算结果储存在this.heartData这样一个二维数组中
  • 数组中存储的内容为相对起始点的坐标数值二元组[(x,y),(x2,y2)]
    getHeart() {
        let t = Math.PI + 0.5;
        let maxt = 2 * Math.PI - 1;
        let vt = this.speed/100;
        let x = 0;
        let y = 0;
        let r = this.heartR;
        for (let i = 0; i < Math.ceil(maxt / vt); i++) {
            x = 16 * Math.pow(Math.sin(t), 3);
            y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
            t += vt;
            x *= r;
            y = -y * r - r * Math.PI * 4;
            if (y < 0) {
                this.heartData.push({ x, y });
            }
        }
    }

4.参考代码: github.com/degiminnal/…