android 贝塞尔曲线画脸
一个简单的例子,效果就是从一张笑脸过渡到一张哭脸 :) -> :(
package com.android.facelove;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by ding_qili on 15/10/20.
*/
public class FaceView extends View {
public FaceView(Context context) {
super(context);
init();
}
public FaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FaceView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawFace(canvas);
drawEyes(canvas);
drawMouth(canvas);
signature(canvas);
}
private void init(){
path = new Path();
paint = new Paint();
paint.setColor(Color.BLACK);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
}
private Path path;
private Paint paint;
private static final int FaceSize = 150;
private static final int EyeSize = 50;
private static final int MouthSize = 70;
private final int smileeyeBézier = 20;
private final int smilemouthBézier = 30;
private final int unhappyeyeBézier = 0;
private final int unhappymouthBézier = -30;
private int curreyeBézier =unhappyeyeBézier;
private int currmouthBézier =unhappymouthBézier;
private ObjectAnimator eyeanim;
private ObjectAnimator mouthanim;
//画脸
private void drawFace(Canvas canvas){
paint.setStrokeWidth(2.0f);
canvas.drawCircle(canvas.getWidth()/2, canvas.getHeight()/2, FaceSize, paint);// 脸
}
//画眼睛
private void drawEyes(Canvas canvas){
drawLeftEye(canvas);
drawRightEye(canvas);
}
private void drawLeftEye(Canvas canvas){
paint.setStrokeWidth(1.0f);
path.reset();// 重置path
int x = canvas.getWidth()/2-FaceSize/2;
int y = canvas.getHeight()/2;
path.moveTo(x-EyeSize/2,y);
// 设置贝赛尔曲线的操作点以及终止点
path.quadTo(x, y-curreyeBézier, x+EyeSize/2, y);
// 绘制贝赛尔曲线(Path)
canvas.drawPath(path, paint);
}
private void drawRightEye(Canvas canvas){
paint.setStrokeWidth(1.0f);
path.reset();// 重置path
int x = canvas.getWidth()/2+FaceSize/2;
int y = canvas.getHeight()/2;
path.moveTo(x-EyeSize/2,y);
// 设置贝赛尔曲线的操作点以及终止点
path.quadTo(x, y-curreyeBézier, x+EyeSize/2, y);
// 绘制贝赛尔曲线(Path)
canvas.drawPath(path, paint);
}
//画嘴巴
private void drawMouth(Canvas canvas){
paint.setStrokeWidth(1.0f);
path.reset();// 重置path
int x = canvas.getWidth()/2;
int y = canvas.getHeight()/2+FaceSize/2;
path.moveTo(x-MouthSize/2,y);
// 设置贝赛尔曲线的操作点以及终止点
path.quadTo(x, y+currmouthBézier, x+EyeSize/2, y);
// 绘制贝赛尔曲线(Path)
canvas.drawPath(path, paint);
}
private void signature(Canvas canvas){
paint.setUnderlineText(true);
paint.setTextSize(30);
canvas.drawText("ding_qili", 50, 50, paint);// 画文本
paint.setUnderlineText(false);
}
public void smileAnimRun()
{
if(eyeanim !=null){
eyeanim.cancel();
}
if(mouthanim !=null){
mouthanim.cancel();
}
eyeanim = ObjectAnimator//
.ofFloat(this, "smileEye", curreyeBézier, smileeyeBézier)//
.setDuration(500);//
eyeanim.start();
eyeanim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float currmouthBézierF = (Float)animation.getAnimatedValue();
curreyeBézier = (int) currmouthBézierF;
FaceView.this.invalidate();
}
});
mouthanim = ObjectAnimator//
.ofFloat(this, "mouthEye", currmouthBézier, smilemouthBézier)//
.setDuration(500);//
mouthanim.start();
mouthanim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float currmouthBézierF = (Float)animation.getAnimatedValue();
currmouthBézier = (int) currmouthBézierF;
FaceView.this.invalidate();
}
});
}
public void unHappyAnimRun()
{
if(eyeanim !=null){
eyeanim.cancel();
}
if(mouthanim !=null){
mouthanim.cancel();
}
eyeanim = ObjectAnimator//
.ofFloat(this, "smileEye", curreyeBézier, unhappyeyeBézier)//
.setDuration(500);//
eyeanim.start();
eyeanim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float currmouthBézierF = (Float)animation.getAnimatedValue();
curreyeBézier = (int) currmouthBézierF;
FaceView.this.invalidate();
}
});
mouthanim = ObjectAnimator//
.ofFloat(this, "mouthEye", currmouthBézier, unhappymouthBézier)//
.setDuration(500);//
mouthanim.start();
mouthanim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
@Override
public void onAnimationUpdate(ValueAnimator animation)
{
float currmouthBézierF = (Float)animation.getAnimatedValue();
currmouthBézier = (int) currmouthBézierF;
FaceView.this.invalidate();
}
});
}
}