内容通过鼠标移动在画布上滚动

时间:2014-09-17 14:32:57

标签: javascript html5 canvas

我试图在画布上实现由 mousemove 控制的无限背景场景滚动

我在 requestAnimationFrame 中的工作几乎正确

 y1 = y1 >= h? y1 - h : y1; // y1 is the current mouse position on('drag') less the offset  if the position is greater than height of canvas reset with offset
 c.font="20px Georgia";
 c.clearRect(0,0, w, h); // w, h is the width and height of canvas
 c.save();
 //c.translate(0, y1);
 for (var i = 0; i < numImages; i++) { // number of images to be drawn to fill area
    var y = y1 + (i * im.height); // reposition the images relative to mouse position
    y = y >= h? - im.height + y1 : y; // if the image position is off screen then re position to top relative to mouse
    c.drawImage(im, 0, y, im.width, im.height);
 }
 c.fillText("y: " + y,10,190);
 c.restore();

然而,当我到达画布边缘并且需要&#34;循环&#34;时会出现问题。图像...无法弄清楚如何在离开视图后重新定位图像相对于鼠标位置

对此有何见解?

更新

我能够连续滚动,但我相信它会被文档元素上的 e.preventDefault 搞砸了>当我在画布元素本身上运行 &#39; touchmove&#39; 时...

画布或文档上运行代码是否更安全?

2 个答案:

答案 0 :(得分:1)

以下是创建无限全景的一种方法:

  • 从源图像创建水平镜像图像。

  • 创建一个动画循环,首先绘制原始&amp;然后是原始图像右侧的镜像..

  • 向右平移:对于每个循环,将图像向左偏移1个像素(偏移 - )。当偏移量是原始+镜像宽度的大小时,则将偏移量重置为零。

  • 向左平移:以偏移= - (原始+镜像宽度)开始,每个循环向右偏移1个像素(偏移++)。当偏移为零时,将偏移重置为 - (原始+镜像)。

  • 鼠标控制:您可以使用鼠标X位置来确定计算所需的偏移量(这又决定了您在无限全景图中的位置)。

    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.crossOrigin="anonymous";
    img.src="https://dl.dropboxusercontent.com/u/139992952/stackoverflow/mountain.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() {
        requestAnimationFrame(pan);
      }, 1000 / fps);
    }
    body{ background-color: ivory; }
    canvas{border:1px solid red;}
    <h4>Infinite panorama using mirror image</h4>
    <canvas id="canvas" width=500 height=143></canvas>

答案 1 :(得分:0)

最简单的方法是做两次传球:一次传球,一次传球

 y1 = y1 >= h? y1 - h : y1; // y1 is the current mouse position on('drag') less the offset  if the position is greater than height of canvas reset with offset
 c.font="20px Georgia";
 c.clearRect(0,0, w, h); // w, h is the width and height of canvas
 c.save();
 var cumulatedHeight=0;
 for (var i = 0; i < numImages; i++) { // number of images to be drawn to fill area
    var y = y1 + cumulatedHeight; // reposition the images relative to mouse position
    if (y>h) break;
    c.drawImage(im, 0, y, im.width, im.height);
    cumulatedHeight+= im.height;
 }
 cumulatedHeight=0;
 for (var i = numImage-1; i >=0; i--) { // number of images to be drawn to fill area
    cumulatedHeight+= im.height;
    var y = y1 - cumulatedHeight; // reposition the images relative to mouse position
    if (y+im.height<0) break;
    c.drawImage(im, 0, y, im.width, im.height);        
 }
 c.fillText("y: " + y,10,190);
 c.restore();

(你可能会注意到我开始工作以防你想要不同高度的图像:只需添加

 var im = someImageArray[i];

在每个for循环中。)