卸腰。。有很多图,请在wifi下观看
齿轮的形状是多种多样的,我没有画渐开线齿轮(对不起各位机械大佬了),简单画一个好实现的思路;
1,把一个圆的边缘均分分成若干点:
while (angular<(2*Math.PI)+sportAngular){ PointF p = new PointF((float)( centerF.x+(diameter/2)*Math.cos(angular)),(float) (centerF.y+(diameter/2)*Math.sin(angular))); breadthP.add(new BreadthP(p,angular)); angular+=breadth; }
2,然后呢,把这些点用path连接起来:
有的同学肯定会说:你骗人,这东西和齿轮有jj关系;
别着急啊,想要画出弯弯曲曲的圆周曲线,我们需要先做一道初中数学题来取用来做贝塞尔曲线的点:
已知O点坐标,日1,日2,x1,y1,x2,y2。求xq,yq的坐标值?
小明同学出色的完成了算术题:
求出贝塞尔点之后,我们的图形变成这个样子:
再将偶数点取负:
这一段的代码实现:
for(int i =0;i<breadthP.size();i++){ int j ; float angulaQ; if(i<breadthP.size()-1){ j = i+1; angulaQ = (breadthP.get(i).angular+breadthP.get(j).angular)/2; }else { j = 0; angulaQ = (float) ((breadthP.get(i).angular+breadthP.get(j).angular+2*Math.PI)/2); } float b = (float) Math.sqrt((breadthP.get(j).f.x-breadthP.get(i).f.x)*(breadthP.get(j).f.x-breadthP.get(i).f.x)+ (breadthP.get(j).f.y-breadthP.get(i).f.y)*(breadthP.get(j).f.y-breadthP.get(i).f.y)); float x1 = (breadthP.get(j).f.x+breadthP.get(i).f.x)/2; float y1 = (breadthP.get(j).f.y+breadthP.get(i).f.y)/2; float d = (float) ((float) Math.sqrt((x1-centerF.x)*(x1-centerF.x) +(y1-centerF.y)*(y1-centerF.y))+ ( (i%2==0) ? (-b) : b ) ); float quadPx =(float)( centerF.x+d*Math.cos(angulaQ)); float quadPy =(float)( centerF.y+d*Math.sin(angulaQ)); gearPath.quadTo(quadPx,quadPy,breadthP.get(j).f.x,breadthP.get(j).f.y); }
我们将取点的密度提高一倍,中间再加个圆圈:
这是不就像是个齿轮了?
再加上个角自增的线程:
Runnable runnable =new Runnable() { @Override public void run() { angle+=(float) (Math.PI/100); gear.setSportAngular(angle); invalidate(); handler.postDelayed(this,5); } }; handler .postDelayed(runnable,0);
你以为这样就ok了?那你也太小看我上班闲的程度了,接下来,我们再来点难度,不知道同学们有没有听说过一种九齿联动的指尖陀螺:
国外超火的指尖陀螺,这次是9个齿轮联动!_机械_科技_bilibili_哔哩哔哩
我们先根据规定陀螺转心的位置,画出9个齿轮的圆心:
/* 5 6 7 4 0 8 3 2 1 */ private void setFixPoints() { fixPoints .clear(); float d = (float) (diameter/Math.sqrt(2)); fixPoints.add(centerF); for (int i =1 ;i<9 ; i++ ){ float j = (i%2==0) ? d : diameter; PointF p = new PointF((float) (centerF.x+ ( j*Math.cos(sportAngular+ Math.PI*i/4))),(float) (centerF.y+j*Math.sin(sportAngular+ Math.PI*i/4))); fixPoints.add(p); } }
然后把它们画出来:
double r = diameter/Math.sqrt(2); for(int i =0;i<shell.getFixPoints().size();i++){ Gear gear = null; if (i==0){ gear = new Gear(shell.getFixPoints().get(i), (float) (r),angleV_C ,context); }else { gear = new Gear(shell.getFixPoints().get(i), (float) (r), (i%2==0) ? angleV_G : angleV_G2,context); } gears.add(gear); }
再套上外壳,关于外壳的完成,其实也是贝塞尔曲线的一种应用,请参考我的另一篇回答:
https://www. zhihu.com/question/3723 1903/answer/139438769
再加上单独齿轮旋转的效果:
最后,再把touch事件写好:
@Override
public boolean onTouchEvent(MotionEvent event){
getTracker(event);
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
startY = event.getY();
startX = event.getX();
float r = (float) (nineGearLinkage.getShell().getDiameter()/Math.sqrt(2)+nineGearLinkage.getShell().getR());
boolean a = Math.abs(centerF.x-startX)<r;
boolean a1 = Math.abs(centerF.y-startY)<r;
if(a&&a1){
isOut = false;
}else {
isOut = true;
}
dV = 0;
startThread();
sA = (float) Math.atan((startY-centerF.y)/(startX-centerF.x));
if(mTracker==null){
mTracker = VelocityTracker.obtain();
}else{
mTracker.clear();
}
mTracker.addMovement(event);
break;
case MotionEvent.ACTION_MOVE:
X = event.getX();
Y = event.getY();
mA = (float) Math.atan((Y-centerF.y)/(X-centerF.x));
if(isOut){
nineGearLinkage.setAngleV(0,mA-sA);
}else {
angle = mA-sA;
nineGearLinkage.setAngleV(angle ,0);
}
invalidate();
mTracker.addMovement(event);
mTracker.computeCurrentVelocity(1000);
break;
case MotionEvent.ACTION_UP:
float b = Math.abs(X-startX)>Math.abs(Y-startY)? (startX-X): (Y-startY);
mV = (b>0)? getSpeed(): -(getSpeed());
dV = mV;
cancelTracker();
startThread();
break;
}
return true;
}
照例,我要把源码放出来给各位同学参考:
从看见这个问题,到完成效果,我差不多花了15,6个小时,还不算我偷偷避开老板的时间,各位同学你们看到这真的忍心不赞一下吗?
其他在知乎上放的Android效果源码: