package com.loaderman.customviewdemo;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.*;
import android.util.AttributeSet;
import android.view.View; public class GetSegmentView extends View { private Path mCirclePath, mDstPath;
private Paint mPaint;
private PathMeasure mPathMeasure;
private Float mCurAnimValue; public GetSegmentView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_SOFTWARE, null); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4);
mPaint.setColor(Color.BLACK); mDstPath = new Path();
mCirclePath = new Path();
mCirclePath.addCircle(100, 100, 50, Path.Direction.CW); mPathMeasure = new PathMeasure(mCirclePath, true); ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setRepeatCount(ValueAnimator.INFINITE);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
mCurAnimValue = (Float) animation.getAnimatedValue();
invalidate();
}
});
animator.setDuration(2000);
animator.start();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float length = mPathMeasure.getLength();
float stop = length * mCurAnimValue;
float start = (float) (stop - ((0.5 - Math.abs(mCurAnimValue - 0.5)) * length));
mDstPath.reset();
canvas.drawColor(Color.WHITE);
mPathMeasure.getSegment(start, stop, mDstPath, true);//用于截取整个path中某个片段,通过参数startD和stopD来控制截取的长度,并将截取后的path保存到参数dst中,最后一个参数表示起始点是否使用moveTo将路径的新起始点移到结果path的起始点中,通常设置为true // mPathMeasure.getSegment(0, stop, mDstPath, true);
canvas.drawPath(mDstPath, mPaint);
}
}
package com.loaderman.customviewdemo;

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.graphics.PathMeasure;
import android.util.AttributeSet;
import android.view.View; public class AliPayView extends View {
private Path mCirclePath, mDstPath;
private Paint mPaint;
private PathMeasure mPathMeasure;
private Float mCurAnimValue;
private int mCentX = 100;
private int mCentY = 100;
private int mRadius = 50; public AliPayView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_SOFTWARE, null); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4);
mPaint.setColor(Color.BLACK); mDstPath = new Path();
mCirclePath = new Path(); mCirclePath.addCircle(mCentX, mCentY, mRadius, Path.Direction.CW); mCirclePath.moveTo(mCentX - mRadius / 2, mCentY);
mCirclePath.lineTo(mCentX, mCentY + mRadius / 2);
mCirclePath.lineTo(mCentX + mRadius / 2, mCentY - mRadius / 3); mPathMeasure = new PathMeasure(mCirclePath, false); ValueAnimator animator = ValueAnimator.ofFloat(0, 2);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
mCurAnimValue = (Float) animation.getAnimatedValue();
invalidate();
}
});
animator.setDuration(4000);
animator.start();
} boolean mNext = false; @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.WHITE); if (mCurAnimValue < 1) {
float stop = mPathMeasure.getLength() * mCurAnimValue;
mPathMeasure.getSegment(0, stop, mDstPath, true);
} else {
if (!mNext) {
mNext = true;
mPathMeasure.getSegment(0, mPathMeasure.getLength(), mDstPath, true);
mPathMeasure.nextContour(); //跳转到下一条曲线函数
}
float stop = mPathMeasure.getLength() * (mCurAnimValue - 1);
mPathMeasure.getSegment(0, stop, mDstPath, true);
}
canvas.drawPath(mDstPath, mPaint);
}
}
package com.loaderman.customviewdemo;

import android.animation.ValueAnimator;
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; public class GetPosTanView extends View {
private Path mCirclePath, mDstPath;
private Paint mPaint;
private PathMeasure mPathMeasure;
private Float mCurAnimValue;
private Bitmap mArrawBmp;
private float[] pos = new float[2];
private float[] tan = new float[2]; public GetPosTanView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_SOFTWARE, null);
mArrawBmp = BitmapFactory.decodeResource(getResources(), R.drawable.arraw);
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4);
mPaint.setColor(Color.BLACK); mDstPath = new Path();
mCirclePath = new Path();
mCirclePath.addCircle(100, 100, 50, Path.Direction.CW); mPathMeasure = new PathMeasure(mCirclePath, true);//true计算的path的闭合长度,false则测量当前path状态长度 ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setRepeatCount(ValueAnimator.INFINITE);//无限循环
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
mCurAnimValue = (Float) animation.getAnimatedValue();
invalidate();
}
});
animator.setDuration(2000);
animator.start();
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); canvas.drawColor(Color.WHITE);
float length = mPathMeasure.getLength(); //计算路径长度
float stop = length * mCurAnimValue;
mDstPath.reset(); mPathMeasure.getSegment(0, stop, mDstPath, true);
canvas.drawPath(mDstPath, mPaint); /**
* 箭头旋转、位移实现方式一:
*/ //计算方位角
// mPathMeasure.getPosTan(stop, pos, tan);//用于得到路径上某一长度的位置,以及位置的证正切值
// float degrees = (float) (Math.atan2(tan[1], tan[0]) * 180.0 / Math.PI);
// Matrix matrix = new Matrix();
// matrix.postRotate(degrees, mArrawBmp.getWidth() / 2, mArrawBmp.getHeight() / 2);
// matrix.postTranslate(pos[0] - mArrawBmp.getWidth() / 2, pos[1] - mArrawBmp.getHeight() / 2); /**
* 箭头旋转、位移实现方式一:
*/
Matrix matrix = new Matrix();
mPathMeasure.getMatrix(stop, matrix, PathMeasure.POSITION_MATRIX_FLAG | PathMeasure.TANGENT_MATRIX_FLAG);//用于的到路径上某一长度的位置以及该位置的正切值的矩阵
matrix.preTranslate(-mArrawBmp.getWidth() / 2, -mArrawBmp.getHeight() / 2);
canvas.drawBitmap(mArrawBmp, matrix, mPaint);
} }
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"> <com.loaderman.customviewdemo.GetSegmentView
android:layout_width="match_parent"
android:layout_height="80dp"/>
<com.loaderman.customviewdemo.AliPayView
android:layout_width="match_parent"
android:layout_height="80dp"/>
<com.loaderman.customviewdemo.GetPosTanView
android:layout_width="match_parent"
android:layout_height="150dp"/>
</LinearLayout>

效果

利用pathMeasure实现路径动画的更多相关文章

  1. 探秘神奇的运动路径动画 Motion Path

    CSS 中有一个非常有意思的模块 -- CSS Motion Path Module Level 1,翻译过来也就是运动路径.本文将对 motion path 一探究竟,通过本文,你可以了解到: 什么 ...

  2. SVG路径动画解密

    原文:SVG路径动画解密 原文链接:http://www.gbtags.com/gb/share/5581.htm SVG路径动画效果现在貌似越来越多网站都使用了,给我的感觉就像是一段时间的流行而已, ...

  3. (数据科学学习手札85)Python+Kepler.gl轻松制作酷炫路径动画

    本文示例代码.数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 Kepler.gl相信很多人都听说过,作为 ...

  4. DrawSVG - SVG 路径动画 jQuery 插件

    jQuery DrawSVG 使用了 jQuery 内置的动画引擎实现 SVG 路径动画,用到了 stroke-dasharray 和 stroke-dashoffset 属性.DrawSVG 是完全 ...

  5. osg 路径 动画 效果

    osg 路径 动画 效果 转自:http://blog.csdn.net/zhuyingqingfen/article/details/8248157 #include <osg/Group&g ...

  6. SVG的路径动画效果

    使用SVG animateMotion实现的一个动画路径效果,相关代码如下. 在线调试唯一地址:http://www.gbtags.com/gb/debug/c88f4099-5056-4ad7-af ...

  7. ArcGIS API for Silverlight 绘制降雨路径动画

    原文:ArcGIS API for Silverlight 绘制降雨路径动画 #region 降雨动画演示 2014-04-16 List<Graphic> graphics = new ...

  8. WPF动画之路径动画(3)

    XAML代码: <Window x:Class="路径动画.MainWindow" xmlns="http://schemas.microsoft.com/winf ...

  9. 利用GPU实现大规模动画角色的渲染

    0x00 前言 我想很多开发游戏的小伙伴都希望自己的场景内能渲染越多物体越好,甚至是能同时渲染成千上万个有自己动作的游戏角色就更好了. 但不幸的是,渲染和管理大量的游戏对象是以牺牲CPU和GPU性能为 ...

随机推荐

  1. Python-共享引用

    A会改变么? 下面三小段代码,A的值都会改变么? >>> A = "spam" >>> B = A >>> B = " ...

  2. windows cmd命令学习

    tasklist|findstr "py"

  3. Linux中条件语句

    Linux中备份一个jar包,需要既判断进程是否停止,又判断文件是否存在 1. 进程停了,文件存在则备份 2.进程停了,文件不存在,无需备份 3. 进程在跑,停止进程:文件存在,将文件进行备份 4. ...

  4. Jenkins配置文件

    https://github.com/zeyangli/Jenkins-docs 在Linux上的Jenkins 以rpm方式部署的配置文件在/etc/sysconfig/jenkins,可以定义Je ...

  5. 别人家的java语言编写的自动化测试系统

    https://gitee.com/testdevops/easyrest 但是我还不会用 ~~~~(>_<)~~~~ 目前的状况是:大概知道流程了,可是第一个用例就跑步起来 自己想写一些 ...

  6. es其他常用功能

    es6除了模块化,class,promise,还有一些其他的常用功能. 1.let/const let是定义一个变量,但是这个变量可以重新赋值,const是定义一个常量,这个常量不能重新赋值 let ...

  7. Airtest---UI自动化测试项目

    Airtest Project是网易游戏团队新开源出来的一款用于UI自动化测试的项目. testerhome中的文档介绍:https://testerhome.com/topics/12486 官方链 ...

  8. Mybatis接口中传递多个参数

    1.接口 public interface MemberMapper { public boolean insertMember(Members member); public Members sel ...

  9. 除了不要 SELECT * ,程序员使用数据库还应知道的11个技巧

    SQL:sum里加条件SELECT SUM( CASE WHEN "V7010" BETWEEN 0 AND 0.1 THEN 1 ELSE 0 END) FROM "C ...

  10. vue 组件高级用法(递归组件,内联模板,动态组件,异步组件)