如你所见。这篇就是要讲下使用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玩转星球相关推荐

  1. transformjs 玩转星球

    如你所见.这篇就是要讲下使用transformjs制作星球的过程.你也可以无视文章,直接去看源码和在线演示: 源码 | 在线演示 代码100行多一点,直接看也没有什么压力.下面分几步讲解下. 生成球上 ...

  2. transformjs - 玩转星球

    如你所见.这篇就是要讲下使用transformjs制作星球的过程.你也可以无视文章,直接去看源码和在线演示: 源码 | 在线演示 代码100行多一点,直接看也没有什么压力.下面分几步讲解下. 生成球上 ...

  3. CocosCreator摘星星

    玩法分析 玩家操作一个反映迟钝却蹦跳不停地小怪物去触碰不断出现的星星,难以驾驭的加速度将给玩家带来很大挑战,和您的小伙伴比一比看谁能拿到更多地星星吧! 创建项目 启动CocosCreator创建项目, ...

  4. 【小伟玩DAPP】疯狂角斗士:NEO上第一款上线即凉格斗游戏

    本来不打算写这个游戏的评测了,但是想想对不起我的1个以太坊,毕竟一个以太坊2000呢,哦不,1900呢,哦不是,1800了 小伟还是坚强的站了起来,用1个以太换了50多个gas,体验了一把这个游戏,且 ...

  5. 小米第二款区块链产品WiFi链,跟网易星球很像!

    继小米加密兔之后,小米昨天又上线了第二款区块链产品"小米WiFi链"."小米WiFi链"官网目前只有一个网页,对"小米WiFi链"进行了简单 ...

  6. 战争星球online服务器维护中,战争星球Online:世界争霸总是显示无法连接网络

    战争星球Online:世界争霸总是显示无法连接网络,相信大家在玩战争星球Online:世界争霸的过程中,经常会遇到这样的问题,下面ourplay小编就简单为大家介绍几种常见的解决方案. 战争星球Onl ...

  7. HAVE FUN | SOFA 飞船——Layotto 星球登陆计划

    一. Layotto 星球介绍 Layotto 是一款使用 Golang 开发的应用运行时, 旨在帮助开发人员快速构建云原生应用,帮助应用和基础设施解耦.Layotto 提供了各种分布式的能力,比如状 ...

  8. 惠星球史上最全攻略,手把手带你飞

    声明:本文禁止转载及任何形式的摘抄! 一.玩转星球 1.城堡 第一,城堡是星球的核心建筑,升级城堡后才能升级其他建筑: 举个栗子: 当活力值达到2000时,我们想升级活力树,但是由于城堡是1级,升级会 ...

  9. 微博3元一万粉软件_实测3款朋友圈很火的“日赚分红300元”游戏软件究竟靠不靠谱!!...

    上次发表了关于对陀螺世界的游戏的看法之后,很多伙伴评论都说天上哪有掉馅饼的事?是的,这类游戏花费时间,流量不说,还不知道会不会对自己的个人信息不利,毕竟这是需要手机验证码登录和微信授权登录的,但是有一 ...

最新文章

  1. JS中的prototype
  2. 重装IE后,ASP.NET无法按F5启动项目的解决方法
  3. Javaweb学习路线(自学规划)
  4. Servlet中的Session
  5. 雷军微博抽奖送的那台蔚来ES6 时隔10个月终于提到车了
  6. 接口返回数据太大_Vue实战044:Mockjs模拟服务器Api接口并返回数据详解
  7. SpringBoot自动装配原理解析
  8. JavaSE思维导图
  9. mac上谷歌浏览器添加插件显示程序包无效的解决办法
  10. 秋天视频批量生成GIF V1.32
  11. 小勇个人理财 怎么用
  12. 萌新卷妹带你逃出算法无名岛第五站
  13. 桌面右键新建菜单管理
  14. Merriam-Webster‘s Vocabular Builder ( BELL )
  15. SpringBoot+Vue项目漫画网站
  16. Linux设备驱动开发详解【二】_设备驱动相关硬件基础知识
  17. 20151006的NOIP模拟赛
  18. 模板 泛化 全特化 偏特化
  19. OSChina 周四乱弹 ——心有鱼,而力不足
  20. Java学习-工具IDEA-黑马视频(第一天)

热门文章

  1. 64位rhel4 u6上安装oracle 10g rac,在64位RHEL4 U6上安装Oracle 10g RAC
  2. 云计算机的层次结构,4.1 云架构的基本层次
  3. ultralight搭建/运行/打包
  4. mysql截取前几个字符串_mysql 截取字符串 函数
  5. 微型计算机由五大部件组成,冯诺依曼计算机的五大组成部件有()
  6. html汽车服务模板,汽车维修HTML模板
  7. Python+mysql高校学生社团管理系统-计算机毕业设计源码00498
  8. 国产公链“皇帝的新衣”,到底还有多少个元年?
  9. 马斯克脑机接口_马斯克的脑机接口公司 Neuralink:能做什么,不能做什么?(上)...
  10. 支付宝租房来电成交总结