記一次requestAnimationFrame之後頁面崩潰、內存泄漏問題

canvas 內存泄漏問題

前言

要解決的問題

公司項目有個地方用到 canvas 做出流光動畫。但是做出來之後,造成的內存無法釋放,頁面掛的時間久了一點點就開始頁面崩潰

源代碼

// 首先獲取canvas
// 在利用 getContext()方法返回一個用於在畫布上繪圖的環境。
let c = document.getElementById("myCanvas");
let context = c.getContext("2d");
// 獲取需要用到的公用屬性 canvas的長度和寬度
let width = c.width;
let height = c.height;
let canvasPoints;
canvasPoints= [{x:100,y:0,r:3},{x:200,y:0,r:3}];
// 開始在畫布上畫點
function canvasChart() {
    for(let i = 0; i < xPoints.length; i++){

        boxWidth = box.clientWidth;
        num = (1903 - boxWidth)/2;

        context.lineWidth = 0;
        context.shadowBlur = 0;
        context.shadowColor = 'rgba(2, 179, 253,1)';
        context.fillStyle = 'rgba(2, 179, 253,1)';
        context.fill();//畫實心圓
        context.beginPath();
        context.arc(canvasPoints[i].x, canvasPoints[i].y, canvasPoints[i].r, 0, Math.PI * 2);
        context.stroke();
    }
    V();
}
// 設置運動的速度,當Y座標到了500的時候,在初始化xPoints座標
function V () {
    if (canvasPoints[0].y < 200) {
        canvasPoints[0].x += 1;
        canvasPoints[0].y += 1;
    } else {
        canvasPoints= [{x:100,y:0,r:3},{x:200,y:0,r:3}];
    }
}
// 利用 requestAnimationFrame 重複執行該動畫
function render() {
    let prev = context.globalCompositeOperation;
    context.globalCompositeOperation = 'destination-in';
    context.globalAlpha = 0.5;
    context.fillRect(0, 0, width, height);
    context.globalCompositeOperation = prev;
    //在主canvas上畫新圓
	canvasChart();
    if (width !== 0) {
    /*這裏執行了之後沒有停止動畫*/
    window.requestAnimationFrame(render);
    }
}

源代碼中,執行了requestAnimationFrame之後沒有停止,canvasChart()沒有加判斷,導致requestAnimationFrame會無線重複的執行下去,所以這裏需要用到 canceAnimationFrame去停止定時器

在上述代碼中,需要在canvasChart()

// 利用 requestAnimationFrame 重複執行該動畫
function render() {
    let prev = context.globalCompositeOperation;
    context.globalCompositeOperation = 'destination-in';
    context.globalAlpha = 0.5;
    context.fillRect(0, 0, width, height);
    context.globalCompositeOperation = prev;
    //在主canvas上畫新圓
	/*這裏執行了之後沒有停止動畫,加if判斷*/
    if(status) {
		canvasChart();
	} else{
		window.canceAnimationFrame (canvasAnimation );
	}
    if (width !== 0) {
    /*這裏執行了之後沒有停止動畫*/
     canvasAnimation = window.requestAnimationFrame(render);
    }
}

! 不過需要考慮canceAnimationFrame的兼容性。這裏大家自行注意

參考文獻:記一次用canvas做出騰訊雲首頁banner流光效果的經歷

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章