优化画布动画(正弦曲线)

Optimizing canvas animation (sine curve)

本文关键字:曲线 布动画 优化 动画      更新时间:2023-09-26

我如何优化这段代码来呈现正弦波,而不会在画布重新绘制时发生小模糊

var canvas = document.getElementById("sinewave");
var points = {};
var counter = 0;
var intensity = 0;
function f(x, intensity) {
    return intensity * Math.sin(0.25 * x) + 100;
}
if (canvas.getContext) {
    var ctx = canvas.getContext("2d");
    ctx.strokeStyle = '#fff';
    ctx.lineWidth = 2;
    var x = 0,
        y = f(0,0);
    var timeout = setInterval(function() {
        if(counter < 400) {
            ctx.beginPath();
            ctx.moveTo(x, y);
            x += 1;
            y = f(x, intensity);
            points[x] = y;
            ctx.lineTo(x, y);
            ctx.stroke();
            if (x > 1000) {
                clearInterval(timeout);
            }
        } else {
            ctx.clearRect(0, 0, 400, 200);
            ctx.beginPath();
            points[x] = y;
            x += 1;
            y = f(x, intensity);
            for(var i = 0; i < 400; i++) {
                ctx.lineTo(i, points[i + counter - 400]);
            }
            ctx.stroke();
        }
        counter++;
    }, 5);
}

一些想法:

  1. 自x==0 &强度==0前400个地块形成一条直线(?)。

  2. setInterval时间太短(5ms)。屏幕大约每隔17毫秒才刷新一次,因此您正在积累浏览器将徒劳地尝试填充的间隔调用。

  3. 使用新的(ish) requestAnimationFrame代替setInterval,因为requestAnimationFrame更好地与显示硬件集成。

下面是重构代码示例和演示:http://jsfiddle.net/m1erickson/MZ7Ap/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
    body{ background-color: black; }
    canvas{border:1px solid red;}
</style>
<script>
$(function(){
    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");
    ctx.strokeStyle = '#fff';
    ctx.lineWidth = 2;
    var points = {};
    var counter = 0;
    var intensity = 2;
    var x = 0;
    var y = fz(0,0);
    animate();
    function fz(x, intensity) {
        return intensity * Math.sin(0.25 * x) + 100;
    }
    function animate(time){
        requestAnimationFrame(animate);
        draw(counter);
        counter++;
    }
    function draw(counter){
        if(counter < 400) {
            ctx.beginPath();
            ctx.moveTo(x, y);
            x += 1;
            y = fz(x, intensity);
            points[x] = y;
            ctx.lineTo(x, y);
            ctx.stroke();
            if (x > 1000) {
                clearInterval(timeout);
            }
        } else {
            ctx.clearRect(0, 0, 400, 200);
            ctx.beginPath();
            points[x] = y;
            x += 1;
            y = fz(x, intensity);
            for(var i = 0; i < 400; i++) {
                ctx.lineTo(i, points[i + counter - 400]);
            }
            ctx.stroke();
        }
    }
}); // end $(function(){});
</script>
</head>
<body>
    <canvas id="canvas" width=900 height=300></canvas>
</body>
</html>