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. KVM虚拟化——简介

    KVM 基于内核的虚拟机KVM(Kernel-Based Virtual Machine)是2007年问世的开源虚拟化解决方案.KVM需要两个条件: ①硬件支持全虚拟化 ②操作系统为Linux KVM ...

  2. 模板引擎-vue中的模板如何被解析,指令如何处理

    模板是什么 <div id='app'> <div> <input v-model="title"/> <button v-on:clic ...

  3. P1282 多米诺骨牌[可行性01背包]

    题目来源:洛谷 题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+ ...

  4. AJAX学习笔记——JSON

    JSON基本概念 1.JSON : JavaScript对象表示法( JavaScript Object Notation ) 2.JSON是存储和交换文本信息的语法,类似XML.它采用键值对的方式来 ...

  5. DTcmsV4.0分析学习——(1)数据库结构分析

    数据库名:DTcmsdb4 DTcmsV4.0共35张表(33张表+2张插件表) dt_article 内容管理 dt_article_albums 图片相册 dt_article_attach 附件 ...

  6. 用Thymeleaf在实际项目中遇到的坑

    最近搭建了基于的springboot的新项目,抛弃了jsp,使用了官方推荐的Thymeleaf(怎么读?[taim][li:f])模板,在实际开发遇到了很多的坑,等项目告一段落,我再一一记录一下,有交 ...

  7. js实现图片上传实时显示

    在开发的时候经常遇到这样的需求,用户在上传图片的时候,想要看到自己上传的图片是否正确,这时候需要把用户上传的图片及时显示出来,然后等他点击上传的时候,程序再执行上传到服务器. <!DOCTYPE ...

  8. [Functional Programming] Rewrite a reducer with functional state ADT

    For example we have a feature reducer like this: // selectCard :: String -> Action String export ...

  9. [Angular 8] Calculate and Measure Performance budgets with the Angular CLI

    Measuring is extremely important, without numbers we don’t know about potential problems and we don’ ...

  10. [GraphQL] Set variable and default value & alias

    query($category:PetCategory=CAT, $status:PetStatus=AVAILABLE) { #availablePets is the alias availabl ...