Ограниченное панорамирование / масштабирование с использованием ViewMatrix - PullRequest
3 голосов
/ 31 августа 2010

Я пытаюсь добавить ограничивающие границы в поведение масштабирования и панорамирования, которое я реализовал для Unveil.js (http://github.com/michael/unveil). При включенных границах вы не сможете перемещаться за пределы границ сцены и уровня масштабирования (= шкала) никогда не должна становиться ниже 1,0. В результате вы вообще не сможете выполнять панорамирование, если вы находитесь на уровне увеличения 1,0.

Вы можете увидеть неограниченное поведение на примере стеков: dejavis.org/stacks. Используйте колесико мыши для увеличения. Вы можете стереть блоки с экрана или бесконечно уменьшить их, чего следует избегать.

Действительно сложная проблема заключается в том, что масштабирование относительно указателя мыши также приводит к смещению области просмотра. Таким образом, проверка границ во время панорамирования не достаточно. Я должен был бы найти умный способ увеличить масштаб до 100% при использовании Mouswheel (без грязных прыжков). Похоже, что Photoshop решил эту проблему при увеличении изображения.

Я абсолютно не представляю, как мне это решить. Очень расстраивает. : /

Я использую матрицу для хранения текущего преобразования View, которым манипулируют неоднократно. Вот код реализации поведения масштабирования и панорамирования.

http://github.com/michael/unveil/blob/master/src/scene/behaviors.js

Спасибо за любые идеи. :)

Приветствия

Michael

Ответы [ 2 ]

2 голосов
/ 01 сентября 2010

Мой предыдущий ответ немного грубоват, и я сделал несколько глупых ошибок, будучи слишком неформальным.Позвольте мне попробовать еще раз:)

Итак, у вас есть матрица 3x3, представляющая преобразование вида, которое выглядит примерно так (если нет вращения):

             [ sx 0  tx ]
viewMatrix = [ 0  sy tx ]
             [ 0  0  1  ]

sx и sy представляют коэффициент масштабирования.Т.е. параметры зума.tx и ty представляют перевод.Т.е. параметры панорамирования.

(Примечание: вы действительно можете заменить sx и sy на s везде, так как sx = sy в вашем случае)

Это легко продемонстрировать, умножив его на точку p в однородных координатах.

[ sx 0  tx ]   [ px ]   [ sx * px + tx ]
[ 0  sy tx ] * [ py ] = [ sy * py + ty ]
[ 0  0  1  ]   [ 1  ]   [ 1            ]

Теперь, если вы визуализируете окно просмотра, его координаты центра будут в [-tx -ty]<sup>T</sup>.

Кроме того, если размер холста равен (width, height), тогда размер области просмотра будет (width/sx, height/sy) (поскольку размер области просмотра обратно масштабируется относительно масштаба нарисованной геометрии).

 _______________
|               |  ^
|       . [-tx] |  |  height/sy
|         [-ty] |  |
|_______________|  v
    width/sx
<--------------->

Когдаувеличение или уменьшение относительно точки привязки sx, sy, tx и ty все изменится.(Если вам нужна помощь с этим расчетом, просто добавьте комментарий, и я помогу. Я немного занят: -))

Так что теперь шаги просты

  1. ПрименитьВаш код увеличения / уменьшения масштаба матрицы (т. е. вычисление sx, sy, tx, ty)
  2. Зафиксируйте минимальный коэффициент масштабирования: s = max(s, 1.0); sx = sy = s
  3. Если границы области просмотра пересекаютсяграницы холста, переведите окно просмотра, пока оно не станет полностью видимым.Возможно, что-то примерно так:

    tx = clamp(tx, width * (1/sx - 1)/2, width * (1 - 1/sx)/2)

    ty = clamp(ty, height * (1/sy - 1)/2, height * (1 - 1/sy)/2)

(Просто проверьте мою математику в конце. Я сделал это вспешка: P)

0 голосов
/ 31 августа 2010

Почему бы не переформулировать проблему немного (для простоты)?Сохраните область просмотра в виде прямоугольника и выполните все операции масштабирования / панорамирования, преобразовав этот прямоугольник.Когда прямоугольник пересекает границу, просто закрепите ее на этой границе.

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

Надеюсь, я понял проблему, которую вы описывалиправильно.

(ПЛОХО) РЕДАКТИРОВАТЬ: При увеличении out , возможно, вы, возможно, захотите не только зажать прямоугольник.Если край прямоугольника попадает на границу, вы можете переместить «устойчивую точку», вокруг которой вы масштабируете (то есть обычно координаты курсора мыши), прямо на границу.Тогда только противоположный край будет масштабироваться больше.Если два ребра пересекаются, то «устойчивая точка» будет в углу, и будет расти только противоположный угол.Это будет поддерживать масштабирование прямоугольника с постоянной скоростью, даже когда один или несколько ребер ограничены границами.

РЕДАКТИРОВАТЬ: На самом деле проще всего не "зажать" края области просмотра, но просто переведите это, пока края не лежат на границе.Мое предыдущее редактирование немного глупо :).Это также сохранит соотношение сторон, которое, я уверен, и будет вашим намерением.Если противоположные края касаются границ, просто прекратите масштабирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...