《TypeScript图形渲染实战:2D架构设计与实现》 —3.2.7 使用getBoundingRect方法变换坐标系

举报
华章计算机 发表于 2019/12/12 19:18:38 2019/12/12
【摘要】 本节书摘来自华章计算机《TypeScript图形渲染实战:2D架构设计与实现》 一书中第3章,第3.2.7节,作者是步磊峰。

3.2.7  使用getBoundingRect方法变换坐标系

  上一节中提到了CanvasMouseEvent中的canvasPosition这个成员变量,它表示的是鼠标指针位置相对于HTMLCanvasElement原点的偏移向量。如何理解这句话呢?最好的方式是画张图,直观且易于理解,如图3.11所示。

 image.png

图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 " ) ;

}

 

  理解了原理后,代码还是很简单的,接下来看一下如何调用该方法。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。