html3d云标签,3D标签云

开始之前

文章开始之前,应该了解几个重要的公式。回忆一下我们逝去的高中。

重要概念:

sinθ、cosθ的值得大小区间是[-1,1];

弧度跟角度的转换公式是:弧度 = π/180 * 角度。

公式:

1、在空间直角坐标系中,以坐标原点为球心,半径为R的球面的参数方程为:

x = r * sinθ * cosΦ;

y = r * sinθ * sinΦ;

z = r * cosθ;

说明:θ为点跟圆心的连线与z轴的夹角,Φ是点跟圆心连线在xy平面投影线与x轴的夹角(可以根据需要建立不同的坐标系,或者取不同的夹角,坐标的表达方式可以有很多,但原理是类似的)。

2、旋转公式:

x1 = cosθ * x - sinθ * y;

y1 = cosθ * y + sinθ * x;

说明:(x,y)是开始的坐标,θ是旋转的角度,(x1,y1)是结束的坐标。球绕某一条轴的旋转可以抽象成圆绕圆心旋转,根据旋转前的坐标和角度可以求出旋转后的坐标。

正文部分

了解了几个公式之后,3D标签云的旋转其实就很简单了。原理就是把标签当成一个点,通过设置不同的θ,Φ把它们平均分布在球面的各个坐标点上。 旋转x轴或者y轴达到球体旋转的目的。z轴是一条虚拟出来的轴,它与我们的屏幕垂直。我们不能真的实现一个立体的球体出来,但是我们可以通过"近大远小"达到视觉的欺骗,呈现一种立体的感觉。

原理差不多说完了,接下来开始具体的代码实现过程。

设置坐标

设置坐标是最重要,也是相对难的一步,因为我们要达到平均分布,避免分布太过集中或者重叠。因为半径是固定的,所以我们从角度出发,调整角度达到平均分布的目的。接下来我们引入一位大神的式子,我也不知道出处是那里,但是确实很好用,式子如下:

θ = arccos(((2 * i) - 1) / len - 1);

Φ = θ * sqrt(len * π);

第一个式子arccos中的((2 * i) - 1) / len - 1其实是一个[-1,1]区间上关于0对称分布的等差数列,通过反余弦转换成弧度值,的确是一个很高明的式子,学渣的我确实想不出来。第二个式子,是关于θ的等差(变量只有θ),不过参数sqrt(len * π)的取值就不是很懂了,还望知情的大神告知。

具体的代码如下:

分配坐标:

var init = function() {

const tagEle = cloud.querySelectorAll('.tag'),

tagLen = tagEle.length;

for(let i = 0; i < tagLen; i++) {

// 设置随机坐标,平均分布

let a = Math.acos((2 * (i + 1) - 1) / tagLen - 1), // θ = arccos(((2*(i+1))-1)/len - 1)

b = a * Math.sqrt(tagLen * Math.PI), // Φ = θ*sqrt(all * π)

x = R * Math.sin(a) * Math.cos(b), // x轴坐标: x=r*sinθ*cosΦ

y = R * Math.sin(a) * Math.sin(b), // y轴坐标: x=r*sinθ*cosΦ

z = R * Math.cos(a), // z轴坐标: z=r*cosθ

t = new tag(tagEle[i] , x , y , z);

tagEle[i].style.color = '#' + Math.floor(Math.random() * 0xffffff).toString(16); // 设置随机颜色

tags.push(t);

t.move(); // 初始化位置

}

animate(); // 旋转

};

设置坐标及参数:

let scale = _focalLength / (_focalLength - this.z),

alpha = (this.z + R) / (2 * R),

ele = this.ele;

ele.style.fontSize = 14 * scale + "px";

ele.style.opacity = alpha + 0.5;

ele.style.zIndex = parseInt(scale * 100);

// 原点是 (cloud.offsetWidth/2, cloud.offsetHeight/2)

ele.style.left = this.x + cloud.offsetWidth / 2 - ele.offsetWidth/2 + "px";

ele.style.top = this.y + cloud.offsetHeight / 2 - ele.offsetHeight/2 + "px";

scale、alpha 都是取关于z坐标的递增函数,所以可以根据需要调整函数达到更好的显示效果。

旋转

开始的时候我们简单介绍了圆的旋转,球的旋转其实类似圆。例如绕z轴旋转,其实改变的是x,y坐标的值,z坐标的值并没有变化。理解了这一层,我们可以得出绕x轴旋转的和y轴旋转的函数,分别为:

/*

绕x轴旋转

y = ycosθ - zsinθ;

z = ysinθ + zcosθ;

*/

function rotateX() {

let cos = Math.cos(angleX),

sin = Math.sin(angleX);

tags.forEach(function(tag) {

let y = tag.y * cos - tag.z * sin,

z = tag.z * cos + tag.y * sin;

tag.y = y;

tag.z = z;

})

};

/*

绕y轴旋转

x = xcosθ - zsinθ;

z = xsinθ + zcosθ;

*/

function rotateY() {

let cos = Math.cos(angleY),

sin = Math.sin(angleY);

tags.forEach(function(tag) {

let x = tag.x * cos - tag.z * sin,

z = tag.z * cos + tag.x * sin;

tag.x = x;

tag.z = z;

})

};

于是我们就能通过控制angleX、angleY的大小来达到旋转的目的了,值越大,单位时间旋转的角度越大,也就是旋转的速度越快。当然,旋转360度跟没旋转的效果是一样的,所以我们应该合理的设置单位时间和每一次旋转的角度值,让我们的眼睛知道它是个球,它在转!!!

全部代码

这是我在百度前端学院的一个课程练习的代码,代码全部放在Github上,希望对您有一点帮助。同时,Github求关注!!!

结束

以上内容来自一个前端低手的个人总结与整理,不足之处,还请指正。

题外:通过这次的练习才知道,学好数学是多么重要啊!!!

革命尚未成功,同志还需很努力!!!

参考文章:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值