【问题标题】:Scroll canvas horizontally水平滚动画布
【发布时间】:2013-06-21 02:18:49
【问题描述】:

我正在尝试绘制一个“无限”图,我的想法是我将通过将画布向左移动一个像素来重新绘制画布,然后清除最右边的列,将一个像素绘制到已清除的列中。但是有些东西不起作用,我无法理解是什么。下面的示例代码:

var telemetryScreen, telemetryTimer;

function displayUI() {
    if (!telemetryScreen) {
        telemetryScreen = document.createElement("div");
        telemetryScreen.className = "telemetry-screen";
        document.body.appendChild(telemetryScreen);
    }
    return telemetryScreen;
}

var plotFps = function(canvas) {
    canvas.className = "telemetry-fps";
    canvas.width = 320;
    canvas.height = 240;
    canvas.getContext("2d").fillStyle = "red";
    if (!telemetryScreen) displayUI().appendChild(canvas);
    return function (delta) {
        var context = canvas.getContext("2d");
        context.drawImage(canvas, 1, 0, 319, 240, 0, 0, 319, 240);
        context.clearRect(319, 0, 1, 240);
        context.fillRect(319, 120 + delta, 1, 1);
    };
}(document.createElement("canvas"));

function startSampling() {
    var now, delta, last, start = new Date().getTime(),
    seconsPerFrame = 16;
    if (telemetryTimer) clearInterval(telemetryTimer);
    telemetryTimer = setInterval(
        function () {
            last = now;
            now = new Date().getTime();
            delta = now - last - seconsPerFrame;
            plotFps(delta);
        }, seconsPerFrame);
    // We don't anticipate framerates
    // higher then 60 fps
}

startSampling();

我也尝试过translate(),但在画布滚动超过其宽度之一后它停止工作:/

【问题讨论】:

    标签: javascript canvas


    【解决方案1】:

    创建无限平移效果:

    • 每一帧,在前一帧左侧几个像素处绘制图像(或图形)
    • 在右侧的“空白”像素中绘制图像(或图形)的副本

    这是图像的基本代码(您可以改为绘制图表):

        var fps = 60;
        var offsetLeft=0;
        function pan() {
    
            // increase the left offset
            offsetLeft+=1;
            if(offsetLeft>infiniteImageWidth){ offsetLeft=0; }
    
            ctx.drawImage(infiniteImage,-offsetLeft,0);
            ctx.drawImage(infiniteImage,infiniteImage.width-offsetLeft,0);
    
            setTimeout(function() {
                requestAnimFrame(pan);
            }, 1000 / fps);
        }
    

    这是代码(由于愚蠢的 CORS 安全性,您需要提供自己的图像):

    您可以忽略“镜像”效果,该效果用于在山景图像上创建无缝过渡。

    <!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: ivory; }
        canvas{border:1px solid red;}
    </style>
    
    <script>
    $(function(){
    
        // thanks Paul Irish for this RAF fallback shim
        window.requestAnimFrame = (function(callback) {
          return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
          function(callback) {
            window.setTimeout(callback, 1000 / 60);
          };
        })();
    
    
        var canvas=document.getElementById("canvas");
        var ctx=canvas.getContext("2d");
    
        var infiniteImage;
        var infiniteImageWidth;
        var img=document.createElement("img");
        img.onload=function(){
    
          // use a tempCanvas to create a horizontal mirror image
          // This makes the panning appear seamless when
          // transitioning to a new image on the right
          var tempCanvas=document.createElement("canvas");
          var tempCtx=tempCanvas.getContext("2d");
          tempCanvas.width=img.width*2;
          tempCanvas.height=img.height;
          tempCtx.drawImage(img,0,0);
          tempCtx.save();
          tempCtx.translate(tempCanvas.width,0);
          tempCtx.scale(-1,1);
          tempCtx.drawImage(img,0,0);
          tempCtx.restore();
          infiniteImageWidth=img.width*2;
          infiniteImage=document.createElement("img");
          infiniteImage.onload=function(){
              pan();
          }
          infiniteImage.src=tempCanvas.toDataURL();
        }
        img.src="YourLandscapeImage.jpg";
    
    
        var fps = 60;
        var offsetLeft=0;
        function pan() {
    
            // increase the left offset
            offsetLeft+=1;
            if(offsetLeft>infiniteImageWidth){ offsetLeft=0; }
    
            ctx.drawImage(infiniteImage,-offsetLeft,0);
            ctx.drawImage(infiniteImage,infiniteImage.width-offsetLeft,0);
    
            setTimeout(function() {
                requestAnimFrame(pan);
            }, 1000 / fps);
        }
    
    }); // end $(function(){});
    </script>
    
    </head>
    
    <body>
        <canvas id="canvas" width=500 height=143></canvas><br>
    </body>
    </html>
    

    【讨论】:

    • 谢谢,我想我最终以不同的方式解决了这个问题,但这似乎也有效。 (我用使用背景颜色的drawRect 替换了clearRect。)仍然很尴尬clearRect 似乎没有做它应该做的事情,但是,它并没有在浏览器中始终如一地做到这一点,所以它必须做一些我不明白的事情。
    猜你喜欢
    • 2012-12-31
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多