第
JS图形编辑器场景坐标视口坐标的相互转换
视口坐标转换为场景坐标
场景坐标转换为视口坐标
图形编辑器坐标系
图形编辑器的坐标系有两种。
一个是场景(scene)坐标系,一个是视口(viewport)坐标系。视口就是场景的一个子区域。
假设我们的视口的原点,离场景原点的坐标水平和垂直距离分别为scrollX和scrollY。
先不考虑缩放,假设我们在视口坐标上的某个地方点击了一下,这个坐标是(x,y)。这个坐标在场景坐标系中,就是:
constsceneX=scrollX+x;
constsceneY=scrollY+y;
挺简单。
视口坐标转换为场景坐标
下面我们引入画布缩放,即画布可以缩小和放大,对应的一个比例值zoom。
视口中的某个坐标(x,y)在场景坐标系,则是:
functionviewportCoordsToSceneCoords(x,y,scrollX,scrollY,zoom){
return{
x:scrollX+x/zoom,
y:scrollY+y/zoom
}
之所以要用x除以zoom,是因为此时视口中展示的是缩放后的图形,里面的坐标都是缩放后的值。所以需要先转换为zoom值为1对应的真实值。
场景坐标转换为视口坐标
然后我们反过来,如何从场景坐标(x,y)转换为视口坐标?将前面的公式做等式变换即可:
functionsceneCoordsToViewportCoords(x,y,scrollX,scrollY,zoom){
return{
x:(x-scrollX)*zoom,
y:(y-scrollY)*zoom
};
我们通常是使用按键加滚轮的方式让画布以光标为中心进行缩放,或按按钮进行缩放,
为了让缩放后的场景还能对上缩放前光标的位置,我们需要计算缩放后的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),其他不变。
就这些了。
总结一下,视口坐标是场景坐标平移并缩放后的结果,所以视口转场景,需要除以zoom再加上偏移值。在图形编辑器中,会有相当多的坐标系转换逻辑,这两个坐标系的关系需要好好消化理解,更多关于JS场景视口坐标转换的资料请关注其它相关文章!