这几天接到了一个需求,需要在canvas中实现2D地图的缩放,Google了一下似乎没有找到很好的解决方案,因此自己推了一个坐标变换的公式,在此做一个记录
首先第一点:地图缩放的关键就是确保两手指之间的中间点在地图上缩放前后的相对位置保持不变

在上图中,定义三个点(x1,y1)(x2,y2)(x3,y3),其中第一个点是缩放前canvas画布绘制的起始点,第二个点是双指触摸中心点在canvas画布上的位置,第三个点是缩放后,第二个点的位置
我们想要做到的目标就是缩放前后,第二个点和第三个点的相对位置保持不变
也就是说,我们需要把第三个点移动到第二个点的位置,具体实现上来说,我们可以通过移动canvas画布绘制的起始点来改变第三个点的位置,也就是图中第三个点到第二个点的箭头表示的
也就是说,我们要计算出第二个点和第三个点的x和y的差值,并将其作为绘制原点的位移
现在开始推导如何计算两点的差值
原始顶点prev:(x1,y1)curr左下顶点:(x1,y1−kh1)原始点(x2,y2)假设变换后的点(x3,y3)有:kh1y3−y1=h1y2−y1y3−y2x3−x2=y2−y1x2−x1我们想要放大缩小后的中心点在可视区域地图上的相对位置保持不变,相当于要计算x3−x2与y3−y2设x2−x3=Δx,y2−y3=Δy(x1−Δx,y1+Δy)即是变换后的绘制原点
x3=kx2−(k−1)x1y3=ky2−(k−1)y1
Δx=(1−k)(x2−x1)Δy=(1−k)(y2−y1)
变换后的坐标(kx1+(1−k)x2,ky1+(1−k)y2)
基本上就是结合相似三角形边之比与三点共线的条件就可以获得用x1,x2表示的x3的表达式
而在代码中,我们又是知道屏幕点击点(x2)与当前cnavas画布绘制原点((x1,y1))的,因此可以递推的算出一次缩放后的绘制原点,使得变换后的(x3,y3的位置和点击点(x2,y2)一致
也就是
(x1n,y1n)=(kx1n−1+(1−k)x2,ky1n−1+(1−k)y2)