摘要:注意第二个参数代表关闭透视投影,因为投影下面会自己去实现。透视投影是视锥体上图没有把视锥体画出来,正交投影是立方体。所以可以设置来使用浏览器自身的透视投影,省去过程。
如你所见。这篇就是要讲下使用transformjs制作星球的过程。你也可以无视文章,直接去看源码和在线演示:
源码 | 在线演示
代码100行多一点,直接看也没有什么压力。下面分几步讲解下。
生成球上点坐标设球心为 (a,b,c),半径为r,
则球的标准方程为 (x-a)²+(y-b)²+(z-c)²=r²
这里假设球心的(0,0,0),则:
标准方程为 x²+y²+z²=r²
因为可以渲染的时候再把球的本地坐标转为世界坐标进行位移,所以球心(0,0,0)便可以。
function randomPoints() { var x, y, z, j = -1, i = 0; for (; i < size; i++) { x = getRandomNumber(-250, 250); y = getRandomNumber(-250, 250); j *= -1; if (x * x + y * y <= r * r) { z = j * Math.sqrt(Math.abs(r * r - x * x - y * y)); positions.push({x: x, y: y, z: z}); rd_positions.push({x: x, y: y, z: z}); } } }
上面的生成过程很取巧:
1.随机生成2D内的圆内的坐标x和y。(x x + y y <= r * r就是表示圆内)
2.根据2D维度的坐标推算其属于球面上的z
其中positions用来存放所有点的local坐标,rd_positions用来以后存放投影后的坐标。
坐标转Domfunction createImgs() { var i = 0, len = positions.length; for (; i < len; i++) { var img = document.createElement("img"); img.style.position = "absolute"; img.style.left = "0px"; img.style.top = "0px"; img.src = "../asset/star.png"; document.body.appendChild(img); Transform(img,true); transformImg(img,i); img_list.push(img); } }
所有的点都对应创建一个绝对定位的图片,并且通过Transform(img,true)给img注入transformation能力。注意第二个参数true代表关闭透视投影,因为投影下面会自己去实现。
投影变换function positionsProjection() { var index = 0, len=positions.length; for (; index < len; index++) { var p = positions[index]; var rp = rd_positions[index]; //perspective projection //rp.x = p.x * distance / Math.abs(camera_position.z - p.z); //rp.y = p.y * distance / Math.abs(camera_position.z - p.z); //orthogonal projection rp.x = p.x ; rp.y = p.y ; } }
为了简单起见,把球心和摄像机(也可以叫眼睛、亦或是视点)的坐标分别设置为:
center = {x: 300, y: 300, z: 0}, camera_position = {x: 300, y: 300, z: 500}, distance = 600,
distance代表摄像机到投影平面的距离,摄像机就固定在球心的正前方不动,这样进行透视投影或正交投影计算起来无比方便,免去用齐次坐标、4*4矩阵的过程。如下简单推导便可:
这里需要注意的是,上面是透视投影的图解,会产生近大远小的感觉。透视投影是视锥体(上图没有把视锥体画出来),正交投影是立方体。
正交投影如下图解,x和y坐标投影后不变就可以了:
可以这么理解:
透视投影从一个点看无数个点
正交投影从无数个点看无数个点
旋转function rotate() { var cx, z, i = 0, len=positions.length; for (; i < len; i++) { cx = positions[i].x; z = positions[i].z; positions[i].x = positions[i].x * Math.cos(step_angle) - positions[i].z * Math.sin(step_angle); positions[i].z = positions[i].z * Math.cos(step_angle) + cx * Math.sin(step_angle); } }
可以看到,上面是绕y轴旋转,所以y的坐标不变,x和z需要经过下面的matrix变换:
function transformImg(img, i) { var z = positions[i].z; img.translateX = center.x + rd_positions[i].x; img.translateY = center.x + rd_positions[i].y; //projection img.scaleX = img.scaleY = 0.5 * distance / Math.abs(camera_position.z - z); img.style.opacity =0.1+ 1 - (r - z) / (2 * r); } function render(){ var i = 0, len=positions.length; for (; i < len; i++) { transformImg(img_list[i],i); } }初始化和循环
function tick() { rotate(); positionsProjection(); render(); requestAnimationFrame(tick); } (function () { randomPoints(); createImgs(); positionsProjection(); tick(); })();
通过通过上面几行代码串整个流程。通过requestAnimationFrame循环执行tick。
最后为了加深理解,你可以把源码 clone下来,然后改代码实现:
试试绕着z轴旋转
试试绕着x轴旋转
试试切换下透视投影和正交投影
透视投影的时候试着修改摄像机的z坐标
正交投影的时候试着修改摄像机的z坐标
透视投影的时候试着修改到投影面的距离
正交投影的时候试着修改到投影面的距离
不使用星星素材换过其他素材会达到意想不到的酷炫效果
第二种实现方式:试试Transform(img,false)因为Transform第二个参数不传,或者设置为false的时候是打开透视投影的。
所以可以设置img.translateZ来使用浏览器自身的透视投影,省去positionsProjection过程。
创建图片的时候,使用下面的方式注入Transformation能力,
Transform(img, false);
即打开透视投影,
即近大远小,
即不用自己去positionsProjection
即不用自己去设置图片的scaleX和scaleY
渲染的时候直接使用原始坐标便可:
function transformImg(img, i) { var p = positions[i]; img.translateX = p.x; img.translateY = p.y; img.translateZ = p.z; img.style.opacity =0.1+ 1 - (r - p.z) / (2 * r); } function render(){ var i = 0, len=positions.length; for (; i < len; i++) { transformImg(img_list[i],i); } }
循环和初始化,不再需要投影过程:
function tick() { rotate(); render(); requestAnimationFrame(tick); } (function () { randomPoints(); createImgs(); tick(); })();transformjs
transformjs提供了基础的transformation能力,不与任何时间和运动库绑定。虽然官网demo简单,但是稍微费点脑细胞就可以做出很酷炫的效果。所以酷炫靠大家,用transformjs就对了。
传送门:transformjs 主页 | transformjs Github
所有例子可以在上面找到。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/91236.html
摘要:写在前面记得以前做过一款游戏。开场动画是一块软体类似豆腐的东西一起摇摆。基本的原理主要是循环运动抽象的的和来实现软体摇摆。目前来看也能做到,因为也能运动和。可以和任意时间运动库配合使用。 写在前面 记得以前facebook做过一款HTML5游戏。开场动画是一块软体类似豆腐的东西一起摇摆。类似的效果如下面的gif所示:showImg(https://segmentfault.com/im...
摘要:更别提配合一些运动或者时间的库来编程了。姿势封装了一大堆关键帧动画,开发者只需要关心添加或者移除相关的动画的便可以。 简介 在过去的两年,越来越多的同事、朋友和其他不认识的童鞋进行移动web开发的时候,都使用了transformjs,所有必要介绍一下,让更多的人受益,提高编程效率,并享受编程乐趣。(当然transformjs不仅仅支持移动设备,支持CSS3 3D Transforms的...
阅读 987·2021-10-19 11:42
阅读 2943·2021-09-10 10:51
阅读 639·2021-09-09 09:33
阅读 1693·2021-09-01 10:43
阅读 2738·2019-08-30 12:43
阅读 3491·2019-08-30 11:24
阅读 2052·2019-08-30 10:56
阅读 2755·2019-08-29 11:00