如你所见。这篇就是要讲下使用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 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变换:

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;
//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

所有例子可以在上面找到。

transformjs玩转星球的更多相关文章

  1. AutoJS4.1.0实战教程 ---火热持续更新中

    这个时代假货太多,虚假广告更是充斥着整个互联网.尤其是那个传奇的我都无语了.好几个明xing代言,问题是太假了……我好奇的是那么虚假怎么就没人管呢,XX部干嘛呢……另外互联网刷视频赚钱就是个炒作.几百 ...

  2. 玩转HTML5移动页面(动效篇)

    原文:http://www.grycheng.com/?p=458 作为一名前端,在拿到设计稿时你有两种选择: 1.快速输出静态页面 2.加上高级大气上档次狂拽炫酷屌炸天的动画让页面动起来 作为一个有 ...

  3. 你也可以玩转Skype -- 基于Skype API开发外壳程序入门

    原文:你也可以玩转Skype -- 基于Skype API开发外壳程序入门 Skype是目前这个星球上最厉害的IM+VOIP软件,Skype现在已经改变了全球2.8亿人的生活方式.你,值得拥有! :) ...

  4. Python又把GUI界面攻下了,今天就告诉你怎么玩

    0.引言 学Python这么久了,一直想做个界面出来,最近发现Python有个内置库tkinter,利用它可以很轻松做出一些简易的UI界面,首先来看Python官方对Tkinter的说明: The t ...

  5. BZOJ 2754 【SCOI2012】 喵星球上的点名

    题目链接:喵星球上的点名 首先可以发现姓和名两个串就是逗你玩的.在两个串中间插入一个\(10001\),当成一个串做就可以了. 于是我们的问题转化为了: 有\(n\)个串\(A_1,A_2,\dots ...

  6. 玩转Vim-札记(一)

    玩转Vim-札记(一) 简介 在这个蔚蓝色的星球上,流传着两大神器的传说:据说Emacs是神的编辑器,而Vim是编辑器之神.一些人勇敢地拾起了Vim或Emacs,却发现学习曲线陡峭而漫长,还是有一些人 ...

  7. App裂变活动多种玩法解析

    移动互联网时代,流量为王.在App获取流量的过程中,有资金的砸广告,没资金的铺渠道,但是不管你有钱没钱,社交平台都是必须重点争夺的流量阵地. 毕竟,截至2018年底,微信及WeChat的合并月活跃账户 ...

  8. 盘点一下Creator星球上的开源工具包!

    晓衡开始写公众号,最早是从上架 Cocos 商店的 pbkiller 插件开始的,到至今有2年2个月了.在这期间,又陆续在公众号上分享了多个实用工具包,在这里统一盘点一下,方便与大家交流学习. 一.u ...

  9. cocos creator 3D | 蚂蚁庄园运动会星星球

    上一篇文章写了一个简易版的蚂蚁庄园登山赛,有小伙伴留言说想要看星星球的,那么就写起来吧! 效果预览 配置环境 cocos creator 3d 1.0.0 小球点击 3d里节点无法用 cc.Node. ...

随机推荐

  1. Oracle使用触发器和mysql中使用触发器的比较——学习笔记

    一.触发器 1.触发器在数据库里以独立的对象存储, 2.触发器不需要调用,它由一个事件来触发运行 3.触发器不能接收参数 --触发器的应用 举个例子:校内网.开心网.facebook,当你发一个日志, ...

  2. 怎样在Dos里切换盘符

    一:在Dos里切换盘符 a:在电脑左下角右击显示图片;(我用的是win10系统,其他系统类似) b:点击运行,输入cmd; c:点击确定: d:输入盘符:(如f:) 或F: 只写字母,不写分号是不行的 ...

  3. 分享在Linux下使用OSGi.NET插件框架快速实现一个分布式服务集群的方法

    在这篇文章我分享了如何使用分层与模块化的方法来设计一个分布式服务集群.这个分布式服务集群是基于DynamicProxy.WCF和OSGi.NET插件框架实现的.我将从设计思路.目标和实现三方面来描述. ...

  4. 匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置

    0x00 前言: 匹夫在日常和别人交流的时候,常常会发现一旦讨论涉及到“类型”,话题的热度就会立马升温,因为很多似是而非.或者片面的概念常常被人们当做是全面和正确的答案.加之最近在园子看到有人翻译的& ...

  5. Go build constraints

    Go语言有一个不(奇)错(葩)的设计,就是build constraints(构建约束).可以在源码中通过注释的方式指定编译选项,比如只允许在linux下,或者在386的平台上编译啊之类的:还可以通过 ...

  6. 2000条你应知的WPF小姿势 基础篇<34-39 Unhandled Exceptions和Resource>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...

  7. 序列化笔记之一:Google的Protocol Buffer格式分析

    从公开介绍来看,ProtocolBuffer(PB)是google 的一种数据交换的格式,它独立于语言,独立于平台.作为一个学了多年通信的人,ProtocolBuffer在我看来是一种信源编码.所谓信 ...

  8. 使用boilerplate模版创建解决方案

    返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 话不多说,让我们开始干吧!对于还没有接触ABP框架或者接触时间还不是很长的小伙伴来说,我建议还是使用官方建议的做法,那就是到ABP ...

  9. AngularJs之八

    ***今天讲一下angularJs的路由功能: 一:angularJs路由. 1.AngularJS 路由允许我们通过不同的 URL 访问不同的内容. 2.通过 AngularJS 可以实现多视图的单 ...

  10. ASP.NET MVC系列:Model

    1. Model任务 Model负责通过数据库.AD(Active Directory).Web Service及其他方式获取数据,以及将用户输入的数据保存到数据库.AD.Web Service等中. ...