# transformjs 玩转星球

## 生成球上点坐标

``````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

## 坐标转 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);
}
}``````

## 投影变换

``````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矩阵的过程。如下简单推导便可：

• 透视投影从一个点看无数个点
• 正交投影从无数个点看无数个点

## 旋转

``````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);
}
}``````

## 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();
})();``````

## 最后

• 试试绕着z轴旋转
• 试试绕着x轴旋转
• 试试切换下透视投影和正交投影
• 透视投影的时候试着修改摄像机的z坐标
• 正交投影的时候试着修改摄像机的z坐标
• 透视投影的时候试着修改到投影面的距离
• 正交投影的时候试着修改到投影面的距离
• 不使用星星素材换过其他素材会达到意想不到的酷炫效果

## 第二种实现方式:试试Transform(img,false)

``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就对了。

JSmiles

0 文章
0 评论
84935 人气