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. spark-submit之使用pyspark

    在linux下,执行pyspark代码 —— 实测有效:但是并不是所有的包都能够成功,一些很复杂的包或者对C依赖很深的包例如 numpy, pandas, scipy等,无法通过本方法实现:对一些比较 ...

  2. vue-cli3项目搭建配置以及性能优化

    项目初始化 注意:安装前请确保有安装node.js,并且node>=8.9 全局安装vue npm install -g @vue/cli 如果之前安装了vue旧版本,查看vue --versi ...

  3. HTML5 服务器发送事件(Server-Sent Events)

    沈阳SEO:HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新. Server-Sent 事件 - 单向消息传递 Server-Sent 事件指的是网页自动获 ...

  4. Time Intersection

    Description Give two users' ordered online time series, and each section records the user's login ti ...

  5. location对象方法(assign()、reload()、replace())

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. TDOA 之 基站接收数据

    基站主要 接收同步节点发来的同步信号,代码里定义为S信息. 以及标签节点发来的定位信号,代码中定义为T信号. 代码中使用中断以及帧过滤功能,对模块只接收自己关心设定好的信息,通过中断告知上层,而不是长 ...

  7. HTML 006 文本格式化(了解)

    HTML 文本格式化 HTML 文本格式化 加粗文本 斜体文本 电脑自动输出 这是 下标 和 上标 尝试一下 » HTML 格式化标签 HTML 使用标签 <b>("bold&q ...

  8. sql server 存储过程---游标的循环

    sqlserver中的循环遍历(普通循环和游标循环) sql 经常用到循环,下面介绍一下普通循环和游标循环 1.首先需要一个测试表数据Student

  9. myeclipse不同版本共存破解办法

    我自己破解的是myeclipse10+myeclipse2018: 方法是:先破解myeclipse10.7,使用破解工具,到最后一步不关闭破解工具,再进行替换文件那一步,路径不选择10版本的,换成M ...

  10. 在mysql中用int类型存储IP

    SELECT INET_ATON( '127.0.0.1' ); SELECT INET_NTOA();