归一化坐标
归一化坐标,是一个二维坐标,仅有X/Y两个维度,且X和Y的取值范围均为[-1, 1]
,坐标原点位于three.js所创建的canvas的中心处。
关于【归一化坐标】的具体概念,可以去百度搜索,我这里说一下我自己的一些见解,主要是作为一个使用者,应该如何去看待这个东西。疏漏之处,还请指正。
要了解归一化坐标,有这么两个前置概念:屏幕坐标
,三维坐标
。
其中,屏幕坐标
指的就是物理屏幕上是坐标,三维坐标
指的则是three.js
所创建的这个逻辑上的三维世界中的坐标。屏幕坐标
以【像素(px)】为单位,三维坐标
以三维世界中的【单位1】为单位。屏幕坐标
的取值范围是屏幕是像素数(X对应横向长度,y对应纵向长度),三维坐标
的取值范围的无穷(z/y/z三个轴均如此)。屏幕坐标
的坐标系原点在屏幕的左上角(页面的左上角),三维坐标
的坐标系原点在三维世界的中心。
现在,我有一个屏幕坐标,使用起来很简单;我也可以创建一个三维坐标,使用起来也很简单。但是,如果我想要把一个屏幕坐标
转换为三维坐标
使用呢?这时,就要使用一个中间值了,这个中间值,也就是这个【归一化坐标】。也就是说,作为一个使用者,可以将归一化坐标当做是:对屏幕坐标
和三维坐标
进行相互转换时的一个中间坐标。在使用上来说,归一化坐标实际使用中的意义,就在这里了。
本文仅讨论从屏幕坐标
转换为三维坐标
的方法,从三维坐标
转换为屏幕坐标
的方法不做讨论。
公式:
首先,先把公式摆出来,以点击事件触发的屏幕坐标为演示。
js复制代码/**
* @mouse 归一化坐标,一个二维坐标
* @event 点击事件中的事件对象
* @container 渲染器的包裹父元素
*/
var mouse = new Three.Vector2();
// 则有公式如下:
mouse.x = ((event.clientX - container.getBoundingClientRect().left) / container.getBoundingClientRect().width) * 2 - 1;
mouse.y = - ((event.clientY - container.getBoundingClientRect().top) / container.getBoundingClientRect().height) * 2 + 1;
推导过程:
设定:屏幕宽度为w,高度为h
已知:A点的屏幕坐标为(x, y),归一化坐标轴所在矩形(也就是three.js所创建的canvas元素)距离屏幕上方距离为t,距离屏幕左侧距离为l
求得:A点的归一化坐标 (a, b)
所谓归一化坐标,可以理解为在屏幕中的某个矩形中建立一个平面直角坐标系(可以称为归一化坐标系),右为此坐标系x轴正方向,上为此坐标系y轴正方向,且x轴取值范围为[-1,1],y轴取值范围为[-1,1],那么矩形内任意一点的坐标都可以用一个屏幕坐标的百分比来表示,百分比的计算为:
坐标x = (x-l)/w - 0.5
坐标y = (y-t)/h - 0.5
分析:此式中x-l
表示矩形内点距离矩形左侧边缘的距离,则(x-l)/w
可表示所点击的点距离屏幕左边缘的距离所占矩形宽度的百分比,此时得到一个值域在[0, 1]
的数字,再减去0.5
则可将值域限制在[-0.5, 0.5]
,同理推得坐标y = (y-t)/h - 0.5
。此时可以得到一个坐标的x,y
值域均在[-0.5, 0.5]
的坐标,这时将值*2
则可将值域拓展到[-1, 1]
,则此时的计算公式也变为:坐标x = (x-l)/w * 2 - 1
坐标y = (y-t)/h * 2 - 1
。
最后,考虑y轴,屏幕坐标轴的y轴轴方向与矩形内归一化坐标系y轴的轴方向相反(无需考虑x轴就是因为屏幕坐标轴的x轴与归一化坐标轴的x轴方向相同),而此前所有计算中y值均为屏幕坐标轴的y值,是故将点从屏幕坐标轴转到归一化坐标轴时,应当对y值进行取反,即坐标y = -[(y-t)/h * 2 - 1]
,去括号,将负号参与计算,得坐标y = 1 - (y-t)/h * 2
。
至此,得出公式:
ini复制代码坐标x = (x-l)/w * 2 - 1
坐标y = 1 - (y-t)/h * 2
将x、y
对应为event.clientX
和event.clientY
;
将w、h
对应为 container.getBoundingClientRect().width
和container.getBoundingClientRect().height
;
将l、t
对应为 container.getBoundingClientRect().left
和container.getBoundingClientRect().top
。
至此,得出上面所说的通用公式。
其实这个所谓的【通用公式】,其实也就是比网上的那些公式多了一步减法而已,x/y分别减去了canvas
元素到屏幕(网页)左边缘的距离和到屏幕(网页)上边缘的距离。但是不理解【归一化坐标】的具体含义,想要想到这一步减去还是很难的。