zoukankan      html  css  js  c++  java
  • 浮动粒子制作404动画页面

    前言:之前在网上看到了这个效果,之后我在做项目的时候,正好将他放进了项目里面,这篇博客就介绍一下该效果的原理;

    1.首先是基础的设置

    const canvas = <HTMLCanvasElement>document.getElementById('canvas');
    let ctx: any = canvas.getContext('2d');
    const W: number = canvas.width = window.innerWidth;
    const H: number = canvas.height = window.innerHeight;
    
    const mFound: number = H * 2.5; //found 的粒子数量
    const mStr: number = H * 1.5;// 404的例子数量
    ctx.textAlign = "center";//居中
    

    canvas 的大小是占据整个屏幕;

    2.绘出字

    const str: string = '404';
    ctx.textBaseline = 'bottom';
    ctx.font = `${H / 2}px  'Arial', sans-serif`;
    ctx.fillText(str, W / 2, (H + H / 4) / 2, W);
    
    const found: string = 'Not Found';
    ctx.textBaseline = 'top';
    ctx.font = `${H / 6}px  'Arial', sans-serif`;
    ctx.fillText(found, W / 2, (H + H / 4) / 2, W);
    

    通过 fillText 的最后一个值,可以让字的大小不超过该值,我选择的是,浏览器的宽度,经我手机上检验,字的大小正好到达手机的宽度;
    再说一下我这边要写2次,是因为字的尺寸是不一样的;

    3.获取粒子

    let imageDataStr = ctx.getImageData(0, 0, W, (H + H / 4) / 2);
    let imageDataFound = ctx.getImageData(0, (H + H / 4) / 2, W, (H - H / 4) / 2);
    
    interface dotsType {
        x: number
        y: number
        r: number
        a: number
        lx: number
        rx: number
        v: number
    }
    
    function getDots(imageData, isStr: boolean): dotsType[] {
        let dots = [];
        let index: number = 0;
        for (let i = 0; i < W; i += 2) {
            for (let j = 0; j < H; j += 2) {
                let k = 4 * (i + j * W);
                if (imageData.data[k + 3] > 0) {
                    dots[index++] = {
                        x: i,
                        y: isStr ? j : j + (H + H / 4) / 2,
                        r: Math.random() * (isStr ? 8 : 3),
                        a: Math.random(),
                        lx: isStr ? i - 4 : i - 2,
                        rx: isStr ? i + 4 : i + 2,
                        v: (Math.random() - .5) * (isStr ? .8 : .4)
                    }
                }
            }
        }
        let newDots = [];
        const m = isStr ? mStr : mFound;
        if (m && (dots.length > m)) {
            for (let i = 0; i < m; i++) {
                newDots.push(dots[Math.floor(Math.random() * dots.length)]);
            }
        } else {
            newDots = dots;
        }
        return newDots;
    }
    

    使用 canvas 的 getImageData函数,将 canvas 读取为 imageData 格式,再根据图片的像素的值来获取写有字的例子的位置,将其添加入一个粒子数组,顺便加入粒子的半径,透明度,运动半径,和运动速度,而他接受的isStr参数,是为了区分是 str 还是 found 而区别的;
    为什么我要这样用一个参数来区分呢? 因为原来我看到的效果他是拿2个 canvas 叠在一起的,十分麻烦,而我根据定位和对应高度,加上 getImageData 的位置参数可以解决这个问题;
    这新建了 newDots 数组是为了根据开头所设置的粒子数来打乱原数组的顺序;

    4.渲染

    let dataStr: dotsType[] = getDots(imageDataStr, true);
    let DataFound: dotsType[] = getDots(imageDataFound, false);
    
    const data: dotsType[] = [...dataStr, ...DataFound];
    
    function render(): void {
        ctx.fillStyle = "#4db9ea";
        ctx.fillRect(0, 0, W, H);
        for (let i = 0; i < data.length; i++) {
            let temp = data[i];
            ctx.beginPath();
            ctx.fillStyle = `rgba(255,255,255,${temp.a})`;
    
            temp.x = temp.x + temp.v;
            temp.y = temp.y + temp.v;
            if (temp.x < temp.lx || temp.x > temp.rx) {
                temp.v = -temp.v;
            }
            ctx.arc(temp.x, temp.y, temp.r, 0, 2 * Math.PI);
            ctx.fill()
        }
    
    }
    
    render();
    

    渲染出对于半径和透明度的圆;
    因为分成了2个 imageData, 所以需要后面将2个粒子数组合并;并且根据每个数组的速度,来进行一个来回的直线运动;

    5.计时

    const requestAnimFrame = window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame;
    
    let startTime = 0;
    
    function animation(time: number = 0): void {
        if (time - startTime > 25) {
            render();
            startTime = time;
        }
        requestAnimFrame(animation)
    };
    
    animation();
    

    本来的话直接使用requestAnimFrame就行了,但是我调低了帧率,影响不大;

    最后:
    demo:点击查看
    github:https://github.com/Grewer/JsDemo/tree/master/floatParticles

  • 相关阅读:
    SASS教程sass超详细教程
    浅谈angular2+ionic2
    深入理解JSON对象
    浅谈闭包
    响应式开发入门
    CSS之float属性归纳探讨
    新学期加油
    Good moring!
    async await的前世今生
    ASP.NET配置KindEditor文本编辑器-图文实例
  • 原文地址:https://www.cnblogs.com/Grewer/p/8385117.html
Copyright © 2011-2022 走看看