大家好,我是前端西瓜哥。图形编辑器有两种类型的坐标系。一个是场景坐标系,一个是视口坐标系。视口是场景的一个子区域。假设我们视口的原点,距离场景原点的坐标水平和垂直距离分别是scrollX和scrollY。无论缩放如何,假设我们在视口坐标上的某处单击,即(x,y)。该坐标在场景坐标系中,即:constsceneX=scrollX+x;constsceneY=scrollY+y;很简单。将视口坐标转换为场景坐标接下来介绍画布缩放,即画布可以缩小和放大,对应一个比例值缩放。viewport中的某个坐标(x,y)在场景坐标系中,则:zoom}}之所以x除以zoom是因为此时viewport中显示的是缩放后的图形,里面的坐标都是缩放后的值。所以需要转换成缩放值1对应的真实值。场景坐标转换成视口坐标然后我们反过来,如何从场景坐标(x,y)转换成视口坐标?只需将前面的公式转化为一个等式即可:画布通过按下按钮和滚轮围绕光标缩放,或者通过按下按钮缩放。为了让缩放后的场景与缩放前光标的位置匹配,我们需要计算缩放后的scrollX和scrollY。校准。核心思想是保持缩放前的点到视口左上角(视口坐标系)的距离相同。functioncalScrollVal(cx,cy,prevZoom,zoom,scrollX,scrollY){//首先计算目标点的场景坐标(这里的cx和cy是基于视口坐标系)const{x:sceneX,y:sceneY}=viewportCoordsToSceneCoords(cx,cy,prevZoom,scrollX,scrollY);//缩放后画布的缩放比例变成了zoom,距离视口左上角的距离变成了cx/zoom//减去这个距离就是新的scrollX。constnewScrollX=sceneX-cx/zoom;constnewScrollY=sceneY-cy/zoom;return{x:newScrollX,y:newScrollY};}说点别的吧。可能会出现这样一种情况,实际视口区域的原点坐标偏移了offsetX和offsetY,如下图所示。我们只需要将之前代码中的scrollX改为(scrollX+offsetX),scrollY改为(scrollY+offsetY),其他不变。就这样。综上所述,视口坐标是场景坐标平移和缩放的结果,所以要将视口转换为场景,需要除以缩放并加上偏移值。在图形编辑器中,会有相当多的坐标系转换逻辑,需要消化和理解这两个坐标系之间的关系。
