《TypeScript图形渲染实战:2D架构设计与实现》 —3.2.7 使用getBoundingRect方法变换坐标系
3.2.7 使用getBoundingRect方法变换坐标系
上一节中提到了CanvasMouseEvent中的canvasPosition这个成员变量,它表示的是鼠标指针位置相对于HTMLCanvasElement原点的偏移向量。如何理解这句话呢?最好的方式是画张图,直观且易于理解,如图3.11所示。
图3.11 getBoundingRect方法示例图
根据图3.11所示,整个HTML结构分为3部分:Document区域、viewport可视区,以及canvas元素区。其中:
* a点为浏览器的viewport原点。
* b点为HTMLCanvasElement元素的原点。
* c点为当前的鼠标指针的位置点。
如果能够知道b点相对于a点的偏移坐标,c点相对于a点的偏移坐标,则b点和c点处于同一个坐标系(也就是浏览器的viewport坐标系),那么很容易就能计算出c点相对于b点的偏移坐标(c - b),这个坐标就是CanvasMouseEvent中成员变量canvasPosition(相对于canvas坐标系的偏移向量)。
幸运地是,可以使用现成的类和方法来获取b点处的坐标和c点处的坐标,让我们来看一下具体的类和方法:
* 可以使用Element类的getBoundingRect方法获取当前元素的大小及相对于浏览器viewport的偏移量,也就是b点处的向量。在这里,当前元素是HTMLCanvasElement,该元素是Element的子类。
* 可以使用MouseEvent的clientX / clientY只读属性获取鼠标事件发生时相对客户区左上角原点处的偏移量,也就是相对于浏览器viewport可视区左上角a点处的偏移量,即c点坐标。
有了上述类的方法,就可以为Application类实现一个重要的坐标转换方法。具体代码如下:
// 将鼠标事件发生时鼠标指针的位置变换为相对当前canvas元素的偏移表示
// 这是一个私有方法,意味着只能在本类中使用,子类和其他类都无法调用本方法
// 只要是鼠标事件(down / up / move / drag .....)都需要调用本方法
// 将相对于浏览器viewport表示的点变换到相对于canvas表示的点
private _viewportToCanvasCoordinate ( evt : MouseEvent ) : vec2 {
if ( this . canvas ) {
let rect : ClientRect = this . canvas . getBoundingClientRect ( ) ;
// 作为测试,每次mousedown时,打印出当前canvas的boundClientRect
的位置和尺寸
// 同时打印出MouseEvent的clientX / clientY 属性
if ( evt . type === "mousedown" ) {
console . log (" boundingClientRect : " + JSON . stringify
( rect ) ) ;
console . log ( " clientX : " + evt . clientX + " clientY : " +
evt.clientY ) ;
}
let x : number = evt . clientX - rect . left ;
let y : number = evt . clientY - rect . top ;
return vec2 . create ( x , y ) ;
}
//到这里,说明canvas为null,直接报错
alert ( " canvas为null " ) ;
throw new Error ( " canvas为null " ) ;
}
理解了原理后,代码还是很简单的,接下来看一下如何调用该方法。
- 点赞
- 收藏
- 关注作者
评论(0)