2D Масштабирование и перемещение
Здравствуйте!
У меня задача сделать масштабирование при помощи колесика мыши на холсте SVG. Причем масштабирование делается через точку, которая в момент действия находится под курсором мыши. Ну, аналогично как это сделано в векторных редакторах. Проблема в том, что работает это, но плохо. Сначала нормально, а потом точка масштабирования не совпадает с точкой курсора мыши. Вот код:
// Единичная матрица
var matrixPrevious = Ext.create("Ext.draw.Matrix", 1, 0, 0, 1, 0, 0);
me.getEl().on("mousewheel", function(e) {
// Здесь по событию от колесика мыши выбирается коэффициент масштабирования
var scale = e.event.wheelDelta > 0 ? 1.2 : 0.8;
// Создаю матрицу масштабирования
var matrixScale = Ext.create("Ext.draw.Matrix", scale, 0, 0, scale, 0, 0);
// Вычисляю координаты курсора мыши относительно холста SVG
x = e.pageX - me.getX();
y = e.pageY - me.getY();
// Вычисляю смещение относительно мыши и необходимого положения масштабируемого изображения
var offsetX = x * (1 - scale);
var offsetY = y * (1 - scale);
// Создаю матрицу перемещения
var matrixTranslate = Ext.create("Ext.draw.Matrix", 1, 0, 0, 1, offsetX, offsetY);
// Беру предыдущую матрицу
var matrixResult = matrixPrevious;
// Все матрицы соединяю умножением
matrixResult.multiply(matrixTranslate);
matrixResult.multiply(matrixScale);
// Применяю матрицу к элементу SVG-холста
me.getSurface().matrix(matrixResult);
// Сохраняю матрицу как предыдущую, чтобы в следующей итерации ее использовать
// для относительных трансформаций
matrixPrevious = matrixResult;
});
У меня есть подозрения, что масштабирования я сделал относительное, а вот перемещение похоже не совсем относительное. Но как это исправить пока не знаю. |
Может лучше использовать snap.svg для этой цели?
http://jsfiddle.net/AGq9X/5/ http://snapsvg.io/docs/#Matrix.scale |
Но это ведь не отменяет создание матрицы?
|
Что-то непонятно, что здесь происходит.
// Вычисляю координаты курсора мыши относительно холста SVG
/*
Вот здесь получаются реальные (экранные) пиксели. А дальше я не вижу,
чтобы ты их переводил в свои сабпиксели (то есть, ты не учитываешь уже
существующее масштабирование)
*/
x = e.pageX - me.getX();
y = e.pageY - me.getY();
/*
Вот где-то здесь тебе надо бы x и у умножить на текущий scale
*/
// Вычисляю смещение относительно мыши и необходимого положения масштабируемого изображения
var offsetX = x - x * scale;
var offsetY = y - y * scale;
|
А как их переводить? У меня когда изначально масштаб 1:1 стоит, то пиксель изображения равен пикселу экрана. А вот когда накладывается transform, то уже они меняются.
Вот куда текущий scale приложить так и не понял. |
Я взял формулу отсюда http://xiper.net/learn/svg/svg-essen...a-center-point
но там расписано как смасштабировать один раз. А что делать, когда надо потом (колесико мыши крутится же дальше) еще раз смасштабировать? Я думал что нужно просто умножать новую матрицу на существующую. |
khusamov, если вы в точности придерживаетесь того, что там описываете, то для масштабирования при прокрутке вам нужно завести отдельную переменную для scale, в которой хранится текущее значение масштабирования. При прокрутке колесика вы:
1) прибавляете к текущему значению scale deltaWheel (scale += deltaWheel) 2) масштабируете оригинальное изображение с текущим (только что записанным) значением scale |
У меня для этой цели заведена специальная матрица. Она сначала пустая (нули для смещений, и 1-ки для масштаба). А потом приращения масштаба туда записываются.
var matrixPrevious = Ext.create("Ext.draw.Matrix", 1, 0, 0, 1, 0, 0);
|
khusamov, дайте пример? Где-нить здесь.
http://jsfiddle.net/ |
Я готовлю пример. Там у меня куча моих классов. Надо как-то их все разместить.
|
| Часовой пояс GMT +3, время: 21:56. |