Ich programmiere ein HTML5-<Leinwand> -Projekt, bei dem Bilder mit dem Scrollrad vergrößert und verkleinert werden. Ich möchte wie bei Google Maps auf den Cursor zoomen, bin aber völlig verloren, wie man die Bewegungen berechnet.
Was ich habe: Bild x und y (obere linke Ecke); Bildbreite und -höhe; Cursor x und y relativ zur Mitte der Leinwand.
Antworten:
Kurz gesagt, Sie möchten
translate()
den Canvas-Kontext anhand Ihres Versatzesscale()
vergrößern oder verkleinern und danntranslate()
um das Gegenteil des Mausversatzes zurück. Beachten Sie, dass Sie die Cursorposition vom Bildschirmbereich in den transformierten Canvas-Kontext umwandeln müssen.Demo: http://phrogz.net/tmp/canvas_zoom_to_cursor.html
Ich habe auf meiner Website ein voll funktionsfähiges Beispiel erstellt, das Sie untersuchen können, indem Sie das Ziehen unterstützen, zum Vergrößern klicken, bei gedrückter Umschalttaste nach außen klicken oder das Rad nach oben / unten scrollen.
Das einzige (aktuelle) Problem ist, dass Safari im Vergleich zu Chrome oder Firefox zu schnell zoomt .
quelle
Ich hoffe, diese JS-Bibliotheken helfen Ihnen: (HTML5, JS)
http://www.netzgesta.de/loupe/
https://github.com/akademy/CanvasZoom
https://github.com/zynga/scroller
Ich benutze Lupe. Es ist toll! Für Sie der beste Fall - Scroller.
quelle
Ich musste kürzlich dieselben Ergebnisse archivieren, die Phrogz bereits erstellt hatte, aber anstatt sie zu verwenden
context.scale()
, berechnete ich jede Objektgröße basierend auf dem Verhältnis.Das habe ich mir ausgedacht. Die Logik dahinter ist sehr einfach. Vor dem Skalieren berechne ich den Punktabstand von der Kante in Prozent und passe das Ansichtsfenster später an die richtige Stelle an.
Ich habe eine ganze Weile gebraucht, um darauf zu kommen, hoffe, es spart jemandem Zeit.
Code-Snippet anzeigen
$(function () { var canvas = $('canvas.main').get(0) var canvasContext = canvas.getContext('2d') var ratio = 1 var vpx = 0 var vpy = 0 var vpw = window.innerWidth var vph = window.innerHeight var orig_width = 4000 var orig_height = 4000 var width = 4000 var height = 4000 $(window).on('resize', function () { $(canvas).prop({ width: window.innerWidth, height: window.innerHeight, }) }).trigger('resize') $(canvas).on('wheel', function (ev) { ev.preventDefault() // for stackoverflow var step if (ev.originalEvent.wheelDelta) { step = (ev.originalEvent.wheelDelta > 0) ? 0.05 : -0.05 } if (ev.originalEvent.deltaY) { step = (ev.originalEvent.deltaY > 0) ? 0.05 : -0.05 } if (!step) return false // yea.. var new_ratio = ratio + step var min_ratio = Math.max(vpw / orig_width, vph / orig_height) var max_ratio = 3.0 if (new_ratio < min_ratio) { new_ratio = min_ratio } if (new_ratio > max_ratio) { new_ratio = max_ratio } // zoom center point var targetX = ev.originalEvent.clientX || (vpw / 2) var targetY = ev.originalEvent.clientY || (vph / 2) // percentages from side var pX = ((vpx * -1) + targetX) * 100 / width var pY = ((vpy * -1) + targetY) * 100 / height // update ratio and dimentsions ratio = new_ratio width = orig_width * new_ratio height = orig_height * new_ratio // translate view back to center point var x = ((width * pX / 100) - targetX) var y = ((height * pY / 100) - targetY) // don't let viewport go over edges if (x < 0) { x = 0 } if (x + vpw > width) { x = width - vpw } if (y < 0) { y = 0 } if (y + vph > height) { y = height - vph } vpx = x * -1 vpy = y * -1 }) var is_down, is_drag, last_drag $(canvas).on('mousedown', function (ev) { is_down = true is_drag = false last_drag = { x: ev.clientX, y: ev.clientY } }) $(canvas).on('mousemove', function (ev) { is_drag = true if (is_down) { var x = vpx - (last_drag.x - ev.clientX) var y = vpy - (last_drag.y - ev.clientY) if (x <= 0 && vpw < x + width) { vpx = x } if (y <= 0 && vph < y + height) { vpy = y } last_drag = { x: ev.clientX, y: ev.clientY } } }) $(canvas).on('mouseup', function (ev) { is_down = false last_drag = null var was_click = !is_drag is_drag = false if (was_click) { } }) $(canvas).css({ position: 'absolute', top: 0, left: 0 }).appendTo(document.body) function animate () { window.requestAnimationFrame(animate) canvasContext.clearRect(0, 0, canvas.width, canvas.height) canvasContext.lineWidth = 1 canvasContext.strokeStyle = '#ccc' var step = 100 * ratio for (var x = vpx; x < width + vpx; x += step) { canvasContext.beginPath() canvasContext.moveTo(x, vpy) canvasContext.lineTo(x, vpy + height) canvasContext.stroke() } for (var y = vpy; y < height + vpy; y += step) { canvasContext.beginPath() canvasContext.moveTo(vpx, y) canvasContext.lineTo(vpx + width, y) canvasContext.stroke() } canvasContext.strokeRect(vpx, vpy, width, height) canvasContext.beginPath() canvasContext.moveTo(vpx, vpy) canvasContext.lineTo(vpx + width, vpy + height) canvasContext.stroke() canvasContext.beginPath() canvasContext.moveTo(vpx + width, vpy) canvasContext.lineTo(vpx, vpy + height) canvasContext.stroke() canvasContext.restore() } animate() })
<!DOCTYPE html> <html> <head> <title></title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> </head> <body> <canvas class="main"></canvas> </body> </html>
quelle
Ich habe die Antwort von @ Phrogz als Grundlage genommen und eine kleine Bibliothek erstellt, die das Ziehen, Zoomen und Drehen von Leinwand ermöglicht. Hier ist das Beispiel.
var canvas = document.getElementById('canvas') //assuming that @param draw is a function where you do your main drawing. var control = new CanvasManipulation(canvas, draw) control.init() control.layout() //now you can drag, zoom and rotate in canvas
Sie können mehr detaillierten Beispiele und Dokumentation des Projektes finden Seite
quelle