transformjs玩转星球
如你所见。这篇就是要讲下使用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用来以后存放投影后的坐标。
坐标转Dom
function 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 projectionrp.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变换:
Transformation
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;//projectionimg.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 玩转星球
如你所见.这篇就是要讲下使用transformjs制作星球的过程.你也可以无视文章,直接去看源码和在线演示: 源码 | 在线演示 代码100行多一点,直接看也没有什么压力.下面分几步讲解下. 生成球上 ...
- transformjs - 玩转星球
如你所见.这篇就是要讲下使用transformjs制作星球的过程.你也可以无视文章,直接去看源码和在线演示: 源码 | 在线演示 代码100行多一点,直接看也没有什么压力.下面分几步讲解下. 生成球上 ...
- CocosCreator摘星星
玩法分析 玩家操作一个反映迟钝却蹦跳不停地小怪物去触碰不断出现的星星,难以驾驭的加速度将给玩家带来很大挑战,和您的小伙伴比一比看谁能拿到更多地星星吧! 创建项目 启动CocosCreator创建项目, ...
- 【小伟玩DAPP】疯狂角斗士:NEO上第一款上线即凉格斗游戏
本来不打算写这个游戏的评测了,但是想想对不起我的1个以太坊,毕竟一个以太坊2000呢,哦不,1900呢,哦不是,1800了 小伟还是坚强的站了起来,用1个以太换了50多个gas,体验了一把这个游戏,且 ...
- 小米第二款区块链产品WiFi链,跟网易星球很像!
继小米加密兔之后,小米昨天又上线了第二款区块链产品"小米WiFi链"."小米WiFi链"官网目前只有一个网页,对"小米WiFi链"进行了简单 ...
- 战争星球online服务器维护中,战争星球Online:世界争霸总是显示无法连接网络
战争星球Online:世界争霸总是显示无法连接网络,相信大家在玩战争星球Online:世界争霸的过程中,经常会遇到这样的问题,下面ourplay小编就简单为大家介绍几种常见的解决方案. 战争星球Onl ...
- HAVE FUN | SOFA 飞船——Layotto 星球登陆计划
一. Layotto 星球介绍 Layotto 是一款使用 Golang 开发的应用运行时, 旨在帮助开发人员快速构建云原生应用,帮助应用和基础设施解耦.Layotto 提供了各种分布式的能力,比如状 ...
- 惠星球史上最全攻略,手把手带你飞
声明:本文禁止转载及任何形式的摘抄! 一.玩转星球 1.城堡 第一,城堡是星球的核心建筑,升级城堡后才能升级其他建筑: 举个栗子: 当活力值达到2000时,我们想升级活力树,但是由于城堡是1级,升级会 ...
- 微博3元一万粉软件_实测3款朋友圈很火的“日赚分红300元”游戏软件究竟靠不靠谱!!...
上次发表了关于对陀螺世界的游戏的看法之后,很多伙伴评论都说天上哪有掉馅饼的事?是的,这类游戏花费时间,流量不说,还不知道会不会对自己的个人信息不利,毕竟这是需要手机验证码登录和微信授权登录的,但是有一 ...
最新文章
- JS中的prototype
- 重装IE后,ASP.NET无法按F5启动项目的解决方法
- Javaweb学习路线(自学规划)
- Servlet中的Session
- 雷军微博抽奖送的那台蔚来ES6 时隔10个月终于提到车了
- 接口返回数据太大_Vue实战044:Mockjs模拟服务器Api接口并返回数据详解
- SpringBoot自动装配原理解析
- JavaSE思维导图
- mac上谷歌浏览器添加插件显示程序包无效的解决办法
- 秋天视频批量生成GIF V1.32
- 小勇个人理财 怎么用
- 萌新卷妹带你逃出算法无名岛第五站
- 桌面右键新建菜单管理
- Merriam-Webster‘s Vocabular Builder ( BELL )
- SpringBoot+Vue项目漫画网站
- Linux设备驱动开发详解【二】_设备驱动相关硬件基础知识
- 20151006的NOIP模拟赛
- 模板 泛化 全特化 偏特化
- OSChina 周四乱弹 ——心有鱼,而力不足
- Java学习-工具IDEA-黑马视频(第一天)
热门文章
- 64位rhel4 u6上安装oracle 10g rac,在64位RHEL4 U6上安装Oracle 10g RAC
- 云计算机的层次结构,4.1 云架构的基本层次
- ultralight搭建/运行/打包
- mysql截取前几个字符串_mysql 截取字符串 函数
- 微型计算机由五大部件组成,冯诺依曼计算机的五大组成部件有()
- html汽车服务模板,汽车维修HTML模板
- Python+mysql高校学生社团管理系统-计算机毕业设计源码00498
- 国产公链“皇帝的新衣”,到底还有多少个元年?
- 马斯克脑机接口_马斯克的脑机接口公司 Neuralink:能做什么,不能做什么?(上)...
- 支付宝租房来电成交总结