简体   繁体   English

如何有效地计算缩放比例?

[英]How do I effectively calculate zoom scale?

I have a draggeable image contained within a box. 我有一个可拖动的图像包含在一个盒子里。 You can zoom in and zoom out on the image in the box which will make the image larger or smaller but the box size remains the same. 您可以放大和缩小框中的图像,这将使图像变大或变小,但框大小保持不变。 The box's height and width will vary as the browser is resized. 随着浏览器调整大小,框的高度和宽度会有所不同。 The top and left values for the image will change as it is dragged around. 图像的顶部和左侧值会随着拖动而改变。

I'm trying to keep whatever the point the box was centered on in the image, in the center. 我试图保持盒子在图像中心的中心位置。 Kind of like how zoom on Google Maps works or the zoom on Mac OS X zooms. 有点像放大谷歌地图的工作原理或放大Mac OS X缩放。

What I'm doing right now is calculating the center of the box (x = w/2, y = h/2) and then using the top and left values for the image to calculate the position of the image in the center of the box. 我现在正在做的是计算框的中心(x = w / 2,y = h / 2),然后使用图像的顶部和左侧值来计算图像在中心的位置。框。 (x -= left, y -= top). (x - = left,y - = top)。

Then I zoom the image by growing or shrinking it and I use the scale change to adjust the coordinates (x = (x * (old_width/new_width), y = (y * (old_height/new_height)). 然后我通过增大或缩小图像来缩放图像,我使用比例变化来调整坐标(x =(x *(old_width / new_width),y =(y *(old_height / new_height))。

I then reposition the image so that its center is what it was before zoom by grabbing the coordinates it is currently centered on (that changed with the resize) and adding the difference between the old center values and the new values to the top and left values (new_left = post_zoom_left + (old_center_x - new_center_x), new_top = post_zoom_top + (old_center_y - new_center_y). 然后我重新定位图像,使其中心在缩放之前通过抓取当前居中的坐标(通过调整大小而改变)并将旧中心值和新值之间的差值添加到顶部和左侧值(new_left = post_zoom_left +(old_center_x - new_center_x),new_top = post_zoom_top +(old_center_y - new_center_y)。

This works ok for zoom in, but zoom out seems to be somewhat off. 这适用于放大,但缩小似乎有点偏。

Any suggestions? 有什么建议么?

My code is below: 我的代码如下:

app.Puzzle_Viewer.prototype.set_view_dimensions = function () {

  var width, height, new_width, new_height, coordinates, x_scale,
    y_scale;

  coordinates = this.get_center_position();
  width = +this.container.width();
  height = +this.container.height();
  //code to figure out new width and height
  //snip ...
  x_scale = width/new_width;
  y_scale = height/new_height;
  coordinates.x = Math.round(coordinates.x * x_scale);
  coordinates.y = Math.round(coordinates.y * y_scale);
  //resize image to new_width & new_height
  this.center_on_position(coordinates);
};

app.Puzzle_Viewer.prototype.get_center_position = function () {

  var top, left, bottom, right, x, y, container;

  right = +this.node.width();
  bottom = +this.node.height();
  x = Math.round(right/2);
  y = Math.round(bottom/2);
  container = this.container.get(0);
  left = container.style.left;
  top = container.style.top;
  left = left ? parseInt(left, 10) : 0;
  top  = top ? parseInt(top, 10) : 0;
  x -= left;
  y -= top;
  return {x: x, y: y, left: left, top: top};
};

app.Puzzle_Viewer.prototype.center_on_position = function (coordinates) {

  var current_center, x, y, container;

  current_center = this.get_center_position();
  x = current_center.left + coordinates.x - current_center.x;
  y = current_center.top + coordinates.y - current_center.y;
  container = this.container.get(0);
  container.style.left = x + "px";
  container.style.top = y + "px";
};

[ Working demo ] [ 工作演示 ]

Data 数据

  • Resize by: R 调整大小: R
  • Canvas size: Cw , Ch 帆布尺寸: CwCh
  • Resized image size: Iw , Ih 调整后的图像尺寸: IwIh
  • Resized image position: Ix , Iy 调整后的图像位置: IxIy
  • Click position on canvas: Pcx , Pcy 单击画布上的位置: PcxPcy
  • Click position on original image: Pox , Poy 点击原始图片上的位置: PoxPoy
  • Click position on resized image: Prx , Pry 单击调整大小后的图像上的位置: PrxPry

Method 方法

  1. Click event position on canvas -> position on image: Pox = Pcx - Ix , Poy = Pcy - Iy 单击画布上的事件位置 - >图像上的位置: Pox = Pcx - IxPoy = Pcy - Iy
  2. Position on image -> Pos on resized image: Prx = Pox * R , Pry = Poy * R 图像上的位置 - >调整大小后的图像上的位置: Prx = Pox * RPry = Poy * R
  3. top = (Ch / 2) - Pry , left = (Cw / 2) - Prx top = (Ch / 2) - Pryleft = (Cw / 2) - Prx
  4. ctx.drawImage(img, left, top, img.width, img.height)

Implementation 履行

// resize image
I.w *= R;
I.h *= R;

// canvas pos -> image pos
Po.x = Pc.x - I.left;
Po.y = Pc.y - I.top;

// old img pos -> resized img pos
Pr.x = Po.x * R;
Pr.y = Po.y * R;

// center the point
I.left = (C.w / 2) - Pr.x;
I.top  = (C.h / 2) - Pr.y;

// draw image
ctx.drawImage(img, I.left, I.top, I.w, I.h);

This is a general formula that works for zooming in or out, and can handle any point as the new center. 这是一个适用于放大或缩小的通用公式,可以处理任何点作为新中心。 To make it specific to your problem: 要使其特定于您的问题:

  • Pcx = Cw / 2 , Pcy = Ch / 2 (alway use the center) Pcx = Cw / 2Pcy = Ch / 2Pcy = Ch / 2使用中心)
  • R < 1 for zooming out, and R > 1 for zooming in R < 1表示缩小, R > 1表示放大

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM