1. 程式人生 > >使用 typescript 和 canvas 重構snow效果

使用 typescript 和 canvas 重構snow效果

讀取圖片 網上 個數 chrom 會有 img ear 練手 查看

前言:之前做過一個 snow 效果,但是是直接用 HTML 做的 點擊此處查看 ,幾個星期前,我用 typescript 和 canvas 重構了一下,
snow效果是一個很簡單的效果,但是用來練手還是不錯的;

  • 首先創建基本變量:
let canvas = <HTMLCanvasElement>document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let H = canvas.height = window.innerHeight;
let W = canvas.width = window.innerWidth;
ctx.fillStyle = "#53B7F6";

在獲取 canvas 的 dom 時可能後報錯,所以要用斷言或者 let canvas:any 這樣來寫,不然會報錯;
這裏讓 canvas 的長,寬分別等於瀏覽器視窗的長寬,顏色為藍色,如果想做背景,可以去掉;

  • 獲取圖片文件:
const renderImg = (x: number = 10, y: number = 10): void => {
    ctx.drawImage(snowImg, x, y, 42, 30);
};

let readStatus: boolean = false;

let snowImg: any = new Image();
snowImg.onload = (): void => {
    readStatus = true;
};

snowImg.src = 'snow.jpg';

要記得讀取圖片的函數是異步執行的,所以添加一個狀態,來判斷圖片是否已加載,而 renderImg 函數呢,就是在 canvas 上繪制圖片,
他有初始值x=10,y=10,後面的42,30 是圖片的大小,這個如果你換一個圖片的話需要好好調節這2個數值;

  • 創建例子存儲數組:
const snowNum: number = 8;

interface snowType {
    x: number,
    y: number,
    stepX: number,
    stepY: number
}


let store: snowType[] = [];

const add = (): void => {
    let num: number = snowNum * Math.random() | 0;
    while (num--) {
        store.push({
            x: Math.random() * W | 0,
            y: 0,
            stepX: (Math.random() * 5 - 2) | 0,
            stepY: ((Math.random() * 8) | 0) + 2
        })
    }
};

snowNum 的作用是每秒最多出現8片 snow,store 中存儲了 snow 的坐標位置,和每秒的移動速度;

  • 渲染函數:
const render = (): void => {
    if (!readStatus) return;
    clearBg();
    let length: number = store.length;
    while (length--) {
        let {x, y, stepX, stepY}:snowType = store[length];
        renderImg(x, y);
        store[length].x += stepX;
        store[length].y += stepY;
        if (check(store[length])) {
            store.splice(length, 1);
        }
    }
};

通過坐標來渲染圖片並添加移動,做出判斷,當 snow 移動到瀏覽器底部時刪除他;

  • 時間計時:
let addTime: number = 0;
let lastTime: number = 0;

const animotion = (timestamp: number = 0): void => {
    if (timestamp - lastTime > 50) {
        render();
        lastTime = timestamp;
    }
    if (timestamp - addTime > 1000) {
        add();
        addTime = timestamp;
    }
    try {
        window.requestAnimationFrame(animotion);
    } catch {
        alert('你的瀏覽器不支持rAF,請更新或更換瀏覽器')
    }
};
animotion();

之前的計時我都是拿 setInterval 來做計時器的,但是會有一個缺點,不知道大家有沒碰到過,就是在 chrome 裏
切換到其他頁面是,數組仍在添加,但是已經停止了渲染,所以再切回來的時候,會出現一大堆的東西,而這個用 rAF 是沒有的,
但是他需要較高的兼容(IE>10),不過網上已經有了用 setInterval 做兼容方法,百度一下就有了,我這裏就不講了;

最後:
demo: 點擊此處查看
GitHub:https://github.com/Grewer/JsDemo/tree/master/snow

如果該文章幫到了你,還請推薦或 star;
完;

使用 typescript 和 canvas 重構snow效果