iT邦幫忙

2021 iThome 鐵人賽

DAY 2
0
Modern Web

JavaScript 嗨起來用 JS 做動畫 ε= ᕕ( ᐛ )ᕗ系列 第 2

Day02 - 用 canvas 做漸變色塗鴉筆

  • 分享至 

  • xImage
  •  

今天想做色彩漸變,角色很單純只有筆刷一位,預計做出的效果是在網頁上用滑鼠塗色,讓筆刷跟著滑鼠游標移動,並且滑鼠移動時記錄當下的筆刷位子(其實也就是當下的滑鼠的位子),讓滑鼠經過的地方都留下筆刷的痕跡

https://ithelp.ithome.com.tw/upload/images/20210917/20140513uxg73ecglj.jpg

工具

// 今天一樣建立 Vector 當做存位子的工具
//((雖然這個練習很迷你,其實不用特別建 Vector
var Vector = function (x, y) {
    this.x = x;
    this.y = y;
};

角色
筆刷

// 筆刷
// 因為想讓筆刷使用跟舞台同一個 canvas 所以預留一個 ctx 參數,等等舞台邀請角色上台時傳入
var Pen = function (ctx){
    this.ctx = ctx;
    this.pos = new Vector(500,200);
    this.r = 60;
    this.rgb = [232, 167, 167];
    this.color = `(${this.rgb[0]},${this.rgb[1]},${this.rgb[2]})`;
};

舞台
角色預設就在舞台上,並設定舞台的初始化

var Game = function () {
    this.infectCanvas = document.getElementById('infectCanvas')
    this.ctx = infectCanvas.getContext('2d');
    
    // 歡迎主角 Pen 上台
    this.pen = new Pen(this.ctx);
    
    // 裝所有 pens
    this.pens = [];
    
    // 預計讓這個 t 會隨著每次執行 update 時上升,等等在 update function 見
    this.t = 0;
    this.init();
    
};
Game.prototype.init = function(){
    this.infectCanvas.width = window.innerWidth;
    this.infectCanvas.height = window.innerHeight;
    // 初始化記得要 render 畫面、update 資料
    this.render();
    this.update();
};

設定 render 函數將畫舞台佈景與角色畫到 canvas 上

Game.prototype.render = function () {
    this.ctx.beginPath();
    this.ctx.fillStyle = '#ebc5c5';
    this.ctx.fillRect(0, 0, this.infectCanvas.width, this.infectCanvas.height);

    // pens
    // 在 canvas 畫布畫出每個筆刷經過的位子
    this.pens.forEach((pen) => {
        this.ctx.beginPath();
        this.ctx.fillStyle = pen.color;
        this.ctx.arc(pen.pos.x, pen.pos.y, this.pen.r, 0, Math.PI * 2);
        this.ctx.fill();
    })
    
    // 重複 render 畫面
    requestAnimationFrame(()=>this.render())
};

本日漸變色重頭戲!
透過時間更新 rgb 三色彩數值之一起向 google color picker 學習漸變色

我先透過觀察 google color picker,當我初始顏色為 rgb(232,167,167) 時,拖移 google color picker 拉吧,會發現顏色一開始 rgb(232,167,167) 的 r 與 b 都不變,只有 g 從 167 上升到 232,也就是整體變成rgb(232,167,167)

接著換 g 與 b 都不變,r 從 232 一路下降到 167,一路拖移 color picker 的拉吧找出漸變的規律
https://ithelp.ithome.com.tw/upload/images/20210917/20140513JPEiKPzFOl.jpg


Game.prototype.update = function() {
    // 每更新一次資料 t 就加一
    this.t++;
    
    // 因為我們用重複執行 update 的頻率很高,所以設個 ts 作為低頻一點的數字
    this.ts = parseInt(this.t/3);

    // 以下出現 65 與 390 的原因就是透過 color picker 啦吧拖曳
    //發現色彩數值每次上升/下降的幅度都是 65,而且總共有六段的上升/下降
    // 所以 65*6 = 390,以 390 為一個循環
    // ts 每過多 390,其 ts%390 這裡的餘數就又從 0 開始上升,讓漸變色循環更新
    
    // 從 rgb(232,167,167) 到 rgb(232,232,167)
    if (this.ts%390 <65){
        this.pen.rgb[1] += 1;

    // 從 rgb(232,232,167) 到 rgb(167,232,167)
    }else if (this.ts%390 >65 && this.ts%390 <65*2 ){
        this.pen.rgb[0] -= 1;
    }
    // 從 rgb(167,232,167) 到 rgb(167,232,232)
    else if (this.ts%390 >65*2 && this.ts%390 <65*3 ){
        this.pen.rgb[2] += 1;
    }
    // 從 rgb(167,232,232) 到 rgb(167,167,232)
    else if (this.ts%390 >65*3 && this.ts%390 <65*4 ){
        this.pen.rgb[1] -= 1;
    }
    // 從 rgb(167,167,232) 到 rgb(232,167,232)
    else if (this.ts%390 >65*4 && this.ts%390 <65*5 ){
        this.pen.rgb[0] += 1;
    }
    // 從 rgb(232,167,232) 到 rgb(232,167,167)
    else if (this.ts%390 >65*5 && this.ts%390 <=65*6 ){
        this.pen.rgb[2] -= 1;
    }
    this.pen.color = `rgb(${this.pen.rgb[0]}, ${this.pen.rgb[1]}, ${this.pen.rgb[2]})`;

    // 重複更新資料
    setTimeout(()=>this.update());
};

// 要建立舞台遊戲才會開始喔
var game = new Game()

mouse event

game.infectCanvas.addEventListener('mousemove',function(e) {
    game.pen.pos = new Vector(e.x, e.y);
    game.pens.push({
        pos: game.pen.pos,
        color: game.pen.color,
    });
})

之後再來認真看網路上的大大做的漸變效果 Animated Background Gradient


如果理解有誤的地方,或有其他漸變色產出方式,都希望路過的朋友能提點提點交流交流啦 ε= ᕕ( ᐛ )ᕗ


上一篇
Day01 - 複習 canvas 做個同化別人的小方塊
下一篇
Day03 - 複習 canvas translate 與 rotate
系列文
JavaScript 嗨起來用 JS 做動畫 ε= ᕕ( ᐛ )ᕗ17
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言