发现网上有很多以鼠标为中心的缩放算法或源码,但是找来找去没有找到“框选缩放”的算法。或者有一些第三方的类,只有使用方法,但没有讲解算法原理。花时间去读懂那些第三方的类,这点时间还不如自己写一个算法出来。特别是第三方类往往是没有注释的或注释非常少,在这种情况下,要去理解别人的思维过程和思维方式,我觉的是一件很花时间和精力的事。所以周末自己用最简单的方式写了一个算法的原理。
要求:实现像FLASH工箱中的缩放工具,点击之后,被点击的点放大后处于显示舞台的正中间;或框选之后,将框选的内容部份放大处于显示舞台的正中间。
我的原理是将动态的元件坐标,找到一个参考点,让它变成相对静态的(其实就是数学里的找隐藏关系,数学好的人可能很容易理解这样的算法)。为了讲述“框选缩放后居中”的原理,所以还是先讲一下元件的“任意点”的居中原理。
如上图:A为显示舞台的原始坐标点(0,0),B为一个元件的在舞台上处于任意位置的注册点,在这个元件上面任意位置点击,它这个点居中在屏幕显示。其实只要理解成B点移动到A点之后再缩放就可以,缩放N倍,那么x就被放大成n*x,y被放大成n*y。那么这个点在舞台中显示的“横向坐标=舞台宽度的一半-x*n”,“竖向坐标=“舞台高度的一半-y*n”。也就是将参考坐标点移到了舞台的正中间。
任意点居中只是为了框选缩放居中打基础,框选缩放后居中才是目标。
右边的元件同样也是在舞台上的任意位置,在我们框选时可以从E点拉到F点,也可以从F点拉到E点;也同样可以从G点拉到H点,也可以从H点拉到G点,四个方向都可以拉出矩形选区。要找到确定的相对的参考坐标,那么首先就要把矩形相对的让它“静止”下来。我的方法是让E点和F点是关键,让整个矩形确定下来。
E点的算法就无论什么方向拖动,取二个坐标的较小值(用Math类可以得到),F点的算法就是取二个坐标中较大的值就可以得到(同样用Math类可以得到)。与上面任意点缩放居中对齐不同的是,这次我们的参考坐标点不是舞台的正中间,而是舞台画布的左上角。
那么框选之后它到底需要被缩放多少倍呢?首先就是要解决这个动态缩放倍数的问题。倍数其实很容易就可以看出来是“舞台的宽度/框选的宽度”、或者“舞台的高度/框选的高度”。为什么要区分二种?这是因为我们在框选时不一定每次都是横竖比率不一定每次都比屏幕的横竖比率要大或要小。有时候我们可能拉一个很狭的横框,或拉一个很狭的竖框都是经常有的事。
那么缩放后元件的整体横向坐标就是“-n*E点横向坐标”,竖向坐标为“-n*E点竖向坐标”。现在缩放后的内容部份都是从原始坐标A点开始了。那么拉下来就要让它居中对齐了,是竖向的还是横向的就是上面所讲的,要先求框选的横竖比率与舞或(或画布)显示区域的横竖比率。如果“舞台的宽/舞台的高”大于“框选宽/框选高”,那么应该要让框选横向居中,因为高度正好适应到舞台的高度,所以高度保持“-n*E点竖向坐标”。反之则反之。
以下就用横向居中作为举例(注意横向居中是时正好是竖向的比率高,因为只有竖的方向达到满屏时,横向才能居中。如果不能理解的话可以画个九宫格,然后替换几个数字进去试一下。)元件横向居中的算法很常用,也很好理解,“(舞台的宽-缩放后元件的宽)/2”,而缩放后元件的宽就是“n*(F点横向坐标-E点横向坐标)”。所以整个把它们联起来就是“-n*E点横向坐标+(宽台宽-n*(F点横向坐标-E点横向坐标))/2”。
垂直居中同理:“-n*E点竖向坐标+(宽台高-n*(F点竖向坐标-E点竖向坐标))/2”。
备注:其实这里还应该进一步考虑,就是如果鼠标在移动过程中,如果移出了舞台外或画布外(或者某个自己想要把它限定的范围内),那么这个框选首先应该是被限定范围的。所以E点不可能任意小或F点任意大的,应该把框选限制在舞台或画布(或某个显示范围内),那么只要鼠标移动的过程中判断F点是否超出了某一范围就可以,如果超出了,F点就被设定为界限值。E点同理。