Reputation: 1717
What I have :
Lets take a 500px wide canvas :
+---------+
+-------------------------------------------------+
| | | |
| X XXXX | XXXXXX | X X XXXXX |
| XXX X XX | XXXX | XX X X |
| X XXXX | XXXX | XX XXXXXX XXXX |
| X XXX | XX | X XXX |
| XXXX XXXXXXX | XXXXXX | X X XX |
| | | XXXXX |
+-------------------------------------------------+
x=0 +---------+ x=500
x=200 x=300
Different drawing are there in different part of canvas.
What I want :
I want to make visible only 1/5 of canvas. Suppose in above diagram x=200 to 300 should be visible.
Ultimately I want to change visible area and produce a slide left or right effect in canvas.
Any Help and lead is appreciated :)
Upvotes: 1
Views: 1477
Reputation: 136707
Drawing on a canvas is fast, like really fast.
Also you can draw a canvas on an other one and do direct rectangular clipping operations using drawImage()
method.
So the best solution IMO, is to first draw your full canvas as a buffer (don't append it to the doc) then draw only the wanted part on the in-doc one.
Here is a rough example on how to achieve it.
// first do your full drawings on a buffer canvas
var buffer = document.createElement('canvas');
var bCtx = buffer.getContext('2d');
buffer.width = 1000;
buffer.height = 200;
bCtx.font = '30px sans-serif';
bCtx.textBaseline = 'middle';
bCtx.textAlign = 'center';
// define your slides
var slideWidth = 100;
var slides = 10;
for(var i=0;i<slides; i++){
bCtx.fillText(i, i*slideWidth+50, buffer.height/2);
bCtx.fillRect((i*slideWidth)-1, 0, 1 , buffer.height);
}
// now our full canvas is drawn
// get the inDoc's context
var ctx = inDoc.getContext('2d');
// the speed at which our slides will move
var offset = 4;
// a function to initialize our animation
var animate = function(currentSlide,to){
var direction = currentSlide<to ? 1:-1;
var from = currentPos;
// an inside func to use raf
var anim = function(){
// that was the last call, return
if(from===to){
return;
}
// clear our inDoc canvas
ctx.clearRect(0,0,inDoc.width, inDoc.height);
// increment our position
from += offset*direction;
currentPos = from;
// draw our buffer canvas onto the inDoc one
// drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh)
ctx.drawImage(buffer, from, 0, slideWidth, buffer.height, 0,0,slideWidth, buffer.height);
// do it again in 30th of a second
requestAnimationFrame(anim);
};
// call the inner animation
anim();
}
// our actual slide
var currentSlide = 0;
// our actual real position
var currentPos = 0;
next.onclick = function(){
// we'll move by one slideWidth
currentSlide += slideWidth;
// we still have room
if(currentSlide <= slides*slideWidth){
animate(currentSlide-slideWidth, currentSlide);
}
// we reached the last slide
if(currentSlide === (slides*slideWidth)-slideWidth){
this.setAttribute('disabled',true);
}
// enable the "previous" button
prev.removeAttribute('disabled');
};
prev.onclick = function(){
// we'll move by one slideWidth backward
currentSlide -= slideWidth;
// we still have room
if(currentSlide >= 0){
animate(currentSlide+slideWidth, currentSlide);
}
// we reached the first slide
if(currentSlide===0){
this.setAttribute('disabled', true);
}
// enable the "next" button
next.removeAttribute('disabled');
};
// draw the first slide
ctx.drawImage(buffer, 0, 0, slideWidth, buffer.height, 0,0,slideWidth, buffer.height);
check.onchange = function(){
this.checked ? document.body.appendChild(buffer) : document.body.removeChild(buffer);
};
body{background: skyblue;}button{ vertical-align : top;}
canvas{background: white}
<button id="prev" disabled>previous</button><canvas id="inDoc" width ="100" height="200"></canvas><button id="next">next</button>
<label for="check">show the buffer canvas</label><input name="check" id="check" type="checkbox"/>
Upvotes: 2