1. 程式人生 > >canvas 雷電文字

canvas 雷電文字

<html><head>
<meta charset="utf-8">
<title>雷電文字</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;
}
<!-- 38, 50, 56-->
.page-thunder-to-text input:hover, .page-thunder-to-text input:focus {
  border: 1px solid rgba(139,0,139, 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" width="1105" height="974"></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>



</body></html>

相關推薦

canvas 雷電文字

<html><head> <meta charset="utf-8"> <title>雷電文字</title> <style> .page-thunder-to-text { position: re

canvas圖片文字自動合成---微信朋友圈圖片分享

canvas-Synthetic-picture canvas圖片合成,支援右鍵另存為 一、合成內容 1.圖片 背景圖 專屬二維碼 使用者頭像(圓形) 2.使用者名稱 二、專案地址 https://github.com/Sta

canvas文字換行

當canvas的寬度不夠寬時,canvas不會自動換行,可以用下面的程式碼處理 <body> <canvas id="canvas" width="200" height="200" style="background:pink;"></canvas>

Canvas繪製文字(七)

canvas的文字是以圖形形式繪製的,實際他不是文字,只是像文字而已;一旦繪製之後,無法編輯,除非擦除文字,重新繪製。沒有充分的理由,最好使用普通的HTML元素,否則一定不要在canvas中建立文字。   context.fillText(text,x,y); 引數x,y表示文字原

android canvas drawText()文字居中

最近也是在學習自定義控制元件,以前只自己隨便玩了下,一直覺得比較難,正好現在工作輕鬆,每天閒著就看看書看看帖子學習自定義控制元件,你還別說自定義控制元件學起來還是蠻有趣的!! 這裡也跟大家分享下我關於drawText()文字居中的方法. 先附上drawText()的方法說明

canvas漸變文字

使用canvas建立漸變文字。效果如下: 程式碼如下: <!DOCTYPE html> <html> <head> <title>漸變文字<

Canvas文字API

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head>

canvas繪製文字 圓弧 填充規則

canvas繪製文字 strokeText()繪製的是空心的文字,fillText設定的是實心的文字 <script> var canvas = document.getEleme

Canvas實現文字

在canvas類裡呼叫textbox      private   TextBox   inputName   =   null;      private   Command   cCancel   =   new   Command("cancel",   Command

小程式 canvas旋轉文字

小程式實現:效果如下圖:js部分: //canvas畫圖片 savedetailCanvas: function () { //['消費者', '知性', '形象力', '形象力', '靚麗', '逛街中', '魅力四射', '小姐姐'] var that =

qml學習---------------利用Canvas繪製文字

在利用Canvas繪製文字的時候,可以指定文字不同的風格。 Context2D中和文字相關的方法有3個: fillText() , strokeText() , text(); 使用方法就下面兩種: ctx.beginPath(); ctx.text(“

canvas.drawText文字居中(備忘)

使用了canvas.drawText(String text, float x, float y, Paint paint) 這個API,發現在設定x,y讓文字居中時會有點問題,X的設定的話應該是可以通過設定 paint.setTextAlign(Paint.Ali

【朝花夕拾】Android自定義View篇之(四)Canvas繪製文字教程

前言       前面的文章中在介紹Canvas的時候,提到過後續單獨講Canvas繪製文字,因為這一節內容比較細緻,內容很多。這裡先宣告一下,本文的內容的來源於騰訊課堂中“仍物線學堂”中課件,因為該課件對常用的繪製文字基本技巧做了比較詳細的講解

超多經典 canvas 實例,動態離子背景、移動炫彩小球、貪吃蛇、坦克大戰、是男人就下100層、心形文字等等等

ntb contex lin 如果 maxwidth sel 容器 操作 reat 超多經典 canvas 實例 普及:<canvas> 元素用於在網頁上繪制圖形。這是一個圖形容器,您可以控制其每一像素,必須使用腳本來繪制圖形。 註意:IE 8 以及更早的版本不

Canvas對畫布及文字控制基礎API學習

style 也不能 不能 pan 平移 spa 畫布 bsp ont 這次純API練習,比較簡單,但是是為了之後的結合項目打基礎的,所以也不能忽視它,下面開始: Canvas的平移、旋轉、縮放 ①、Canvas的平移: ②、Canvas的旋轉: ③、Ca

Canvas--文字渲染

大小 ddc 寬度 const image ret base jpg eight 1、使用font屬性設置文字的樣式屬性。默認值為:20px sans-serif   font 屬性使用的語法與 CSS font 屬性 相同。   context.font = ‘fon

小程序---canvas畫圖,生成分享圖片,畫圖文字換行

return 指正 png ttext def fun context lte ctx 小程序目前只支持轉發,不支持分享朋友圈,為了能實現分享,很多線上小程序通過生成分享圖片,保存到相冊來給用戶增加分享的可能。 具體思路及簡要代碼如下: 一:canvas畫圖 draw

canvas文字自動換行、圓角矩形畫法、生成圖片手機長按保存

UNC get 函數 odata -i 圓角 ont eight nehe canvas的文字自動換行函數封裝 // str:要繪制的字符串 // canvas:canvas對象 // initX:繪制字符

微信小程序-canvas繪制文字實現自動換行

就是 creat 代碼 eas fun 一定的 文本 分割 func 在使用微信小程序canvas繪制文字時,時常會遇到這樣的問題:因為canvasContext.fillText參數為 我們只能設置文本的最大寬度,這就產生一定的了問題。如果我們繪制的文本長度不確定或者我

Python3 tkinter基礎 Canvas create_text 在畫布上添加文字

clas get ubuntu enc bject 堅持 str 語言 .html ? python : 3.7.0 OS : Ubuntu 18.04.1 LTS