我正在编写一个 HTML5 <canvas > 项目,该项目涉及使用滚轮放大和缩小图像。我想像谷歌地图一样放大光标,但我完全不知道如何计算运动。
我所拥有的:图像 x 和 y(左上角);图像宽度和高度;相对于画布中心的光标 x 和 y。
我正在编写一个 HTML5 <canvas > 项目,该项目涉及使用滚轮放大和缩小图像。我想像谷歌地图一样放大光标,但我完全不知道如何计算运动。
我所拥有的:图像 x 和 y(左上角);图像宽度和高度;相对于画布中心的光标 x 和 y。
简而言之,您希望translate()
通过偏移scale()
来放大或缩小画布上下文,然后translate()
通过鼠标偏移的相反位置返回。请注意,您需要将光标位置从屏幕空间转换为转换后的画布上下文。
ctx.translate(pt.x,pt.y);
ctx.scale(factor,factor);
ctx.translate(-pt.x,-pt.y);
我在我的网站上提供了一个完整的工作示例供您检查、支持拖动、单击放大、按住 shift 单击缩小或向上/向下滚动滚轮。
唯一的(当前)问题是与 Chrome 或 Firefox 相比,Safari 的缩放速度太快。
我希望,这些 JS 库会帮助你:(HTML5, JS)
http://www.netzgesta.de/loupe/
https://github.com/akademy/CanvasZoom
https://github.com/zynga/scroller
至于我,我正在使用放大镜。这很棒!对你来说最好的情况 - 滚动条。
我最近需要归档与 Phrogz 已经完成的相同的结果,但context.scale()
我没有使用,而是根据比率计算每个对象的大小。
这就是我想出的。其背后的逻辑非常简单。在缩放之前,我以百分比计算与边缘的点距离,然后将视口调整到正确的位置。
我花了很长时间才想出它,希望它可以节省某人的时间。
我以@Phrogz 的回答为基础,制作了一个小型库,使画布能够拖动、缩放和旋转。这是示例。
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
您可以在项目页面上找到更详细的示例和文档
使用ctx.setTransform
为您提供了比多个矩阵调用更多的性能ctx.translate
,ctx.scale
,ctx.translate
。
不需要复杂的转换反转,因为昂贵的 DOM 矩阵调用 tp 在缩放和屏幕坐标系之间转换点。
灵活性,因为您不需要使用,ctx.save
并且ctx.restore
如果您使用不同的转换来渲染内容。返回到转换ctx.setTransform
而不是潜在的帧率ctx.restore
调用
易于反转变换并获得(屏幕)像素位置的世界坐标,反之亦然。
使用鼠标和鼠标滚轮在鼠标位置放大和缩小
使用此方法通过 CSS 转换在答案底部的 CSS 演示点(鼠标)缩放页面内容的示例也有下一个示例中演示的副本。
以及使用 setTransform 在某个点缩放画布内容的此方法的示例
给定比例和像素位置,您可以按如下方式获得新比例...
const origin = {x:0, y:0}; // canvas origin
var scale = 1; // current scale
function scaleAt(x, y, scaleBy) { // at pixel coords x, y scale by scaleBy
scale *= scaleBy;
origin.x = x - (x - origin.x) * scaleBy;
origin.y = y - (y - origin.y) * scaleBy;
}
定位画布并绘制内容
ctx.setTransform(scale, 0, 0, scale, origin.x, origin.y);
ctx.drawImage(img, 0, 0);
如果您有鼠标坐标,则使用
const zoomBy = 1.1; // zoom in amount
scaleAt(mouse.x, mouse.y, zoomBy); // will zoom in at mouse x, y
scaleAt(mouse.x, mouse.y, 1 / zoomBy); // will zoom out by same amount at mouse x,y
恢复默认转换
ctx.setTransform(1,0,0,1,0,0);
获取缩放坐标系中某个点的坐标和缩放坐标系中某个点的屏幕位置
屏幕到世界
function toWorld(x, y) { // convert to world coordinates
x = (x - origin.x) / scale;
y = (y - origin.y) / scale;
return {x, y};
}
屏幕上的世界
function toScreen(x, y) {
x = x * scale + origin.x;
y = y * scale + origin.y;
return {x, y};
}