Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/423.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在映射应用程序中实现稳定的缩放_Javascript_Canvas - Fatal编程技术网

Javascript 如何在映射应用程序中实现稳定的缩放

Javascript 如何在映射应用程序中实现稳定的缩放,javascript,canvas,Javascript,Canvas,我正在实现一个具有点击、拖动和缩放功能的应用程序,它类似于谷歌地图。我已经成功地实现了平移和缩放,但是,缩放点当前位于坐标0,0。放大和缩小时,坐标0,0处栅格的位置保持不变,而所有其他坐标都会从该点放大/缩小 相反,我希望能够实现稳定的缩放,其中缩放点是当前鼠标位置下的位置。要了解我在寻找什么,请打开谷歌地图,将鼠标放在特定点上方,然后使用鼠标滚轮滚动。注意鼠标下的位置是如何保持固定的 如何修改本例中的zoomGrid函数,以实现鼠标滚轮缩放,从而尊重鼠标的位置 function zoomGr

我正在实现一个具有点击、拖动和缩放功能的应用程序,它类似于谷歌地图。我已经成功地实现了平移和缩放,但是,缩放点当前位于坐标
0,0
。放大和缩小时,坐标
0,0
处栅格的位置保持不变,而所有其他坐标都会从该点放大/缩小

相反,我希望能够实现稳定的缩放,其中缩放点是当前鼠标位置下的位置。要了解我在寻找什么,请打开谷歌地图,将鼠标放在特定点上方,然后使用鼠标滚轮滚动。注意鼠标下的位置是如何保持固定的

如何修改本例中的
zoomGrid
函数,以实现鼠标滚轮缩放,从而尊重鼠标的位置

function zoomGrid(mouseEvent) {
  var delta = mouseEvent.deltaY;
  if (mouseEvent.deltaMode == 1) { //Firefox scrolls by line instead of by pixel so multiply the delta by 20
    delta *= 20;
  }
  zoom += delta;
  zoom = Math.min(zoom, 3000);
  zoom = Math.max(zoom, -1000);
  scale = Math.pow(2,(zoom / 1000));

  var mousePos = {x: mouseEvent.offsetX, y: mouseEvent.offsetY};
  //gridPos = ???

  drawGrid();
  drawShapes();
}
完整演示:


(PS,我已经看到了,但是不能把逻辑转换成可执行代码)。

< P>也许你应该考虑使用库来处理它?< /P>
非常不可知,因此您应该能够将其与应用程序集成。

以下是一些实现您所需功能的代码

这个答案有点过分了,但我的时间有点短,不能删掉不需要的东西

该演示允许您缩放、平移和旋转。它首先加载一个映像(大小合理,因此具有低GPU RAM的设备可能不喜欢它,并且运行缓慢)

一旦汽车图像加载

  • 左键拖动以平移
  • 用于放大和缩小的控制盘
  • “向下”上的右键设置旋转原点,然后向外拖动以旋转
  • 中键将重置视图
使用“仅在绝对坐标下渲染”。如果数据集很大,则在剔除渲染调用时,可以使用“显示变换角点”作为世界坐标视图边界

重要的功能位于顶部

  • display
    在一帧中调用一次,并处理所有渲染
  • displayTransform
    是负责平移、缩放和旋转的对象。它有一些评论,但没有解释,所以如果您遇到问题,请随时提问
  • 取消公告调整大小事件时调用
    onResize
  • startup
    在启动时调用一次,并设置displayTransform
  • 底部的样板代码处理鼠标和画布,可以忽略
鼠标
是保存鼠标状态的全局对象。
mouse.x
mouse.y
是画布坐标
mouse.buttonRaw
是位字段,如果按下按钮,则位打开。见下一段
mouse.w
是滚轮-120、0或120

displayTransform.mouseWorldX
displayTransform.mouseWorldY
保留鼠标在图像上的位置(因为这与画布坐标不匹配);
displayTransform.corners
是一个长度为8的数组,画布角的坐标为[x1,y1,…,x4,y4],从左上角沿顺时针方向投影到世界(图像)坐标上。您可以使用它们在视图外部绘制栅格和剔除渲染调用

我没有添加任何鼠标按钮常量,因此当您看到与鼠标按钮有关的任何内容时,0是左1是中2是右ID。当检查鼠标时,请单击
鼠标。buttonRaw
是一个位字段,左1位,中2位,右3位。只屏蔽您感兴趣的鼠标按钮。按钮aw&1
位于左侧
&2
中间
&4`右侧

var startup=function(){
displayTransform.ctx=ctx;
displayTransform.mouse=鼠标;
displayTransform.setMouseRotate(2);//将旋转功能设置为按钮3
displayTransform.setMouseTranslate(0);
displayTransform.setWheelZoom();
img=新图像();
img.src=”https://upload.wikimedia.org/wikipedia/commons/e/e5/Fiat_500_in_Emilia-Romagna.jpg"
}
var-img;
var onResize=function(){
ctx.font=“14px verdana”;
ctx.textAlign=“中心”;
ctx.textb基线=“中间”;
如果(图像完成){
displayTransform.fitView(0,0,img.宽度,img.高度,“适合”);
}
}
var-stillTime=0;
常数鼠标时间=1000;
函数显示(){
displayTransform.update();//更新转换
displayTransform.setDefault();//设置主转换以清除screem
clearRect(0,0,canvas.width,canvas.height);
//如果加载的图像显示它
如果(图像完成){
if(displayTransform.quiet | | |(mouse.buttonRaw&2)){
静止时间+=1;
if(stillTime>MOUSE|u STILL|u TIME |(MOUSE.buttonRaw&2)){
静止时间=0;
displayTransform.fitView(0,0,图像宽度,图像高度,“适合”)
}
}否则{
静止时间=0;
}
displayTransform.setTransform();
ctx.drawImage(img,0,0);
}否则{
//正在等待加载映像
displayTransform.setTransform();
ctx.fillText(“加载图像…”,100100);
}
}
var displayTransform=(函数(){
常量按钮=[1,2,4];
//创建位置描述。
//x和y是的位置(在画布上变换的点0,0将结束)
//原点x,y是缩放和旋转的中心位置。
//比例是指比例(缩放)大的数字放大小的数字缩小。1是1像素=1像素
//旋转是旋转。0 id从左到右穿过屏幕,带有正值旋转
//顺时针方向。值以弧度为单位
变量位置=函数(x,y,originX,originY,scale,rotation){
返回{
x:x,
y:y,
牛:原版,
oy:原创,
比例:比例,
旋转:旋转,
};
}
//返回用于保存转换的数组
var mousePos = {x: mouseEvent.offsetX, y: mouseEvent.offsetY};
var mouseGridPos = plus(multiply(mousePos, scale), gridPos);
var delta = mouseEvent.deltaY;
if (mouseEvent.deltaMode == 1) { //Firefox scrolls by line instead of by pixel so multiply the delta by 20
  delta *= 20;
}
zoom += delta;
zoom = Math.min(zoom, 3000);
zoom = Math.max(zoom, -1000);
scale = Math.pow(2,(zoom / 1000));
//Calculate the grid position by using the previous scaled
//mouse position and the new scale
gridPos = minus(mouseGridPos, multiply(mousePos, scale));