canvas 3D元素、旋转变换

使用canvas获取上下文时,使用getContext("2d")api;那么相应的是不是也有getContext("3d")

沮丧脸,现阶段还不支持该api;那么我们如何通过2d 的canvas面绘制出3d效果的元素呢?

使用透视投影

image-20180908152948850

三维效果,可以理解为:是建立在一定的透视变化基础上的。而所谓的透视变化,指的是人眼观察物体时会有的“近大远小”的效果。

元素依照自己在虚拟三维空间中的位置,调整自己的位置和尺寸,从而创造出正确的三维效果。这个从虚拟三维空间转换到平面中的显示过程,也常称为投影。

如何在canvas坐标系中,利用透视来绘制3d?

canvas坐标系:使用W3C坐标系,坐标原点位于浏览器的左上角,沿x轴向右是正值,沿y轴向下是正值;

image-20180908153512020

透视关系

image-20180908154033410

基本思想:随着物体的原理(z坐标增加),它的大小缩小到0,同时x,y坐标向消失点移动

1
2
3
4
5
scale = f1 / (f1 + zpos);
object.scaleX = object.scaleY = scale;
object.alpha = scale; // optional
object.x = vanishingPointX + xpos * scale;
object.y = vanishingPointY + ypos * scale;

示例:

image-20180908161729898

简单的3d旋转

参照css 3d transform坐标系:

image-20180908154734767

(y轴的正轴朝下)

在处理三维坐标旋转时,使用标准的矩阵旋转公示是沒有问题的。但是把二维坐标旋转调用三次,也能够实现三维坐标的旋转,易读易懂,处理速度也较快。

三维坐标旋转的二维分解图如下:

image-20180908155028467

其中,一般的二维坐标旋转绕是Z轴旋转,物体只有x、y坐标会变化(风车旋转),三维中还可以绕x和y轴旋转。

绕x轴旋转:只有y、z坐标会变化(轮胎滚动)。

绕y轴旋转,只有x,z坐标会变化(唱片机)。

二维坐标旋转

image-20180908155130602

1
2
x1 = (x - x0) * cos(a) - (y - y0) * sin(a) + x0
y1 = (y - y0) * cos(a) + (x - x0) * sin(a) + y0

对应的其他两个轴的旋转公式:

1
2
3
4
5
6
7
// 绕x轴旋转
y1 = (y - y0) * cos(a) - (z - z0) * sin(a) + y0
z1 = (z - z0) * cos(a) + (y - y0) * sin(a) + z0
// 绕y轴旋转
x1 = (x - x0) * cos(a) - (z - z0) * sin(a) + x0
z1 = (z - z0) * cos(a) + (x - x0) * sin(a) + z0

注:文章研究的初衷是,canvas元素仿css 3d transform,寻找变换后的坐标点;示例不够具体,此处暂不提供;另外相对3d旋转矩阵计算方法来说,本文方法较为初级,且变换时的顺序要与css 旋转顺序一致,需要注意。

参考文章: