Reputation: 5255
I'm trying to implement an infinite background scene scroll that is controlled by the mousemove on a canvas
I have the following in a requestAnimationFrame working almost right
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();
However the problem comes in when I have reached the end of the canvas edges and need to "loop" the image... can't figure out how to reposition the images after going out of view in relation to the mouse position
Any insight on this?
Update:
I'm able to get a continuous scroll but I believe its being messed up by an e.preventDefault on the document element while i'm running the 'touchmove' on the canvas element itself...
Is it safer to run the code on the canvas or the document?
Upvotes: 0
Views: 84
Reputation: 19294
Most simple way is to do two passes : one down, one up
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();
(you might notice i started the work in case you want images with different heights : just add
var im = someImageArray[i];
in each for loop.)
Upvotes: 0
Reputation: 105035
Here's one way of creating an infinite panorama:
Create a horizontally mirrored image from your source image.
Create an animation loop that draws first the original & then the mirror image to the right of the original image..
Panning Visually Rightward: With each loop, offset the images by 1 pixel leftward (offset--). When the offset is the size of original+mirror width, then reset the offset to zero.
Panning Visually Leftward: Start with an offset=-(original+mirror width), With each loop, offset the images by 1 pixel rightward (offset++). When the offset is zero, then reset the offset to -(original+mirror).
Mouse Control: You can use the mouse-X position to determine to calculate your desired offset (which in turn determines your position within the infinite panorama).
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>
Upvotes: 1