H5雷电打过文字特效

  • 内容
  • 相关

H5 Canvas雷电打出文字特效代码

代码转自网上,不喜勿喷!!

<!doctype html>

<html>

<head>

<meta charset="utf-8">

<title>H5 Canvas雷电打出文字特效</title>

<style>

.page-thunder-to-text {

  position: relative;

  overflow: hidden;

}

.page-thunder-to-text canvas {

  display: block;

}

.page-thunder-to-text input {

  position: absolute;

  bottom: 50px;

  left: 0;

  right: 0;

  display: block;

  outline: none;

  background-color: rgba(38, 50, 56, 0.2);

  color: #ffffff;

  border: none;

  width: 50%;

  min-width: 500px;

  max-width: 100%;

  margin: auto;

  height: 60px;

  line-height: 60px;

  font-size: 40px;

  padding: 0 20px;

}

.page-thunder-to-text input:hover, .page-thunder-to-text input:focus {

  border: 1px solid rgba(38, 50, 56, 0.6);

}

.page-thunder-to-text input::-webkit-input-placeholder {

  color: rgba(255, 255, 255, 0.1);

}

</style>



</head>

<body>



<div class="page page-thunder-to-text">

 <input id="input" type="text" maxlength="24" placeholder="I love you!">

 <canvas id="canvas"></canvas>

</div>



<script>

let canvas, ctx, w, h, thunder, text, particles, input;



function Thunder(options) {

    options = options || {};

    this.lifespan = options.lifespan || Math.round(Math.random() * 10 + 10);

    this.maxlife = this.lifespan;

    this.color = options.color || '#fefefe';

    this.glow = options.glow || '#2323fe';

    this.x = options.x || Math.random() * w;

    this.y = options.y || Math.random() * h;

    this.width = options.width || 2;

    this.direct = options.direct || Math.random() * Math.PI * 2;

    this.max = options.max || Math.round(Math.random() * 10 + 20);

    this.segments = [...new Array(this.max)].map(() => {

        return {

            direct: this.direct + (Math.PI * Math.random() * 0.2 - 0.1),

            length: Math.random() * 20 + 80,

            change: Math.random() * 0.04 - 0.02

        };

    });



    this.update = function(index, array) {

        this.segments.forEach(s => { (s.direct += s.change) && Math.random() > 0.96 && (s.change *= -1) });

        (this.lifespan > 0 && this.lifespan--) || this.remove(index, array);

    }



    this.render = function(ctx) {

        if (this.lifespan <= 0) return;

        ctx.beginPath();

        ctx.globalAlpha = this.lifespan / this.maxlife;

        ctx.strokeStyle = this.color;

        ctx.lineWidth = this.width;

        ctx.shadowBlur = 32;

        ctx.shadowColor = this.glow;

        ctx.moveTo(this.x, this.y);

        let prev = { x: this.x, y: this.y };

        this.segments.forEach(s => {

            const x = prev.x + Math.cos(s.direct) * s.length;

            const y = prev.y + Math.sin(s.direct) * s.length;

            prev = { x: x, y: y };

            ctx.lineTo(x, y);

        });

        ctx.stroke();

        ctx.closePath();

        ctx.shadowBlur = 0;

        const strength = Math.random() * 80 + 40;

        const light = ctx.createRadialGradient(this.x, this.y, 0, this.x, this.y, strength);

        light.addColorStop(0, 'rgba(250, 200, 50, 0.6)');

        light.addColorStop(0.1, 'rgba(250, 200, 50, 0.2)');

        light.addColorStop(0.4, 'rgba(250, 200, 50, 0.06)');

        light.addColorStop(0.65, 'rgba(250, 200, 50, 0.01)');

        light.addColorStop(0.8, 'rgba(250, 200, 50, 0)');

        ctx.beginPath();

        ctx.fillStyle = light;

        ctx.arc(this.x, this.y, strength, 0, Math.PI * 2);

        ctx.fill();

        ctx.closePath();

    }



    this.remove = function(index, array) {

        array.splice(index, 1);

    }

}



function Spark(options) {

    options = options || {};

    this.x = options.x || w * 0.5;

    this.y = options.y || h * 0.5;

    this.v = options.v || { direct: Math.random() * Math.PI * 2, weight: Math.random() * 14 + 2, friction: 0.88 };

    this.a = options.a || { change: Math.random() * 0.4 - 0.2, min: this.v.direct - Math.PI * 0.4, max: this.v.direct + Math.PI * 0.4 };

    this.g = options.g || { direct: Math.PI * 0.5 + (Math.random() * 0.4 - 0.2), weight: Math.random() * 0.25 + 0.25 };

    this.width = options.width || Math.random() * 3;

    this.lifespan = options.lifespan || Math.round(Math.random() * 20 + 40);

    this.maxlife = this.lifespan;

    this.color = options.color || '#feca32';

    this.prev = { x: this.x, y: this.y };



    this.update = function(index, array) {

        this.prev = { x: this.x, y: this.y };

        this.x += Math.cos(this.v.direct) * this.v.weight;

        this.x += Math.cos(this.g.direct) * this.g.weight;

        this.y += Math.sin(this.v.direct) * this.v.weight;

        this.y += Math.sin(this.g.direct) * this.g.weight;

        this.v.weight > 0.2 && (this.v.weight *= this.v.friction);

        this.v.direct += this.a.change;

        (this.v.direct > this.a.max || this.v.direct < this.a.min) && (this.a.change *= -1);

        this.lifespan > 0 && this.lifespan--;

        this.lifespan <= 0 && this.remove(index, array);

    }



    this.render = function(ctx) {

        if (this.lifespan <= 0) return;

        ctx.beginPath();

        ctx.globalAlpha = this.lifespan / this.maxlife;

        ctx.strokeStyle = this.color;

        ctx.lineWidth = this.width;

        ctx.moveTo(this.x, this.y);

        ctx.lineTo(this.prev.x, this.prev.y);

        ctx.stroke();

        ctx.closePath();

    }



    this.remove = function(index, array) {

        array.splice(index, 1);

    }

}



function Particles(options) {

    options = options || {};

    this.max = options.max || Math.round(Math.random() * 10 + 10);

    this.sparks = [...new Array(this.max)].map(() => new Spark(options));



    this.update = function() {

        this.sparks.forEach((s, i) => s.update(i, this.sparks));

    }



    this.render = function(ctx) {

        this.sparks.forEach(s => s.render(ctx));

    }

}



function Text(options) {

    options = options || {};

    const pool = document.createElement('canvas');

    const buffer = pool.getContext('2d');

    pool.width = w;

    buffer.fillStyle = '#000000';

    buffer.fillRect(0, 0, pool.width, pool.height);



    this.size = options.size || 100;

    this.copy = (options.copy || `Hello!`) + ' ';

    this.color = options.color || '#cd96fe';

    this.delay = options.delay || 5;

    this.basedelay = this.delay;

    buffer.font = `${this.size}px Comic Sans MS`;

    this.bound = buffer.measureText(this.copy);

    this.bound.height = this.size * 1.5;

    this.x = options.x || w * 0.5 - this.bound.width * 0.5;

    this.y = options.y || h * 0.5 - this.size * 0.5;



    buffer.strokeStyle = this.color;

    buffer.strokeText(this.copy, 0, this.bound.height * 0.8);

    this.data = buffer.getImageData(0, 0, this.bound.width, this.bound.height);

    this.index = 0;



    this.update = function() {

        if (this.index >= this.bound.width) {

            this.index = 0;

            return;

        }

        const data = this.data.data;

        for (let i = this.index * 4; i < data.length; i += (4 * this.data.width)) {

            const bitmap = data[i] + data[i + 1] + data[i + 2] + data[i + 3];

            if (bitmap > 255 && Math.random() > 0.96) {

                const x = this.x + this.index;

                const y = this.y + (i / this.bound.width / 4);

                thunder.push(new Thunder({

                    x: x,

                    y: y

                }));

                Math.random() > 0.5 && particles.push(new Particles({

                    x: x,

                    y: y

                }));

            }

        }

        if (this.delay-- < 0) {

            this.index++;

            this.delay += this.basedelay;

        }

    }



    this.render = function(ctx) {

        ctx.putImageData(this.data, this.x, this.y, 0, 0, this.index, this.bound.height);

    }

}



function loop() {

    update();

    render();

    requestAnimationFrame(loop);

}



function update() {

    text.update();

    thunder.forEach((l, i) => l.update(i, thunder));

    particles.forEach(p => p.update());

}



function render() {

    ctx.globalCompositeOperation = 'source-over';

    ctx.globalAlpha = 1;

    ctx.fillStyle = '#000000';

    ctx.fillRect(0, 0, w, h);

    //

    ctx.globalCompositeOperation = 'screen';

    text.render(ctx);

    thunder.forEach(l => l.render(ctx));

    particles.forEach(p => p.render(ctx));

}



(function () {

    //

    canvas = document.getElementById('canvas');

    input = document.getElementById('input');

    ctx = canvas.getContext('2d');

    w = window.innerWidth;

    h = window.innerHeight;

    canvas.width = w;

    canvas.height = h;

    thunder = [];

    particles = [];

    //

    text = new Text({

        copy: 'Anh Yêu Em!'

    });

    canvas.addEventListener('click', (e) => {

        const x = e.clientX;

        const y = e.clientY;

        thunder.push(new Thunder({

            x: x,

            y: y

        }));

        particles.push(new Particles({

            x: x,

            y: y

        }));

    });

    let cb = 0;

    input.addEventListener('keyup', (e) => {

        clearTimeout(cb);

        cb = setTimeout(() => {

            text = new Text({

                copy: input.value

            });

        }, 300);

    });

    //

    loop();

})()

</script>

本文标签:

版权声明:若无特殊注明,本文皆为《若离风》原创,转载请保留文章出处。

本文链接:H5雷电打过文字特效 - https://www.rlfit.cn/?post=331

收录状态: [百度已收录]

发表评论

电子邮件地址不会被公开。 必填项已用*标注

未显示?请点击刷新

允许邮件通知