admin管理员组文章数量:1313006
I am looking for a way to wrap a bitmap image around the canvas, for an infinite scrolling effect. I'm looking at EaselJS but clean javascript code will also suffice.
Right now I am displacing an image to the left, and when it reaches a certain mark, it resets itself.
Coming from actionscript, there was an option to "wrap" the pixels of a bitmap around to the other side, thereby never really displacing the image, instead you were wrapping the pixels inside the image. Is this possible in javascript with canvas?
My current code:
this.update = function() {
// super large graphic
_roadContainer.x -= 9;
if(_roadContainer.x < -291) _roadContainer.x = 0;
}
I am looking for a way to wrap a bitmap image around the canvas, for an infinite scrolling effect. I'm looking at EaselJS but clean javascript code will also suffice.
Right now I am displacing an image to the left, and when it reaches a certain mark, it resets itself.
Coming from actionscript, there was an option to "wrap" the pixels of a bitmap around to the other side, thereby never really displacing the image, instead you were wrapping the pixels inside the image. Is this possible in javascript with canvas?
My current code:
this.update = function() {
// super large graphic
_roadContainer.x -= 9;
if(_roadContainer.x < -291) _roadContainer.x = 0;
}
Share
Improve this question
asked Nov 28, 2013 at 10:45
KokodokoKokodoko
28.2k36 gold badges132 silver badges205 bronze badges
3 Answers
Reset to default 5Start with a good landscape image.
Flip the image horizontally using context.scale(-1,1).
Combine the flipped image to the right side of the original image.
Because we have exactly mirrored the images, the far left and right sides of the bined image are exactly the same.
Therefore, as we pan across the bined image and “run out of image”, we can just add another copy of the bined image to the right side and we have infinite + seamless panning.
Here's code and a Fiddle: http://jsfiddle/m1erickson/ywDp5/
<!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./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.crossOrigin="anonymous";
img.src="https://dl.dropboxusercontent./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() {
requestAnimFrame(pan);
}, 1000 / fps);
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=500 height=143></canvas><br>
</body>
</html>
You can achieve this quite easily with the html5 canvas.
Look at the drawImage specification here :
http://www.whatwg/specs/web-apps/current-work/multipage/the-canvas-element.html#drawing-images
drawImage es in 3 flavors, the first being a simple copy of the image, the second allowing to scale the image, and the third is the one you seek, it allows to perform clipping in a single call.
What you have to do :
- have a counter that will move from zero to the width of your image, then loop to zero again.
- each frame, draw the maximum of the image that you can on the canvas.
- If there is still some part of the canvas not drawn, draw again the image starting from zero to fill the canvas.
i made a fiddle, the only part that matters is in the animate function (other things are tools i often use in my fiddles).
(Rq : I assumed in this example that two images would be enough to fill the canvas.)
http://jsfiddle/gamealchemist/5VJhp/
var startx = Math.round(startPos);
var clippedWidth = Math.min(landscape.width - startx, canvasWidth);
// fill left part of canvas with (clipped) image.
ctx.drawImage(landscape, startx, 0, clippedWidth, landscape.height,
0, 0, clippedWidth, landscape.height);
if (clippedWidth < canvasWidth) {
// if we do not fill the canvas
var remaining = canvasWidth - clippedWidth;
ctx.drawImage(landscape, 0, 0, remaining, landscape.height,
clippedWidth, 0, remaining, landscape.height);
}
// have the start position move and loop
startPos += dt * rotSpeed;
startPos %= landscape.width;
To answer my own question: I found a way to achieve this effect with EaselJS. The great benefit of this method is that you don't have to check for the position of your bitmap. It will scroll infinitely - without ever resetting the position to 0.
The trick is to fill a shape with a bitmapfill. You can set a bitmapfill to repeat infinitely. Then you use a Matrix2D to decide the offset of the bitmapfill. Since it repeats automatically, this will generate a scrolling effect.
function.createRoad() {
// road has a matrix, shape and image
_m = new createjs.Matrix2D();
// this gets the image from the preloader - but this can be any image
_r = queue.getResult("road");
// this creates a shape that will hold the repeating bitmap
_roadshape = new createjs.Shape();
// put the shape on the canvas
addChild(_roadshape);
}
//
// the draw code gets repeatedly called, for example by requestanimationframe
//
function.drawRoad() {
// var _speed = 4;
_m.translate(-_speed, 0);
_roadshape.graphics.clear().beginBitmapFill(_r, "repeat", _m).rect(0, 0, 900, 400);
}
本文标签: javascriptMake a bitmap wrap around the canvas for infinite scrollingStack Overflow
版权声明:本文标题:javascript - Make a bitmap wrap around the canvas for infinite scrolling - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741894203a2403481.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论