国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

程序員的小浪漫----文字粒子效果

xiaodao / 1282人閱讀

摘要:預(yù)覽完整項目預(yù)覽預(yù)覽地址粒子效果原理在中,可以通過方法來獲取像素數(shù)據(jù)。下例是通過改變像素的數(shù)據(jù)而重新寫出來的文字。不過可能會造成文字部分地方缺失。煙花效果可以看一下我的上一篇,程序員的小浪漫煙火完整項目項目地址如果覺得還不錯,請一個吧。

預(yù)覽

完整項目預(yù)覽----預(yù)覽地址;

粒子效果原理

在canvas中,可以通過getImageData()方法來獲取像素數(shù)據(jù)。

ctx.fillStyle = "#ff0000";
ctx.fillRect(0, 0, 1, 1);
const imageData = ctx.getImageData(0, 0, 1, 1);

imageData有三個屬性:

data:數(shù)組,包含了像素信息,每個像素會有四個長度,如[255,0,0,255, ... ,255,127,0,255],分別代表該像素的RGBA值。

widthimageData對象的寬。

heightimageData對象的高。

首先在canvas寫上某種顏色文字,再去分析像素數(shù)據(jù)(比如改像素是否有透明度等),然后自己記錄下該像素點的位置

下例是通過改變像素的數(shù)據(jù)而重新寫出來的文字。

ctx.font = "bold 40px Arial";
ctx.textBaseline = "middle";
ctx.textAlign = "center";
ctx.fillText("你好啊", 60, 20);

document.querySelector("#button").addEventListener("click", function(){
    const imgData = ctx.getImageData(0, 0, 120, 40);
    for(let i = 0;i < imgData.data.length; i+=4){
        if(imgData.data[i + 3] == 0) continue;
        imgData.data[i] = 255;
        imgData.data[i + 1] = 0;
        imgData.data[i + 2] = 0;
        // imgData.data[i + 3] = 255;  這個代表的是透明度 透明度不變 255最高 0最低
    }
    ctx.putImageData(imgData,120,0);
});

這段代碼只是示例說明一下,實際上才不會有人這么腦殘去換顏色吧。

獲取點位置

要獲取點的位置,首先要將字寫在畫布上,但是字又不能讓別人看到。所以可以動態(tài)創(chuàng)建一個畫布,這個畫布不會append到任何節(jié)點上,只會用于寫字。

const cache = document.createElement("canvas");

將寬高等與展示的畫布設(shè)置成一樣的。(不貼這部分的代碼了)

創(chuàng)建一個對象,用于獲取點的位置

const ShapeBuilder = {
    //初始化字的對齊方式等,我認(rèn)為middle 與 center比較好計算一點
    init(width, height){
        this.width = width;
        this.height = height;
        this.ctx = cache.getContext("2d");
        this.ctx.textBaseline = "middle";
        this.ctx.textAlign = "center";
    },
    //獲取位置之前必須先要寫入文字。 這里的size=40是默認(rèn)值
    write(words, x, y, size = 40){
        //清除之前寫的字。
        this.ctx.clearRect(0, 0, this.width, this.height);
        this.font = `bold ${size}px Arial`;
        this.ctx.fillText(words, x, y);
        //記錄當(dāng)前文字的位置,方便計算獲取像素的區(qū)域
        this.x = x;
        this.y = y;
        this.size = size;
        this.length = words.length;
    },
    getPositions(){
        //因為imgData數(shù)據(jù)非常的大,所以盡可能的縮小獲取數(shù)據(jù)的范圍。
        const xStart = this.x - (this.length / 2) * this.size, 
            xEnd = this.x + (this.length / 2) * this.size,
            yStart = this.y - this.size / 2, 
            yEnd = this.y + this.size / 2, 
            
            //getImageData(起點x, 起點y, 寬度, 高度);
            data = this.ctx.getImageData(xStart, yStart, this.size * this.length, this.size).data;
            
        //間隔 (下面有介紹)
        const gap = 4;
        
        let positions = [], x = xStart, y = yStart;
        
        for(var i = 0;i < data.length; i += 4 * gap){
            if(data[i+3] > 0){
                positions.push({x, y});    
            }
            
            x += gap;
            
            if(x >= xEnd){
                x = xStart;
                y += gap;
                i += (gap - 1) * 4 * (xEnd - xStart);
            }
        }
        return positions;
    }
}

ShapeBuilder.init();

關(guān)于gap:在循環(huán)imgData數(shù)組的時候,數(shù)據(jù)量太大可能會造成卡頓,所以可以使用間隔來獲取坐標(biāo)點的方法。不過可能會造成文字部分地方缺失。就需要個人來權(quán)衡利弊,自己來調(diào)整了。

gap的值必須能被xEnd-xStart給整除,不然會造成獲取坐標(biāo)點錯位的后果。

關(guān)于canvasmiddlecenter的規(guī)則:

this.ctx.font = "bold 40px Arial";
this.ctx.fillText("你好",40 ,20);

效果如下圖所示

fillText設(shè)置的坐標(biāo)點剛好會是整個字的中點,就是圖中middlecenter的交點。其實以其它對齊方式也是可以的,看個人喜好。

更多的對齊規(guī)則參考HTML 5 Canvas 參考手冊的文本。

創(chuàng)建微粒類

微粒應(yīng)該隨機(jī)生成,然后移動到指定的位置去。

微粒類的屬性:

自身當(dāng)前位置(x,y), 目標(biāo)位置:(xEnd,yEnd),自身大小(size),自身顏色(color),移動快慢(e)

方法:go():每一幀都要移動一段距離,render():渲染出微粒(我用心形的形狀)

class Particle {
    constructor({x, y, size = 2, color, xEnd, yEnd, e = 60} = {}){
        this.x = x;
        this.y = y;
        this.size = size;
        this.color = color ||  `hsla(${Math.random() * 360}, 90%, 65%, 1)`;
        this.xEnd = xEnd;
        this.yEnd = yEnd;
        
        //經(jīng)過e幀之后到達(dá)目標(biāo)地點
        this.e = e;
        //計算每一幀走過的距離
        this.dx = (xEnd - x) / e;
        this.dy = (yEnd - y) / e;
    }
    go(){
        //到目的后保持不動 (其實這里也可以搞點事情的)
        if(--this.e <= 0) {
            this.x = this.xEnd;
            this.y = this.yEnd;
            return ;
        }
        this.x += this.dx;
        this.y += this.dy;
    }
    render(ctx){
        this.go();
        //下面是畫出心型的貝塞爾曲線
        ctx.beginPath();
        ctx.fillStyle = this.color;
        ctx.moveTo(this.x + 0.5 * this.size, this.y + 0.3 * this.size);
        ctx.bezierCurveTo(this.x + 0.1 * this.size, this.y, this.x, 
                        this.y + 0.6 * this.size, this.x + 0.5 * 
                        this.size, this.y + 0.9 * this.size);
        ctx.bezierCurveTo(this.x + 1 * this.size, this.y + 0.6 * 
                        this.size, this.x + 0.9 * this.size, this.y, 
                        this.x + 0.5 * this.size,
                        this.y + 0.3 * this.size);
        ctx.closePath();
        ctx.fill();
        return true;
    }
}

微粒類最基本的屬性與方法就是這些,如果要讓粒子更好看一點,或者更生動一點,可以自己添加一些屬性與方法。

具體流程
const canvas = {
    init(){
        //設(shè)置一些屬性
        this.setProperty();
        //創(chuàng)建微粒
        this.createParticles();
        //canvas的循環(huán)
        this.loop();
    },
    setProperty(){
        this.ctx = studio.getContext("2d");
        this.width = document.body.clientWidth;
        this.height = document.body.clientHeight;
        this.particles = [];
    },
    createParticles(){
        let dots;
        //ShapeBuilder.write(words, x, y, size)
        ShapeBuilder.write("每個字都是",this.width / 2, this.height / 3, 120);
        dots = ShapeBuilder.getPositions(6);
        ShapeBuilder.write("愛你的模樣", this.width / 2, this.height * 2 / 3, 120);
        dots = dots.concat(ShapeBuilder.getPositions(6));
        //dots已經(jīng)獲取到了字的坐標(biāo)點 
        //每一個微粒的目標(biāo)地點都是dots的坐標(biāo)
        //每一個微粒都隨機(jī)出生在畫布的某個位置
        for(let i = 0; i < dots.length; i++){
            this.particles.push(new Particle({
                xEnd:dots[i].x, 
                yEnd:dots[i].y , 
                x: Math.random() * this.width, 
                y: Math.random() * this.height, 
                size:6, 
                color:"hsla(360, 90%, 65%, 1)"
            }));
        }
    },
    loop(){
        //每一幀清除畫布,然后再渲染微粒就可以了
        requestAnimationFrame(this.loop.bind(this));
        this.ctx.clearRect(0, 0, this.width, this.height);
        for(var i = 0; i < this.particles.length; i++){
            this.particles[i].render(this.ctx);
        }
    }
}

canvas.init();

如果想要給每個粒子加上小尾巴的話,那么在每一幀的時候,就不要清除畫布,而且覆蓋一層有透明度的底色。

//修改loop方法
//this.ctx.clearRect(0, 0, this.width, this.height);
this.ctx.fillStyle = "rgba(0,0,0,0.2)";
this.ctx.fillRect(0, 0, this.width, this.height);

這樣的話會變成如下效果

最后

在這這篇文章的時候,并沒有注意太多細(xì)節(jié),比如gap應(yīng)該是可以被設(shè)置的,或者是一個被特殊標(biāo)注的常量,而不應(yīng)該隨便寫在方法中。對于本例的代碼,切勿生搬硬套,重要的是要理解原理,以及自己親自動手嘗試

我也是在寫這篇文章的過程中,才發(fā)現(xiàn)了之前獲取position一個不精準(zhǔn)的地方。

這里只講了粒子效果最基礎(chǔ)的用法,實際上還可以做出很多非常炫酷的效果

比如在粒子到達(dá)目的地后還可以抖動什么的

粒子形狀、顏色的變化等等。

這個項目還可以搞很多事情的,大家也可以自己多來嘗試弄些更加炫酷的效果。

煙花效果可以看一下我的上一篇,程序員的小浪漫----煙火

完整項目

github項目地址

如果覺得還不錯,請star一個吧。

參考項目

github上的一個項目---- shape-shifter

這個項目我覺得非常不錯,可惜作者都消失好多年了。

codepen.io 上的一個作品 ---- Love In Hearts

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92920.html

相關(guān)文章

  • 序員小浪----煙火

    摘要:多代碼,慎讀預(yù)覽完整項目預(yù)覽預(yù)覽地址屬性設(shè)計煙花狀態(tài)煙花應(yīng)有三個狀態(tài)升空等待炸裂炸裂后煙花發(fā)射點,爆炸點,升空后等待炸裂時間,炸裂后微粒個數(shù),煙花半徑煙花炸裂后微粒自身位置,自身大小,自身速度,最大煙花半徑。 多代碼,慎讀!!! 預(yù)覽 showImg(https://segmentfault.com/img/remote/1460000013324854?w=349&h=423); 完...

    roundstones 評論0 收藏0
  • Canvas 實現(xiàn)炫麗粒子運(yùn)動效果粒子生成文字

    摘要:代碼實現(xiàn)炫麗的粒子運(yùn)動效果云庫前端散開類型歸位隨機(jī)散開效果對歸位有效輸入漢字后回車代碼不多,只要是幾個操作元素。看起來運(yùn)行順暢的代碼也或多或少有一些瑕疵,日前這個效果還只支持中文。 沒有最好,只有更好,如題所示,這篇文章只要是分享一個用 Canvas 來實現(xiàn)的粒子運(yùn)動效果。感覺有點標(biāo)題黨了,但換個角度,勉勉強(qiáng)強(qiáng)算是炫麗吧,雖然色彩上與炫麗無關(guān),但運(yùn)動效果上還是算得上有點點炫的。不管怎么...

    icattlecoder 評論0 收藏0
  • 《每周一點canvas動畫》—— 文字粒子

    摘要:代碼文件每周一點動畫系列文章目前已經(jīng)更新了篇,今天給大家發(fā)個福利。粒子的位置為,我們作為參數(shù)傳入。粒子切換粒子切換的代碼在中,很簡單,就是綁定了兩個事件。 代碼文件 每周一點canvas動畫系列文章目前已經(jīng)更新了12篇,今天給大家發(fā)個福利。我們使用canvas來制作一個小的效果。這個小效果是我從codePen上看到的,我對其做了些修改增強(qiáng),添加了一些新的功能。UI界面就如下圖中看到的樣...

    Riddler 評論0 收藏0

發(fā)表評論

0條評論

xiaodao

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<