校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃

主頁 > 知識庫 > 詳解Canvas 實現(xiàn)炫麗的粒子運動效果(粒子生成文字)

詳解Canvas 實現(xiàn)炫麗的粒子運動效果(粒子生成文字)

熱門標簽:農(nóng)村住宅地圖標注 鄭州電銷外呼系統(tǒng)違法嗎 威海營銷外呼系統(tǒng)招商 鶴壁手機自動外呼系統(tǒng)怎么安裝 中紳電銷智能機器人 漳州人工外呼系統(tǒng)排名 ai電銷機器人連接網(wǎng)關 跟電銷機器人做同事 濟南辦理400電話

沒有最好,只有更好,如題所示,這篇文章只要是分享一個用 Canvas 來實現(xiàn)的粒子運動效果。感覺有點標題黨了,但換個角度,勉勉強強算是炫麗吧,雖然色彩上與炫麗無關,但運動效果上還是算得上有點點炫的。不管怎么樣,我們還是開始這個所謂的炫麗效果吧!

直接上代碼 ,不懂可以看代碼注釋。估計就會看明白大概的思路了。

html 代碼

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas 實現(xiàn)炫麗的粒子運動效果-云庫前端</title>
<style>
* {
    margin: 0;
    padding: 0;
}
html,
body {
    width: 100%;
    height: 100%;
}
canvas {
    display: block;
    background: #000;
}
body::-webkit-scrollbar{
    display: none;
}
.operator-box{
    position: fixed;
    top: 0;
    left: 50%;
    border: 1px solid #fff;
    background: rgba(255,255,255,0.5);
    padding: 20px 10px;
    -webkit-transform: translateX(-50%);
    transform: translateX(-50%);
}
.back-type,.back-animate{
    margin-right: 20px;
}
.flex-box{
    display: flex;
    justify-content: center;
    align-items: center;
}
#input-text{
    line-height: 35px;
    width: 260px;
    height: 35px;
    background: rgba(0, 0, 0,0.7);
    color: #fff;
    font-size: 16px;
    border: none;
    outline: none;
    text-indent: 12px;
    box-shadow: inset 0 0 12px 1px rgba(0,0,0,0.7);
}
#input-text::placeholder{
    color: #ccc;
    line-height: 55px;
    height: 55px;
}
select{
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    border: none;
    padding: 0px 20px 0px 6px;
    height: 35px;
    color: #fff;
    text-align: left;
    background: rgba(0, 0, 0,0.7) url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAICAYAAAAx8TU7AAAAOUlEQ…R4gPgWEIMAiOYBCS4C8ZDAIrBq4gigNkztQEFMi6AuQHESAPMeXiEMiWfpAAAAAElFTkSuQmCC) no-repeat 190px 12px;
    background-size: 5px 8px;
    box-shadow: inset 0 0 12px 1px rgba(0,0,0,0.7);
}
</style>
</head>
<body>
<div class="operator-box">
<div class="flex-box">
    <div class="back-type">散開類型:
        <select name="" id="selectType">
            <option value="back">歸位</option>
            <option value="auto">隨機</option>
        </select>
    </div>
    <div class="back-animate">散開效果(對歸位有效):
       <select class="back-dynamics" id="selectDynamics">
           <option value="spring">dynamics.spring</option>
           <option value="bounce">dynamics.bounce</option>
           <option value="forceWithGravity">dynamics.forceWithGravity</option>
           <option value="gravity">dynamics.gravity</option>
           <option value="easeInOut">dynamics.easeInOut</option>
           <option value="easeIn">dynamics.easeIn</option>
           <option value="easeOut">dynamics.easeOut</option>
           <option value="linear">dynamics.linear</option>
       </select>
    </div>
    <div class="input-box"><input type="text" placeholder="輸入漢字后回車" id="input-text"></div>
</div>
</div>
<script src="dynamics.min.js"></script>
<script src="index.js"></script>
<script>
var iCircle = new Circle();
</script>
</body>
</html>

HTML 代碼不多,只要是幾個操作元素。這里一看就明白。不費過多口舌。我們來看看本文的主角 JavaScript 代碼,不過,在看代碼前,我們不妨先聽聽實現(xiàn)這個效果的思路:

  1. 首先,我們得先生成一堆群眾演員(粒子);
  2. 把每個粒子的相關參數(shù)掛到自身的一些屬性上,因為第個粒子都會有自己的運動軌跡;
  3. 接著得讓它們各自運動起來。運動有兩種(自由運動和生成文字的運動);

JavaScript 代碼中使用了三個 Canvas 畫布,this.iCanvas(主場)、this.iCanvasCalculate(用來計算文字寬度)、this.iCanvasPixel(用于畫出文字,并從中得到文字對應的像素點的位置坐標)。

this.iCanvasCalculate 和 this.iCanvasPixel 這兩個無需在頁面中顯示出來,只是輔助作用。

下面就獻上棒棒的 JS 實現(xiàn)代碼

function Circle() {
    var This = this;
    this.init();
    this.generalRandomParam();
    this.drawCircles();
    this.ballAnimate();
    this.getUserText();
    // 窗口改變大小后,生計算并獲取畫面
    window.onresize = function(){
        This.stateW = document.body.offsetWidth;
        This.stateH = document.body.offsetHeight;
        This.iCanvasW = This.iCanvas.width = This.stateW;
        This.iCanvasH = This.iCanvas.height = This.stateH;
        This.ctx = This.iCanvas.getContext("2d");
    }
}
// 初始化
Circle.prototype.init = function(){
    //父元素寬高
    this.stateW = document.body.offsetWidth;
    this.stateH = document.body.offsetHeight;
    this.iCanvas = document.createElement("canvas");
    // 設置Canvas 與父元素同寬高
    this.iCanvasW = this.iCanvas.width = this.stateW;
    this.iCanvasH = this.iCanvas.height = this.stateH;
    // 獲取 2d 繪畫環(huán)境
    this.ctx = this.iCanvas.getContext("2d");
    // 插入到 body 元素中
    document.body.appendChild(this.iCanvas);
    this.iCanvasCalculate = document.createElement("canvas");
    // 用于保存計算文字寬度的畫布
    this.mCtx =  this.iCanvasCalculate.getContext("2d");
    this.mCtx.font = "128px 微軟雅黑";
    this.iCanvasPixel = document.createElement("canvas");
    this.iCanvasPixel.setAttribute("style","position:absolute;top:0;left:0;");
    this.pCtx = null; // 用于繪畫文字的畫布
    // 隨機生成圓的數(shù)量
    this.ballNumber = ramdomNumber(1000, 2000);
    // 保存所有小球的數(shù)組
    this.balls = [];
    // 保存動畫中最后一個停止運動的小球
    this.animte = null;
    this.imageData = null;
    this.textWidth = 0; // 保存生成文字的寬度
    this.textHeight = 150; // 保存生成文字的高度
    this.inputText = ""; // 保存用戶輸入的內(nèi)容
    this.actionCount = 0;
    this.ballActor = []; // 保存生成文字的粒子
    this.actorNumber = 0; // 保存生成文字的粒子數(shù)量
    this.backType = "back"; // 歸位
    this.backDynamics = ""; // 動畫效果
    this.isPlay = false; // 標識(在生成文字過程中,不能再生成)
}
// 渲染出所有圓
Circle.prototype.drawCircles = function () {
    for(var i=0;i<this.ballNumber;i++){
        this.renderBall(this.balls[0]);
    }
}
// 獲取用戶輸入文字
Circle.prototype.getUserText = function(){
    This = this; // 保存 this 指向
    ipu = document.getElementById("input-text");
    ipu.addEventListener("keydown",function(event){
        if(event.which === 13){ // 如果是回車鍵
            ipu.value = ipu.value.trim(); // 去頭尾空格
            var pat = /[u4e00-u9fa5]/; // 中文判斷
            var isChinese = pat.test(ipu.value);
            if(ipu.value.length !=0 && isChinese){
                This.inputText = ipu.value;
            }else{
                alert("請輸入漢字");
                return;
            }
            if(This.isPlay){
                return
            }
            This.getAnimateType();
            This.getTextPixel();
            This.isPlay = true;
        }
    });
}
// 計算文字的寬
Circle.prototype.calculateTextWidth = function () {
    this.textWidth = this.mCtx.measureText(this.inputText).width;
}
// 獲取文字像素點
Circle.prototype.getTextPixel = function () {
    if(this.pCtx){
        this.pCtx.clearRect(0,0,this.textWidth,this.textHeight);
    }
    this.calculateTextWidth(this.inputText);
    this.iCanvasPixel.width = this.textWidth;
    this.iCanvasPixel.height = this.textHeight;
    this.pCtx =  this.iCanvasPixel.getContext("2d");
    this.pCtx.font = "128px 微軟雅黑";
    this.pCtx.fillStyle = "#FF0000";
    this.pCtx.textBaseline = "botom";
    this.pCtx.fillText(this.inputText,0,110);
    this.imageData = this.pCtx.getImageData(0,0,this.textWidth,this.textHeight).data;
    this.getTextPixelPosition(this.textWidth,this.textHeight);
}
// 獲取文字粒子像素點位置
Circle.prototype.getTextPixelPosition = function (width,height) {
    var left = (this.iCanvasW - width)/2;
    var top = (this.iCanvasH - height)/2;
    var space = 4;
    this.actionCount = 0;
    for(var i=0;i<this.textHeight;i+=space){
        for(var j=0;j<this.textWidth;j+=space){
            var index = j*space+i*this.textWidth*4;
            if(this.imageData[index] == 255){
                if(this.actionCount<this.ballNumber){
                    this.balls[this.actionCount].status = 1;
                    this.balls[this.actionCount].targetX = left+j;
                    this.balls[this.actionCount].targetY = top+i;
                    this.balls[this.actionCount].backX = this.balls[this.actionCount].x;
                    this.balls[this.actionCount].backY = this.balls[this.actionCount].y;
                    this.ballActor.push(this.balls[this.actionCount]);
                    this.actionCount++;
                }
            }
        }
        this.actorNumber = this.ballActor.length;
    }
    this.animateToText();
}
// 粒子運動到指定位置
Circle.prototype.animateToText = function(){
    for(var i=0;i<This.actorNumber;i++){
        dynamics.animate(This.ballActor[i], {
          x: this.ballActor[i].targetX,
          y: this.ballActor[i].targetY
        },{
            type: dynamics.easeIn,
            duration: 1024,
        });
    }
    setTimeout(function(){
        This.ballbackType();
    },3000);
}
// 粒子原路返回
Circle.prototype.ballBackPosition = function(){
    for(var i=0;i<This.actorNumber;i++){
        var ball = This.ballActor[i];
        dynamics.animate(ball, {
          x: ball.backX,
          y: ball.backY
        },{
            type: dynamics[this.backDynamics],
            duration: 991,
            complete:this.changeStatus(ball)
        });
    }
}
// 獲取類型|動畫效果
Circle.prototype.getAnimateType = function() {
    var selectType = document.getElementById("selectType");
    var selectDynamics = document.getElementById("selectDynamics");
    this.backType = selectType.options[selectType.options.selectedIndex].value;
    this.backDynamics = selectDynamics.options[selectDynamics.options.selectedIndex].value;
}
// 復位散開
Circle.prototype.ballbackType = function(){
    if(this.backType == "back"){
        this.ballBackPosition();
    }else{
        this.ballAutoPosition();
    }
    this.ballActor = [];
}
// 隨機散開
Circle.prototype.ballAutoPosition = function(ball){
    for(var i=0;i<this.actorNumber;i++){
        this.changeStatus(this.ballActor[i])
    }
}
// 更改小球狀態(tài)
Circle.prototype.changeStatus = function(ball){
    ball.status = 0;
    if(this.isPlay == true){
        this.isPlay = false;
    }
}
// 隨機生成每個圓的相關參數(shù)
Circle.prototype.generalRandomParam = function(){
    for(var i=0;i<this.ballNumber;i++){
        var ball = {};
        ball.size = 1; // 隨機生成圓半徑
        // 隨機生成圓心 x 坐標
        ball.x = ramdomNumber(0+ball.size, this.iCanvasW-ball.size);
        ball.y = ramdomNumber(0+ball.size, this.iCanvasH-ball.size);
        ball.speedX = ramdomNumber(-1, 1);
        ball.speedY = ramdomNumber(-1, 1);
        this.balls.push(ball);
        ball.status = 0;
        ball.targetX = 0;
        ball.targetY = 0;
        ball.backX = 0;
        ball.backY = 0;
    }
}
// 改變圓的位置
Circle.prototype.changeposition = function(){
    for(var i=0;i<this.ballNumber;i++){
        if( this.balls[i].status == 0){
            this.balls[i].x += this.balls[i].speedX;
            this.balls[i].y += this.balls[i].speedY;
        }
    }
}
// 畫圓
Circle.prototype.renderBall = function(ball){
    this.ctx.fillStyle = "#fff";
    this.ctx.beginPath(); // 這個一定要加
    this.ctx.arc(ball.x, ball.y, ball.size, 0, 2 * Math.PI);
    this.ctx.closePath(); // 這個一定要加
    this.ctx.fill();
}
// 小球碰撞判斷
Circle.prototype.collision = function(ball){
    for(var i=0;i<this.ballNumber;i++){
       if(ball.x>this.iCanvasW-ball.size || ball.x<ball.size){
            if(ball.x>this.iCanvasW-ball.size){
                ball.x = this.iCanvasW-ball.size;
            }else{
                ball.x = ball.size;
            }
            ball.speedX = - ball.speedX;
       }
       if(ball.y>this.iCanvasH-ball.size || ball.y<ball.size){
            if(ball.y>this.iCanvasH-ball.size){
                ball.y = this.iCanvasH-ball.size;
            }else{
                ball.y = ball.size;
            }
            ball.speedY = - ball.speedY;
       }
    }
}
// 開始動畫
Circle.prototype.ballAnimate = function(){
    var This = this;
    var animateFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
    (function move(){
        animte = animateFrame(move);
        This.ctx.clearRect(0, 0, This.iCanvasW, This.iCanvasH);
        This.changeposition();
        for(var i=0;i<This.ballNumber;i++){
           This.collision(This.balls[i]);
           This.renderBall(This.balls[i]);
        }
    })();
}
// 生成一個隨機數(shù)
function ramdomNumber(min, max) {
    return Math.random() * (max - min) + min;
}

看了代碼估計也只是心里炫了一下,也沒有讓你想把這個東西做出來的欲望,為此我知道必需得讓你眼睛心服口服才行。在線 DEMO: 動感的粒子示例。

人無完人,代碼也一樣。看起來運行順暢的代碼也或多或少有一些瑕疵,日前這個效果還只支持中文。英文的話,我得再努力一把,不管怎么樣,英文后面肯定是會加入來的,只是時間問題了。還有代碼中用于標記是否可再次執(zhí)行生成文字的 屬性:this.isPlay ,還是一點瑕疵,this.isPlay 的狀態(tài)更改沒有準確的在粒子歸位的那一瞬間更改,而是提前更改了狀態(tài)。但這個狀態(tài)不會影響本例子效果的完整實現(xiàn)。

這個例子中用到了 dynamics.js 庫,主要是用到它里面的一些運動函數(shù),讓粒子動起來更感人一些,僅此而已。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

 

標簽:惠州 萍鄉(xiāng) 蘇州 文山 營口 咸陽 甘南 紅河

巨人網(wǎng)絡通訊聲明:本文標題《詳解Canvas 實現(xiàn)炫麗的粒子運動效果(粒子生成文字)》,本文關鍵詞  詳解,Canvas,實現(xiàn),炫麗,的,粒子,運動,效果,生成,;如發(fā)現(xiàn)本文內(nèi)容存在版權問題,煩請?zhí)峁┫嚓P信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《詳解Canvas 實現(xiàn)炫麗的粒子運動效果(粒子生成文字)》相關的同類信息!
  • 本頁收集關于詳解Canvas 實現(xiàn)炫麗的粒子運動效果(粒子生成文字)的相關信息資訊供網(wǎng)民參考!
  • 推薦文章
    校园春色亚洲色图_亚洲视频分类_中文字幕精品一区二区精品_麻豆一区区三区四区产品精品蜜桃
    欧美精品一区在线观看| 国产精品伦一区| 成人欧美一区二区三区小说| 天天色综合天天| 北条麻妃一区二区三区| 欧美一区二区福利在线| 亚洲精品久久久蜜桃| 国产在线视频一区二区三区| 欧美日韩1234| 亚洲乱码一区二区三区在线观看| 国产揄拍国内精品对白| 欧美日韩亚洲综合| 亚洲精品一二三| 99精品黄色片免费大全| 国产日韩欧美电影| 韩国理伦片一区二区三区在线播放| 色婷婷综合久久久| 中文字幕色av一区二区三区| 国产一区二区不卡在线| 91精品国产91久久综合桃花| 午夜精品福利在线| 欧美自拍丝袜亚洲| 一区二区三区欧美| 91黄视频在线| 一区二区国产盗摄色噜噜| 欧美三日本三级三级在线播放| 日韩毛片在线免费观看| av不卡在线播放| 国产精品久久久久久户外露出| 丁香激情综合国产| 中文在线免费一区三区高中清不卡| 国产风韵犹存在线视精品| 久久只精品国产| 成人美女视频在线观看18| 国产精品色眯眯| 99国产精品一区| 曰韩精品一区二区| 欧美在线视频你懂得| 亚洲成人高清在线| 欧美一卡二卡在线观看| 久久99国产精品免费网站| www国产精品av| 岛国精品一区二区| 亚洲精品视频一区| 在线观看91av| 精品写真视频在线观看| 国产欧美日韩综合| 91老司机福利 在线| 亚洲成av人片一区二区| 日韩色视频在线观看| 国产精品亚洲专一区二区三区 | 久久国产三级精品| 26uuu精品一区二区在线观看| 国产白丝精品91爽爽久久| 国产精品色哟哟网站| 91九色02白丝porn| 美国十次综合导航| 国产精品国产三级国产三级人妇| 91免费视频网| 久久成人免费日本黄色| 国产精品女同一区二区三区| 在线免费一区三区| 国产又黄又大久久| 亚洲一区免费在线观看| 精品国产一区二区精华| 99久久免费国产| 日韩va亚洲va欧美va久久| 久久久久国产精品厨房| 欧洲视频一区二区| 激情深爱一区二区| 亚洲国产精品久久人人爱| 久久免费美女视频| 欧美日韩亚洲综合在线 | 美美哒免费高清在线观看视频一区二区 | 中文天堂在线一区| 欧美乱妇15p| 成人国产视频在线观看| 日韩精品一二三四| 国产蜜臀97一区二区三区| 欧美日韩午夜精品| 99久久久国产精品| 久久av中文字幕片| 五月婷婷欧美视频| 亚洲欧洲三级电影| www国产成人| 777xxx欧美| 色婷婷国产精品综合在线观看| 国产一区二区三区香蕉| 亚洲成年人网站在线观看| 亚洲色欲色欲www| 国产欧美一区二区精品仙草咪| 欧美精品少妇一区二区三区| 99v久久综合狠狠综合久久| 激情另类小说区图片区视频区| 亚洲无人区一区| 亚洲女厕所小便bbb| 久久久噜噜噜久久人人看| 91精品久久久久久蜜臀| 欧美性色黄大片手机版| 99在线热播精品免费| 大尺度一区二区| 国产一区二区三区免费播放 | 亚洲欧美精品午睡沙发| 中文字幕欧美日韩一区| 久久色成人在线| 欧美大片在线观看一区| 日韩免费视频线观看| 日韩欧美的一区二区| 日韩一区二区三区电影| 91.com在线观看| 欧美放荡的少妇| 欧美一级欧美三级| 欧美一级二级三级蜜桃| 91精品国产全国免费观看| 欧美一区二区三区思思人| 日韩色视频在线观看| 日韩一二三四区| 欧美精品一区二区久久婷婷| 精品成人私密视频| 久久久久久久久免费| 欧美精彩视频一区二区三区| 中文字幕不卡在线播放| 一色桃子久久精品亚洲| 国产精品久久久久影院色老大| 欧美韩国日本一区| 中文字幕在线观看一区| 亚洲精品亚洲人成人网| 亚洲风情在线资源站| 日韩不卡免费视频| 国产河南妇女毛片精品久久久| 99久久久精品| 在线不卡的av| 久久网站热最新地址| 国产日产精品1区| 亚洲男人都懂的| 婷婷综合五月天| 国产一区二区视频在线播放| 92精品国产成人观看免费| 欧美影院午夜播放| 精品国产电影一区二区| 国产精品美女久久久久aⅴ | 91精品久久久久久久99蜜桃| 精品国产1区2区3区| 欧美激情一区二区三区| 亚洲在线观看免费| 美洲天堂一区二卡三卡四卡视频| 国产高清不卡一区二区| 色素色在线综合| 精品欧美黑人一区二区三区| 欧美激情综合五月色丁香小说| 亚洲一区二区三区三| 狠狠色伊人亚洲综合成人| 91国偷自产一区二区开放时间 | 精品国产免费一区二区三区香蕉| 国产精品美女久久福利网站| 三级在线观看一区二区| 国产成人免费在线视频| 欧美男女性生活在线直播观看| 欧美激情一区二区三区全黄| 香蕉影视欧美成人| 99精品视频在线播放观看| 欧美一区二区福利视频| 亚洲欧美福利一区二区| 久久精品国产澳门| 91久久精品午夜一区二区| 国产清纯在线一区二区www| 尤物在线观看一区| 国产高清精品网站| 日韩一卡二卡三卡| 一区二区三区高清在线| 国产成人av电影免费在线观看| 欧美巨大另类极品videosbest| 亚洲天堂成人网| 国产aⅴ精品一区二区三区色成熟| 欧美片在线播放| 夜夜夜精品看看| 成人app下载| 欧美经典三级视频一区二区三区| 麻豆精品在线看| 91精品国产一区二区三区蜜臀| 亚洲欧美aⅴ...| 91在线小视频| 国产精品成人网| 国产aⅴ综合色| 国产欧美日产一区| 国产麻豆精品视频| 欧美精品一区二区三区四区 | 欧美va亚洲va香蕉在线| 亚洲国产综合色| 日本久久一区二区三区| 亚洲欧美日韩中文字幕一区二区三区| 国产成人精品影视| 久久综合久久综合久久| 日本aⅴ亚洲精品中文乱码| 欧美日韩国产高清一区二区 | 不卡一二三区首页| 久久久噜噜噜久久人人看 | 精品亚洲porn| 26uuu成人网一区二区三区| 99国产精品视频免费观看|