Monday, May 26, 2014

Smooth turning along path

In last example of "Animation of moving bitmap along path", the bitmap turn suddenly in turning points of the path. This example modify to have a smooth turning.


Modify AnimationView.java.
package com.example.androidanimationalongpath;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Toast;

public class AnimationView extends View {
 
 Paint paint;
 
 Bitmap bm;
 int bm_offsetX, bm_offsetY;
 
 Path animPath;
 PathMeasure pathMeasure;
 float pathLength;
 
 float step;   //distance each step
 float distance;  //distance moved
 float curX, curY;
  
 float curAngle;  //current angle
 float targetAngle; //target angle
 float stepAngle; //angle each step

 float[] pos;
 float[] tan;
 
 Matrix matrix;

 public AnimationView(Context context) {
  super(context);
  initMyView();
 }

 public AnimationView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initMyView();
 }

 public AnimationView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  initMyView();
 }
 
 public void initMyView(){
  paint = new Paint();
  paint.setColor(Color.BLUE);
  paint.setStrokeWidth(1);
  paint.setStyle(Paint.Style.STROKE);
    
  bm = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
  bm_offsetX = bm.getWidth()/2;
  bm_offsetY = bm.getHeight()/2;
  
  animPath = new Path();
  animPath.moveTo(100, 100);
  animPath.lineTo(200, 100);
  animPath.lineTo(300, 50);
  animPath.lineTo(400, 150);
  animPath.lineTo(100, 300);
  animPath.lineTo(600, 300);
  animPath.lineTo(100, 100);
  animPath.close();

  pathMeasure = new PathMeasure(animPath, false);
  pathLength = pathMeasure.getLength();
  
  Toast.makeText(getContext(), "pathLength: " + pathLength, Toast.LENGTH_LONG).show();
  
  step = 1;
  distance = 0;
  curX = 0;
  curY = 0;
  
  stepAngle = 1; 
  curAngle = 0;
  targetAngle = 0;
  
  pos = new float[2];
  tan = new float[2];
  
  matrix = new Matrix();
 }

 @Override
 protected void onDraw(Canvas canvas) {
  
  canvas.drawPath(animPath, paint);
  
  matrix.reset();
  
  if((targetAngle-curAngle)>stepAngle){
   curAngle += stepAngle;
   matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
   matrix.postTranslate(curX, curY);
   canvas.drawBitmap(bm, matrix, null);
  }else if((curAngle-targetAngle)>stepAngle){
   curAngle -= stepAngle;
   matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
   matrix.postTranslate(curX, curY);
   canvas.drawBitmap(bm, matrix, null);
  }else{
   curAngle=targetAngle;
   if(distance < pathLength){
    pathMeasure.getPosTan(distance, pos, tan);

    targetAngle = (float)(Math.atan2(tan[1], tan[0])*180.0/Math.PI);
    matrix.postRotate(curAngle, bm_offsetX, bm_offsetY);
    
    curX = pos[0]-bm_offsetX;
    curY = pos[1]-bm_offsetY;
    matrix.postTranslate(curX, curY);
    
    canvas.drawBitmap(bm, matrix, null);
    
    distance += step;
   }else{
    distance = 0;
   }
  }

  invalidate();
 }

}

Other files, MainActivity.java and /res/layout/activity_main.xml, refer last exercise.

download filesDownload the files.

More example of Drawing Path on canvas of custom View.

No comments: