您的位置:首页 > 大数据 > 人工智能

Paint&Canvas实现一个点(图片)在圆形(轨迹)上运动

2015-03-23 20:08 661 查看
转载请注明出处,谢谢~

这个效果其实还算简单,只是需要一些计算和猜想。首先,我的说,Android Screen Monitor实在是卡,真机不卡的,所以我描述下这个效果吧。。。

就是有一个圆,然后这个圆上有一个点,或者你可以当做是一个图片,在绕着这个圆形轨迹运动,就是这样。


画个图,丑死了。。。。

首先,这个效果的实现需要考虑以下几点:

1.圆怎么实现?

2.点(图片)怎么实现?

3.运动怎么实现?

这是最主要的三点。然后我们一一考虑。

先看圆怎么实现,这种类似运动轨迹的问题,不建议用图片实现,所以这里的圆我们用Canvas和Paint画出来:

Paint paint = new Paint();
		paint.setStyle(Paint.Style.STROKE);
		paint.setColor(Color.BLACK);
		canvas.drawCircle(px1, py1, radio, paint);


然后看点是怎么实现的,这个点是要运动的,可以选择属性动画,也可以选择重绘界面,这里我用的是重绘界面的方式,个人感觉用属性动画也能实现,不过没有实践:

Paint paint2 = new Paint();
		paint2.setStyle(Paint.Style.FILL);
		paint2.setColor(Color.WHITE);
		canvas.drawCircle(px, py,5, paint2);


第三个问题,也是最让人困扰的问题,怎么让它在这个圆上运动,考虑x,y两个方向的位移,首先实验了x和y等量变化,即x+=1,y+=1,显然,不可以,这成直线运动了。没有别的办法,写圆的一般表达式吧。(x-a)^2+(y-b)^2=r^2,这是我们高中乃至初中就知道的圆形的一般表达式,我们做个变换,(y-b)^2 = r^2 - (x-a)^2,那么我们就可以看出来,两边开根号,既得y-b的值,然后把b移过去就是y的值,那么在x值已知的情况下,我们就可以很容易的求得此时的y,这就是圆形轨迹。

if (flag == LEFT_RIGHT_DOWN) {//上半圆的运动轨迹方程
						px += 2;
						//y = b + (int) Math.sqrt(r^2 - (x - a)^2);
						if (px <= px1+radio) {
							py = py1 - (int) Math.sqrt( Math.pow(radio, 2) - Math.pow( (px - px1),2 ) );
						}else {
							px = px1 + radio;
							flag = RIGHT_LEFT_UP;
						}
					}else if (flag == RIGHT_LEFT_UP) {//下半圆的运动轨迹方程
						px -= 2;
						if (px >= px1 - radio) {
							py = py1 + (int) Math.sqrt( Math.pow(radio, 2) - Math.pow( (px - px1),2 ) );
						}else{
							px = px1 - radio;
							flag = LEFT_RIGHT_DOWN;
						}
					}


这就解决了我们期待已久的问题。然后在onDraw里重绘界面即可完成轨迹的运动。

下面将这个View的所有代码贴出,个人感觉没必要上传源码,因为在布局文件中放上它,activity中调一下start方法即可。

package com.ocean.gradualchange.paint;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import android.view.WindowManager;

public class PaintView extends View{

private int width;
private int height;
private float scale;
private float px1 = 360;
private float py1 = 540;
private float px = 360;
private float py = 340;
private float radio = 200;
private int RIGHT_LEFT_UP = 2;
private int LEFT_RIGHT_DOWN = 3;
private int flag = LEFT_RIGHT_DOWN;
private boolean isStart = false;

private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 0:
if (isStart) {
if (flag == LEFT_RIGHT_DOWN) {//上半圆的运动轨迹方程 px += 2; //y = b + (int) Math.sqrt(r^2 - (x - a)^2); if (px <= px1+radio) { py = py1 - (int) Math.sqrt( Math.pow(radio, 2) - Math.pow( (px - px1),2 ) ); }else { px = px1 + radio; flag = RIGHT_LEFT_UP; } }else if (flag == RIGHT_LEFT_UP) {//下半圆的运动轨迹方程 px -= 2; if (px >= px1 - radio) { py = py1 + (int) Math.sqrt( Math.pow(radio, 2) - Math.pow( (px - px1),2 ) ); }else{ px = px1 - radio; flag = LEFT_RIGHT_DOWN; } }
invalidate();
handler.sendEmptyMessageDelayed(0,10);
}
break;
default:
break;
}
};
};

public PaintView(Context context) {
super(context);
getWindow(context);
}

public PaintView(Context context, AttributeSet attrs) {
super(context, attrs);
getWindow(context);
}

private void getWindow(Context context) {
WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
width = manager.getDefaultDisplay().getWidth();
height = manager.getDefaultDisplay().getHeight();
scale = context.getResources().getDisplayMetrics().density;
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.BLACK); canvas.drawCircle(px1, py1, radio, paint);
// canvas.drawCircle(360, 1432-46+height-45, 1432, paint);

Paint paint2 = new Paint(); paint2.setStyle(Paint.Style.FILL); paint2.setColor(Color.WHITE); canvas.drawCircle(px, py,5, paint2);

}

private int getRadius(){
int x = width / 2;
int y1 = (int) getPX(23);
return 1143;
}

private float getPX(float dp) {
return dp * scale + 0.5f;
}

public void start() {
isStart = true;
handler.sendEmptyMessageDelayed(0, 100);
}

public void stop() {
isStart = false;
}

public boolean isStart() {
return isStart;
}
}


记得转载注明出处哦~~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: