Как мне эффективно рассчитать масштаб увеличения? - PullRequest
4 голосов
/ 26 октября 2010

У меня есть перетаскиваемое изображение внутри коробки. Вы можете увеличивать и уменьшать изображение в окне, которое будет увеличивать или уменьшать изображение, но размер окна остается тем же. Высота и ширина окна будут меняться по мере изменения размера браузера. Верхнее и левое значения изображения будут изменяться при его перетаскивании.

Я пытаюсь сохранить в центре точку, на которой была центрирована коробка на изображении. Вроде как работает зум на Google Картах или зум на Mac OS X увеличивает.

То, что я сейчас делаю, - это вычисление центра поля (x = w / 2, y = h / 2), а затем использование верхнего и левого значений для изображения для расчета положения изображения в центр коробки. (x - = слева, y - = сверху).

Затем я масштабирую изображение, увеличивая или уменьшая его, и использую изменение масштаба для регулировки координат (x = (x * (old_width / new_width), y = (y * (old_height / new_height)).

Затем я переставляю изображение так, чтобы его центр был таким, каким он был до масштабирования, захватывая координаты, в которых он в данный момент центрирован (что изменилось при изменении размера) и добавляя разницу между старыми значениями центра и новыми значениями в верх и оставленные значения (new_left = post_zoom_left + (old_center_x - new_center_x), new_top = post_zoom_top + (old_center_y - new_center_y).

Это работает нормально для увеличения, но уменьшение, кажется, немного отключено.

Есть предложения?

Мой код ниже:

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";
};

1 Ответ

8 голосов
/ 26 октября 2010

[ Рабочая демонстрация ]

Данные

  • Изменить размер по: R
  • Размер холста: Cw, Ch
  • Размер изображения изменен: Iw, Ih
  • Положение измененного изображения: Ix, Iy
  • Положение клика на холсте: Pcx, Pcy
  • Нажмите на исходное изображение: Pox, Poy
  • Положение клика на измененном изображении: Prx, Pry

Метод

  1. Щелкните положение события на холсте -> положение на изображении: Pox = Pcx - Ix, Poy = Pcy - Iy
  2. Положение на изображении -> Поз. На изображении с измененным размером: Prx = Pox * R, Pry = Poy * R
  3. top = (Ch / 2) - Pry, left = (Cw / 2) - Prx
  4. ctx.drawImage(img, left, top, img.width, img.height)

Осуществление

// 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);

Это общая формула, которая работает для увеличения или уменьшения масштаба и может обрабатывать любую точку в качестве нового центра. Чтобы сделать это специфичным к вашей проблеме:

  • Pcx = Cw / 2, Pcy = Ch / 2 (всегда используйте центр)
  • R < 1 для уменьшения и R > 1 для увеличения
...