【问题标题】:Optimizing canvas animation (sine curve)优化画布动画(正弦曲线)
【发布时间】:2014-03-27 06:20:57
【问题描述】:

如何优化此代码以呈现正弦波,而不会在重新绘制画布时发生一点模糊

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);
}

【问题讨论】:

    标签: javascript html canvas


    【解决方案1】:

    一些想法:

    1. 由于 x==0 和强度==0,前 400 个图形成一条直线 (?)。

    2. 您的 setInterval 时间太短(5 毫秒)。屏幕大约每 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>
    

    【讨论】:

    • 太棒了!谢谢,请问如何通过方程式限制函数的高度?这样即使强度为 100000,它也不会高于画布高度
    • 不客气!最大/最小正弦值为 1.00 和 -1.00。所以从你的 f() 向后工作:minIntensity=100 和 maxIntensity=canvas.height-100。如果你想使用这些最小值/最大值之外的值,你将不得不缩放强度值(这也会使你的波倾斜,因为你的 x 值在每次计算中前进 1 个像素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 2020-09-11
    • 2023-03-10
    • 1970-01-01
    • 2020-05-17
    相关资源
    最近更新 更多