首页 > 特效插件 > 粒子效果 >  基于webgl和canvas的科技梦幻波浪动态线条正文

基于webgl和canvas的科技梦幻波浪动态线条

特效介绍
html5波浪效果

基于webgl和canvas的HTML5科技梦幻波浪动态线条特效动画背景代码,颜色随机,可设置颜色,颜色模式基于HSV。下面代码即是本插件的全部内容,所以就不提供下载地址了。
使用方法
1、在需要显示本canvas的地方加入下面代码,大小可自己设置,也可以用css定义:
<canvas width="1363" height="937" id="waves"></canvas>
2、在页面底部加入下面的js
"use strict";
const webGL = {
    init(options) {
        this.elem = document.querySelector("#waves");
        this.gl = (
            this.elem.getContext("webgl", options) ||
            this.elem.getContext("experimental-webgl", options)
        );
        if (!this.gl) return false;
        const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
        this.gl.shaderSource(vertexShader, `
            precision highp float;
            attribute vec2 aPosition;
            uniform vec3 uHSV;
            uniform vec2 uResolution;
            varying vec4 vColor;
            vec3 hsv2rgb(vec3 c) {
                vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
                vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
                return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
            }
            void main() {
                gl_PointSize = 1.0;
                gl_Position = vec4(
                    ( aPosition.x / uResolution.x * 2.0) - 1.0,
                    (-aPosition.y / uResolution.y * 2.0) + 1.0,
                    0.0,
                    1.0
                );
                vColor = vec4(hsv2rgb(uHSV), 1.0);
            }
        `);
        this.gl.compileShader(vertexShader);
        const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
        this.gl.shaderSource(fragmentShader, `
            precision highp float;
            varying vec4 vColor;
            void main() {
                gl_FragColor = vColor;
            }
        `);
        this.gl.compileShader(fragmentShader);
        this.program = this.gl.createProgram();
        this.gl.attachShader(this.program, vertexShader);
        this.gl.attachShader(this.program, fragmentShader);
        this.gl.linkProgram(this.program);
        this.gl.useProgram(this.program);
        this.aPosition = this.gl.getAttribLocation(this.program, "aPosition");
        this.gl.enableVertexAttribArray(this.aPosition);
        this.positionBuffer = this.gl.createBuffer();
        this.uHSV = this.gl.getUniformLocation(this.program, "uHSV");
        this.gl.enableVertexAttribArray(this.uHSV);
        this.resize();
        window.addEventListener("resize", () => this.resize(), false);
        return this;
    },
    resize () {
        this.width = this.elem.width = this.elem.offsetWidth;
        this.height = this.elem.height = this.elem.offsetHeight;
        const uResolution = this.gl.getUniformLocation(this.program, "uResolution");
        this.gl.enableVertexAttribArray(uResolution);
        this.gl.uniform2f(uResolution, this.width, this.height);
        this.gl.viewport(0, 0,
            this.gl.drawingBufferWidth,
            this.gl.drawingBufferHeight
        );
    },
    blend (s, d) {
        this.gl.blendFunc(s, d);
        this.gl.enable(this.gl.BLEND);
    },
    createBufferLine (len) {
        this.num = len;
        this.bufferLine = new Float32Array(len * 2);
    },
    beginPath () {
        this.k = 0;
    },
    strokeStyle (h, s, v) {
        this.gl.uniform3f(this.uHSV, h, s, v);
    },
    lineTo (x, y) {
        this.bufferLine[this.k++] = x;
        this.bufferLine[this.k++] = y;
    },
    stroke () {
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer);
        this.gl.vertexAttribPointer(this.aPosition, 2, this.gl.FLOAT, false, 0, 0);
        this.gl.bufferData(
            this.gl.ARRAY_BUFFER,
            this.bufferLine,
            this.gl.DYNAMIC_DRAW
        );
        this.gl.drawArrays(this.gl.LINE_STRIP, 0, this.num);
    }
};

{
    const perlin = {
        init() {
            this.p = new Uint8Array(512);
            const p = new Uint8Array(256);
            for (let i = 0; i < 256; i++) p[i] = i;
            for (let i = 255; i > 0; i--) {
                const n = Math.floor((i + 1) * Math.random());
                [p[i], p[n]] = [p[n], p[i]];
            }
            for (let i = 0; i < 512; i++) this.p[i] = p[i & 255];
        },
        fade(t) {
            return t * t * t * (t * (t * 6 - 15) + 10);
        },
        lerp(t, a, b) {
            return a + t * (b - a);
        },
        grad(hash, x, y, z) {
            const h = hash & 15;
            const u = h < 8 ? x : y;
            const v = h < 4 ? y : h == 12 || h == 14 ? x : z;
            return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
        },
        noise(xi, yi, zi) {
            const X = Math.floor(xi) & 255;
            const Y = Math.floor(yi) & 255;
            const Z = Math.floor(zi) & 255;
            const x = xi - Math.floor(xi);
            const y = yi - Math.floor(yi);
            const z = zi - Math.floor(zi);
            const u = this.fade(x);
            const v = this.fade(y);
            const w = this.fade(z);
            const A = this.p[X] + Y;
            const AA = this.p[A] + Z;
            const AB = this.p[A + 1] + Z;
            const B = this.p[X + 1] + Y;
            const BA = this.p[B] + Z;
            const BB = this.p[B + 1] + Z;
            return this.lerp(
                w,
                this.lerp(
                    v,
                    this.lerp(u, this.grad(this.p[AA], x, y, z), this.grad(this.p[BA], x - 1, y, z)),
                    this.lerp(u, this.grad(this.p[AB], x, y - 1, z), this.grad(this.p[BB], x - 1, y - 1, z))
                ),
                this.lerp(
                    v,
                    this.lerp(u, this.grad(this.p[AA + 1], x, y, z - 1), this.grad(this.p[BA + 1], x - 1, y, z - 1)),
                    this.lerp(
                        u,
                        this.grad(this.p[AB + 1], x, y - 1, z - 1),
                        this.grad(this.p[BB + 1], x - 1, y - 1, z - 1)
                    )
                )
            );
        }
    };
    const canvas = webGL.init({
        alpha: false,
        stencil: false,
        antialias: false,
        depth: false,
    });
    canvas.blend(canvas.gl.ONE, canvas.gl.ONE);
    perlin.init();
    canvas.createBufferLine(100);
    let z = 0;
    function run() {
        const sw = canvas.width / 100;
        const sh = sw * 30;
        for (let i = 0; i < 180; i++) {
            canvas.beginPath();
            canvas.strokeStyle(
                z + i / 360,
                0.5,
                0.3
            );
            for (let j = -50; j < 50; j++) {
                const h = perlin.noise(j * 0.05, z - i * 0.01, z);
                canvas.lineTo(
                    canvas.width * 0.5 + 0.01 * (i + 180) * j * sw * 0.5,
                    -90 + i + canvas.height * 0.5 + h * sh
                );
            }
            canvas.stroke();
        }
        z += 0.0025;
        requestAnimationFrame(run);
    }
    run();
}
3、如果要修改颜色,可以在js代码中找到canvas.strokeStyle,修改里面的值,颜色模式为HSV