I'm working on developing some software in HTML5 which involves the use of canvases. There is one canvas in which I need to be able to zoom and allow the user to doodle on the canvas on mouse clicks. So far, I have gotten the zoom to work, with help from some examples I found. The problem is that after zooming, the mouse position on my drawing tool is out of whack. Before any zooming, I can draw just fine. Here is the code for the zoom:
//Zoom
mainCanvas.onmousewheel = function(event) {
var mousex = event.clientX - mainCanvas.offsetLeft;
var mousey = event.clientY - mainCanvas.offsetTop;
var wheel = event.wheelDelta / 120;
//n or -n
var zoom = 0;
if(wheel < 0) {
zoom = 1 / 2;
if(currentzoom == 1)
return;
} else {
mousex = event.clientX - mainCanvas.offsetLeft;
mousey = event.clientY - mainCanvas.offsetTop;
zoom = 2;
if(currentzoom == 32)
return;
}
currentzoom *= zoom;
mainContext.translate(originx, originy);
mainContext.scale(zoom, zoom);
mainContext.translate(-(mousex / scale + originx - mousex / (scale * zoom ) ), -(mousey / scale + originy - mousey / (scale * zoom ) ));
originx = (mousex / scale + originx - mousex / (scale * zoom ) );
originy = (mousey / scale + originy - mousey / (scale * zoom ) );
scale *= zoom;
draw(mainContext, gridArray);
}
Like I said, the zoom is not the actual problem, just the root of the problem. Here is the code which determines mouse position for the drawing tool:
//this function determines the mouse position relative to the canvas element
function ev_canvas(ev) {
if(ev.layerX || ev.layerX == 0) {//Firefox, IE
ev._x = ev.layerX;
ev._y = ev.layerY;
} else if(ev.offsetX || ev.offsetX == 0) {//Opera
ev._x = ev.offsetX;
ev._y = ev.offsetY;
}
var func = tool[ev.type];
if(func) {
func(ev);
}
}
I'm sure that the problem lies in the latter block of code, but I'm not sure out to fix it. Any help would be appreciated.
I'm working on developing some software in HTML5 which involves the use of canvases. There is one canvas in which I need to be able to zoom and allow the user to doodle on the canvas on mouse clicks. So far, I have gotten the zoom to work, with help from some examples I found. The problem is that after zooming, the mouse position on my drawing tool is out of whack. Before any zooming, I can draw just fine. Here is the code for the zoom:
//Zoom
mainCanvas.onmousewheel = function(event) {
var mousex = event.clientX - mainCanvas.offsetLeft;
var mousey = event.clientY - mainCanvas.offsetTop;
var wheel = event.wheelDelta / 120;
//n or -n
var zoom = 0;
if(wheel < 0) {
zoom = 1 / 2;
if(currentzoom == 1)
return;
} else {
mousex = event.clientX - mainCanvas.offsetLeft;
mousey = event.clientY - mainCanvas.offsetTop;
zoom = 2;
if(currentzoom == 32)
return;
}
currentzoom *= zoom;
mainContext.translate(originx, originy);
mainContext.scale(zoom, zoom);
mainContext.translate(-(mousex / scale + originx - mousex / (scale * zoom ) ), -(mousey / scale + originy - mousey / (scale * zoom ) ));
originx = (mousex / scale + originx - mousex / (scale * zoom ) );
originy = (mousey / scale + originy - mousey / (scale * zoom ) );
scale *= zoom;
draw(mainContext, gridArray);
}
Like I said, the zoom is not the actual problem, just the root of the problem. Here is the code which determines mouse position for the drawing tool:
//this function determines the mouse position relative to the canvas element
function ev_canvas(ev) {
if(ev.layerX || ev.layerX == 0) {//Firefox, IE
ev._x = ev.layerX;
ev._y = ev.layerY;
} else if(ev.offsetX || ev.offsetX == 0) {//Opera
ev._x = ev.offsetX;
ev._y = ev.offsetY;
}
var func = tool[ev.type];
if(func) {
func(ev);
}
}
I'm sure that the problem lies in the latter block of code, but I'm not sure out to fix it. Any help would be appreciated.
Share Improve this question edited Feb 11, 2020 at 19:23 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked May 16, 2012 at 20:34 user1237544user1237544 511 gold badge2 silver badges4 bronze badges 3- 1 I'm no expert in canvases, but I'd say you have to transform your mouse coordinates with essentially the same (maybe some inverse) tranformation you used on the context. Right now, it's probably drawing in the top left corner of the image as a whole when you click in the top left corner, even if you're zoomed in on a different location? – Brendan Commented May 16, 2012 at 20:43
- I do think that the mouse coordinates need to be transformed similarly, and I've been fiddling with it, but I have not yet found any solution for it. As for the zoom, it zooms relative to mouse position(in the direction of mouse position), and where it draws is dependent on where I zoom. I'm zooming on a colored grid which I have drawn, and after zooming, often times the part of the image I am doodling on is not visible on the canvas. Generally, you are right though. The doodle after zoom is usually up and left from actual mouse position. – user1237544 Commented May 17, 2012 at 15:30
- Did you find an answer for this? I have the same problem. – jgarza Commented Apr 30, 2013 at 23:35
4 Answers
Reset to default 0I suspect this is a snippet of code that relies on some global variables like currentzoom
So, if I understand this question right, the problem lies in how you are using the canvas for both mouse control and zooming. I suspect that when you zoom, the DOM is placing the mouse cursor where it belongs on the picture as it was initially rendered. So if you zoom in 200% and place the mouse 100 pixels left of center of the canvas, the canvas will behave as though the mouse was 200 pixels to the left of center.
currentzoom = 1;
originX = 0;
originY = 0;
function ev_canvas(ev) {
if(ev.layerX || ev.layerX == 0) {//Firefox, IE
ev._x = ev.layerX * currentzoom / 1 - originX;
ev._y = ev.layerY * currentzoom / 1 - originY;
} else if(ev.offsetX || ev.offsetX == 0) {//Opera
ev._x = ev.offsetX * currentzoom / 1 - originX;
ev._y = ev.offsetY * currentzoom / 1 - originY;
}
var func = tool[ev.type];
if(func) {
func(ev);
}
}
The / 1
is preserved in case future users want to set a non "1" value to currentzoom
.
For Joomla site you can use Mouse Over Zoom - it's a Joomla Extension that enables you to view bigger versions of the thumbnails from your Joomla webpage. Now you can browse images galleries with ease: just move the mouse cursor over thumbnails to view images in their full size without loading a new page. Download it here http://joomlaboat./mouse-over-zoom
Pictures are automatically resized if they don't fit the window. You can customize the extension there are a lot of additional options. In order to load transparent images, without background just use .png images.
Just try this out:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis./ajax/libs/jquery/1.3.2/jquery.js"></script>
<style>
body {
margin: 0px;
padding: 0px;
}
#wrapper {
position: relative;
border: 1px solid #9C9898;
width: 578px;
height: 200px;
}
#buttonWrapper {
position: absolute;
width: 30px;
top: 2px;
right: 2px;
}
input[type =
"button"] {
padding: 5px;
width: 30px;
margin: 0px 0px 2px 0px;
}
</style>
<script>
function draw(scale, translatePos){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// clear canvas
context.clearRect(0, 0, canvas.width, canvas.height);
context.save();
context.translate(translatePos.x, translatePos.y);
context.scale(scale, scale);
context.beginPath(); // begin custom shape
context.moveTo(-119, -20);
context.bezierCurveTo(-159, 0, -159, 50, -59, 50);
context.bezierCurveTo(-39, 80, 31, 80, 51, 50);
context.bezierCurveTo(131, 50, 131, 20, 101, 0);
context.bezierCurveTo(141, -60, 81, -70, 51, -50);
context.bezierCurveTo(31, -95, -39, -80, -39, -50);
context.bezierCurveTo(-89, -95, -139, -80, -119, -20);
context.closePath(); // plete custom shape
var grd = context.createLinearGradient(-59, -100, 81, 100);
grd.addColorStop(0, "#8ED6FF"); // light blue
grd.addColorStop(1, "#004CB3"); // dark blue
context.fillStyle = grd;
context.fill();
context.lineWidth = 5;
context.strokeStyle = "#0000ff";
context.stroke();
context.restore();
}
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var translatePos = {
x: canvas.width / 2,
y: canvas.height / 2
};
var scale = 1.0;
var scaleMultiplier = 0.8;
var startDragOffset = {};
var mouseDown = false;
// add button event listeners
document.getElementById("plus").addEventListener("click", function(){
scale /= scaleMultiplier;
draw(scale, translatePos);
}, false);
document.getElementById("minus").addEventListener("click", function(){
scale *= scaleMultiplier;
draw(scale, translatePos);
}, false);
// add event listeners to handle screen drag
canvas.addEventListener("mousedown", function(evt){
mouseDown = true;
startDragOffset.x = evt.clientX - translatePos.x;
startDragOffset.y = evt.clientY - translatePos.y;
});
canvas.addEventListener("mouseup", function(evt){
mouseDown = false;
});
canvas.addEventListener("mouseover", function(evt){
mouseDown = false;
});
canvas.addEventListener("mouseout", function(evt){
mouseDown = false;
});
canvas.addEventListener("mousemove", function(evt){
if (mouseDown) {
translatePos.x = evt.clientX - startDragOffset.x;
translatePos.y = evt.clientY - startDragOffset.y;
draw(scale, translatePos);
}
});
draw(scale, translatePos);
};
jQuery(document).ready(function(){
$("#wrapper").mouseover(function(e){
$('#status').html(e.pageX +', '+ e.pageY);
});
})
</script>
</head>
<body onmousedown="return false;">
<div id="wrapper">
<canvas id="myCanvas" width="578" height="200">
</canvas>
<div id="buttonWrapper">
<input type="button" id="plus" value="+"><input type="button" id="minus" value="-">
</div>
</div>
<h2 id="status">
0, 0
</h2>
</body>
</html>
Works perfect for me with mouse movement track.. Njoy!!!
I got a better script to get mouse position on the canvas:
function writeMessage(canvas, message) {
var context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
context.font = '18pt Calibri';
context.fillStyle = 'black';
context.fillText(message, 10, 25);
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect(), root = document.documentElement;
// return relative mouse position
var mouseX = evt.clientX - rect.top - root.scrollTop;
var mouseY = evt.clientY - rect.left - root.scrollLeft;
return {
x: mouseX,
y: mouseY
};
}
window.onload = function() {
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
canvas.addEventListener('mousemove', function(evt) {
var mousePos = getMousePos(canvas, evt);
var message = "Mouse position: " + mousePos.x + "," + mousePos.y;
writeMessage(canvas, message);
}, false);
};
Try it out, ment if any issues..