How to effectively calculate the scale of the scale?

I have a reversible image contained in a field. You can enlarge and reduce the image in the window, which will make the image larger or smaller, but the box size remains unchanged. The height and width of the window will change as the browser resizes. The top and left values ​​for the image will change as they move.

I am trying to keep what the drawer was focused on in the image, in the center. How you like zooming in on Google Maps or zooming in on Mac OS X.

What I'm doing right now is calculating the center of the window (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 - = left, y - = top).

Then I enlarge the image by zooming in or out, and I use zooming to adjust the coordinates (x = (x * (old_width / new_width), y = (y * (old_height / new_height)).

Then I move the image so that its center is what it was before scaling, capturing the coordinates in which it is currently centered (resized), and adding the difference between the old center values ​​and the new values ​​up 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).

This works fine for zooming, but zooming out seems a bit 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"; }; 
+4
source share
1 answer

[ Working demo ]

Data

  • Resize: R
  • Canvas Size: Cw , Ch
  • Resized Image: Iw , Ih
  • Changed image position: Ix , Iy
  • Click on canvas: Pcx , Pcy
  • Select a position on the original image: Pox , Poy
  • Select a position by image size: Prx , Pry

Method

  • Click the event position on the canvas β†’ position on the image: Pox = Pcx - Ix , Poy = Pcy - Iy
  • Image Position β†’ Pos for Modified Image: Prx = Pox * R , Pry = Poy * R
  • top = (Ch / 2) - Pry , left = (Cw / 2) - Prx
  • ctx.drawImage(img, left, top, img.width, img.height)

Implementation

 // resize image Iw *= R; Ih *= 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 = (Cw / 2) - Pr.x; I.top = (Ch / 2) - Pr.y; // draw image ctx.drawImage(img, I.left, I.top, Iw, Ih); 

This is a general formula that works to zoom in or out and can process any point as a new center. To make it specific to your problem:

  • Pcx = Cw / 2 , Pcy = Ch / 2 (always use the center)
  • R < 1 for scaling and R > 1 for scaling
+8
source

All Articles