I’m trying to scale canvas to/from mouse position, but it works not perfect (always goes few cells away from mouse pos). I’ve read all similar posts but i don’t know what’s wrong.
https://jsfiddle.net/shumikua/3afxtmqw/
All code is only to run snippet, it works good. Problem is in function scale.
JavaScript
x
12
12
1
function scale(svg, e){
2
let x = e.originalEvent.offsetX - canvas[0].offsetLeft;
3
let y = e.originalEvent.offsetY - canvas[0].offsetTop;
4
let deltaY = e.originalEvent.deltaY;
5
let scale_now = deltaY < 0 ? 1.5 : 1/1.5;
6
scaleFactor *= scale_now;
7
panX = x - (x - panX)*scale_now;
8
panY = y - (y - panY)*scale_now;
9
10
draw();
11
}
12
Advertisement
Answer
In function scale()
keep the same values for x
and y
before and after scaling. You just need to update coordinates in screen panX
and panY
.
JavaScript
1
93
93
1
var canvas;
2
var ctx;
3
var ww;
4
var wh;
5
var scaleFactor;
6
var panX;
7
var panY;
8
9
function draw() {
10
ctx.clearRect(0, 0, ww, wh);
11
let size = Math.min((ww - 10) / 60, (wh - 10) / 60);
12
let padding = {
13
x: ww - size * 60,
14
y: wh - size * 60,
15
}
16
ctx.save();
17
ctx.translate(panX, panY);
18
ctx.scale(scaleFactor, scaleFactor);
19
for (let i = 0; i < 60; i++) {
20
for (let j = 0; j < 60; j++) {
21
ctx.fillStyle = '#f' + i + j + 'f';
22
ctx.fillRect(padding.x / 2 + size * j, padding.y / 2 + size * i, size, size);
23
}
24
}
25
ctx.restore();
26
}
27
28
function scale(svg, e) {
29
let x = e.originalEvent.offsetX;
30
let y = e.originalEvent.offsetY;
31
let deltaY = e.originalEvent.deltaY;
32
let scale_now = deltaY < 0 ? 1.5 : 1 / 1.5;
33
scaleFactor *= scale_now;
34
panX = x - (x - panX) * scale_now;
35
panY = y - (y - panY) * scale_now;
36
draw();
37
}
38
39
function move(svg, x, y) {
40
panX += x;
41
panY += y;
42
draw();
43
}
44
45
function initialise() {
46
ctx = canvas.get(0).getContext('2d');
47
ww = canvas.outerWidth();
48
wh = canvas.outerHeight();
49
canvas.attr('width', ww);
50
canvas.attr('height', wh);
51
scaleFactor = 1.0;
52
panX = 0;
53
panY = 0;
54
draw();
55
}
56
$(document).ready(function() {
57
canvas = $('.canva');
58
initialise();
59
canvas.bind('mousewheel DOMMouseScroll', function(e) {
60
e.preventDefault();
61
});
62
canvas.on('mousewheel DOMMouseScroll', function(e) {
63
if (e.ctrlKey) {
64
scale($(this), e);
65
} else if (e.shiftKey) {
66
move($(this), -e.originalEvent.deltaY / 5, 0);
67
} else {
68
move($(this), 0, -e.originalEvent.deltaY / 5);
69
}
70
});
71
canvas.mousedown(function(e) {
72
if (e.which !== 2) return;
73
e.preventDefault();
74
$(this).css('cursor', 'move');
75
let old_x = e.offsetX;
76
let old_y = e.offsetY;
77
$(this).mousemove(function(emove) {
78
let x = emove.offsetX;
79
let y = emove.offsetY;
80
move($(this), emove.offsetX - old_x, emove.offsetY - old_y);
81
old_x = x;
82
old_y = y;
83
});
84
$(this).mouseup(function() {
85
$(this).off('mousemove');
86
$(this).css('cursor', 'default');
87
});
88
$(this).mouseleave(function() {
89
$(this).off('mousemove');
90
$(this).css('cursor', 'default');
91
});
92
});
93
});
JavaScript
1
15
15
1
canvas {
2
image-rendering: optimizeSpeed;
3
/* Older versions of FF */
4
image-rendering: -moz-crisp-edges;
5
/* FF 6.0+ */
6
image-rendering: -webkit-optimize-contrast;
7
/* Safari */
8
image-rendering: -o-crisp-edges;
9
/* OS X & Windows Opera (12.02+) */
10
image-rendering: pixelated;
11
/* Awesome future-browsers */
12
-ms-interpolation-mode: nearest-neighbor;
13
shape-rendering: crispEdges;
14
border: 1px solid black;
15
}
JavaScript
1
2
1
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
2
<canvas id="canvas" class="canva" width="200" height="200"></canvas>
Hold Ctrl and scroll wheel to scale.