mccainz mccainz - 3 months ago 21
Javascript Question

Image in canvas leaves a tiled trail when panned

I am trying to create a pannable image viewer which also allows magnification. If the zoom factor or the image size is such that the image no longer paints over the entire canvas then I wish to have the area of the canvas which does not contain the image painted with a specified background color.

My current implementation allows for zooming and panning but with the unwanted effect that the image leaves a tiled trail after it during a pan operation (much like the cards in windows Solitaire when you win a game). How do I clean up my canvas such that the image does not leave a trail and my background rectangle properly renders in my canvas?

To recreate the unwanted effect set magnification to some level at which you see the dark gray background show and then pan the image with the mouse (mouse down and drag).

Code snippet added below and Plnkr link for those who wish to muck about there.
http://plnkr.co/edit/Cl4T4d13AgPpaDFzhsq1



<!DOCTYPE html>
<html>

<head>
<style>
canvas{
border:solid 5px #333;
}
</style>

</head>

<body>

<button onclick="changeScale(0.10)">+</button>
<button onclick="changeScale(-0.10)">-</button>

<div id="container">
<canvas width="700" height="500" id ="canvas1"></canvas>
</div>

<script>

var canvas = document.getElementById('canvas1');
var context = canvas.getContext("2d");
var imageDimensions ={width:0,height:0};
var photo = new Image();
var isDown = false;
var startCoords = [];
var last = [0, 0];
var windowWidth = canvas.width;
var windowHeight = canvas.height;

var scale=1;

photo.addEventListener('load', eventPhotoLoaded , false);
photo.src = "http://www.html5rocks.com/static/images/cors_server_flowchart.png";

function eventPhotoLoaded(e) {
imageDimensions.width = photo.width;
imageDimensions.height = photo.height;
drawScreen();
}

function changeScale(delta){
scale += delta;
drawScreen();
}

function drawScreen(){
context.fillRect(0,0, windowWidth, windowHeight);
context.fillStyle="#333333";
context.drawImage(photo,0,0,imageDimensions.width*scale,imageDimensions.height*scale);
}

canvas.onmousedown = function(e) {
isDown = true;

startCoords = [
e.offsetX - last[0],
e.offsetY - last[1]
];
};

canvas.onmouseup = function(e) {
isDown = false;

last = [
e.offsetX - startCoords[0], // set last coordinates
e.offsetY - startCoords[1]
];
};

canvas.onmousemove = function(e)
{
if(!isDown) return;

var x = e.offsetX;
var y = e.offsetY;

context.setTransform(1, 0, 0, 1,
x - startCoords[0], y - startCoords[1]);
drawScreen();
}


</script>
</body>

</html>




Answer

You need to reset the transform.

Add context.setTransform(1,0,0,1,0,0); just before you clear the canvas and that will fix your problem. It sets the current transform to the default value. Then befor the image is draw set the transform for the image.