android滚动球面布局

在某网站上看到一个效果,就是关键字的布局呈球状排布,并可以根据鼠标的移动而旋转。于是也想在Android实现同样的效果,顺便封装成通用的控件,说不定以后就可以用到了。

说干就干,大家先看看我的实现效果,Github地址:https://github.com/dgutkai/RollingBall.git,欢迎fork。

一、技术选型

开始我选择自定义一个View,在View的OnDraw方法中绘制球形,然而这种方法最大的一个缺点就是球形元素不能很好添加事件。于是改成现在的方法,即集成ViewGroup,将子控件的按照球形摆布,这样每一个子控件可以单独接受事件,也可以在XML任意布局控件。

二、球形布局理论推导

A、球面上每点的坐标(x, y, z)

x=R\cdot cos\theta \cdot sin\phi

y=R\cdot sin\theta \cdot cos\phi

z=R\cdot cos\phi

由于我们显示的界面是一个平面,所以,z坐标将作为深度变量,也就是作为透明度和缩放的值。

B、手指上下滑,坐标点(x, y, z)变为(x1, y1, z1)

由于我们屏幕上只显示XOY平面,所以当我们上下滑动的时候,球将围绕X轴旋转。因此X坐标值不变,我们在YOZ平面上看Y坐标和Z坐标的变化。

如图所示,假设球绕X轴旋转了\Delta \theta,那么得到新坐标为:

x_{1}=x

y_{1}=R_{1}\cdot cos(\theta + \Delta \theta )

z_{1}=R_{1}\cdot sin(\theta + \Delta \theta )

其中R_{1}= \frac{y}{cos\theta }=\frac{z}{sin\theta }

利用三角函数公式展开:

y_{1}=R_{1}\cdot (cos\theta\cdot cos\Delta \theta - sin\theta\cdot sin\Delta \theta) =R_{1}\cdot cos\theta\cdot cos\Delta \theta - R_{1}\cdot sin\theta\cdot sin\Delta \theta

z_{1}=R_{1}\cdot (sin\theta\cdot cos\Delta \theta + cos\theta\cdot sin\Delta \theta) =R_{1}\cdot sin\theta\cdot cos\Delta \theta + R_{1}\cdot cos\theta\cdot sin\Delta \theta

将R1代入上式,

y_{1}=\frac{y}{cos\theta }\cdot cos\theta\cdot cos\Delta \theta -\frac{z}{sin\theta } \cdot sin\theta\cdot sin\Delta \theta = y\cdot cos\Delta \theta - z\cdot sin\Delta \theta

z_{1} =\frac{z}{sin\theta }\cdot sin\theta\cdot cos\Delta \theta + \frac{y}{cos\theta }\cdot cos\theta\cdot sin\Delta \theta=z\cdot cos\Delta \theta + y\cdot sin\Delta \theta

C、手指左右滑动,坐标点(x1, y1, z1)变为(x2, y2, z2)

和B同理,手指左右滑动,球绕Y轴旋转,Y坐标不变,X、Z坐标变换原理同上,可得到
x_{2} = x_{1}\cdot cos\Delta \phi - z_{1}\cdot sin\Delta \phi

y_{2} = y_{1}

z_{2} = z_{1}\cdot cos\Delta\phi + x_{1}\cdot sin\Delta\phi

D、使用代码实现

BollBean bb1 = bollBeans[i];

double rx1 = bb1.getBX();
double ry1= bb1.getBY()*Math.cos(a1)+bb1.getBZ()*(-Math.sin(a1));
double rz1= bb1.getBY()*Math.sin(a1)+bb1.getBZ()*Math.cos(a1);

double rx2= rx1*Math.cos(b1)+rz1*Math.sin(b1);
double ry2=ry1;
double rz2= rx1*(-Math.sin(b1))+rz1*Math.cos(b1);

bb1.setBX(rx2);
bb1.setBY(ry2);
bb1.setBZ(rz2);

代码中a1,b1分别表示球绕X轴和Y轴旋转的角度。这样将手指移动的距离近似为转动的角度,便能够得到随着手指转动的球了。

详细Demo可以到我的Github下载查看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值