使用ViewMatrix进行约束平移/缩放

时间:2010-08-30 21:00:13

标签: javascript html5 graphics

我正在尝试为我为Unveil.js(http://github.com/michael/unveil)实现的缩放和平移行为添加约束边界。启用边界后,您无法在场景边界外平移,并且zoomlevel(= scale)不应低于1.0。因此,如果您处于zoomlevel 1.0,则根本无法进行平移。

您可以在堆栈示例中看到未受约束的行为:dejavis.org/stacks。使用鼠标滚轮进行缩放。你可以将屏幕擦除屏幕或无限缩小它们,这应该避免。

真正难以解决的问题是,相对于鼠标指针进行缩放也会导致视口移动到位。因此在平移过程中检查边界是不够的。使用Mouswheel时我必须找到一种智能的缩放方式(不做脏跳)。在缩放图片时,Photoshop似乎已经解决了这个问题。

我完全不知道如何解决这个问题。很沮丧。 :/

我正在使用Matrix来存储重复操作的当前View转换。 这是缩放和平移行为的实现代码。

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

感谢您的任何想法。 :)

干杯,

迈克尔

2 个答案:

答案 0 :(得分:2)

我之前的回答有点粗糙,我过于非正式地犯了一些愚蠢的错误。让我再试一次:))

所以你有一个3x3矩阵表示看起来像这样的视图转换(如果没有旋转):

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

sxsy代表缩放系数。即缩放参数。 txty代表翻译。即平移参数。

(注意:您实际上可以在sx之后的任何地方替换sys

通过将其与齐次坐标中的点sx = sy相乘,可以很容易地证明这一点。

p

现在,如果您可视化视口,其中心坐标将位于[ sx 0 tx ] [ px ] [ sx * px + tx ] [ 0 sy tx ] * [ py ] = [ sy * py + ty ] [ 0 0 1 ] [ 1 ] [ 1 ]

此外,如果画布大小为[-tx -ty]T,则视口的大小将为(width, height)(因为视口的大小与绘制的几何图形的比例成反比)。

(width/sx, height/sy)

当相对于锚点sx放大或缩小时,sy,tx和ty都将改变。 (如果你需要这个计算的帮助,只需添加一个评论,我会帮助。我有点忙: - ))

所以现在步骤很简单

  1. 将放大/缩小代码应用于矩阵(即计算sx,sy,tx,ty)
  2. 钳制最小缩放系数: _______________ | | ^ | . [-tx] | | height/sy | [-ty] | | |_______________| v width/sx <--------------->
  3. 如果视口边框与画布边界相交,请将视口转换为完全在视图中。可能大概是这样的:

    s = max(s, 1.0); sx = sy = s

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

  4. (最后检查我的数学结果。我匆忙做了:P)

答案 1 :(得分:0)

为什么不稍微重新解决问题(简单来说)?将视口存储为矩形,并通过变换该矩形来执行所有缩放/平移操作。当矩形越过边界时,只需将其夹在边界上即可。

然后只需从矩形大小和位置计算缩放和平移参数。

希望我理解你正确描述的问题。

(BAD)编辑:当缩放 out 时,您可能不仅想要夹住矩形。 如果矩形的边缘到达边界,则可以将正在缩放的​​“稳定点”(即通常是鼠标光标坐标)移动到边界上。然后只有相反的边缘会扩大。如果两条边相交,那么“稳定点”将位于拐角处,只有相对的角落会增长。即使一个或多个边缘被约束到边界,这也将使矩形按比例保持一致。

编辑:实际上最简单的方法是不要“夹住”视口的边缘,而只是将其平移直到边缘位于边界上。我以前的编辑有点傻:)。这也将保持纵横比固定,我肯定是你的意图。如果相对边缘触及边界,则只需停止缩放。