利用pathMeasure实现路径动画
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实现路径动画的更多相关文章
- 探秘神奇的运动路径动画 Motion Path
CSS 中有一个非常有意思的模块 -- CSS Motion Path Module Level 1,翻译过来也就是运动路径.本文将对 motion path 一探究竟,通过本文,你可以了解到: 什么 ...
- SVG路径动画解密
原文:SVG路径动画解密 原文链接:http://www.gbtags.com/gb/share/5581.htm SVG路径动画效果现在貌似越来越多网站都使用了,给我的感觉就像是一段时间的流行而已, ...
- (数据科学学习手札85)Python+Kepler.gl轻松制作酷炫路径动画
本文示例代码.数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 Kepler.gl相信很多人都听说过,作为 ...
- DrawSVG - SVG 路径动画 jQuery 插件
jQuery DrawSVG 使用了 jQuery 内置的动画引擎实现 SVG 路径动画,用到了 stroke-dasharray 和 stroke-dashoffset 属性.DrawSVG 是完全 ...
- osg 路径 动画 效果
osg 路径 动画 效果 转自:http://blog.csdn.net/zhuyingqingfen/article/details/8248157 #include <osg/Group&g ...
- SVG的路径动画效果
使用SVG animateMotion实现的一个动画路径效果,相关代码如下. 在线调试唯一地址:http://www.gbtags.com/gb/debug/c88f4099-5056-4ad7-af ...
- ArcGIS API for Silverlight 绘制降雨路径动画
原文:ArcGIS API for Silverlight 绘制降雨路径动画 #region 降雨动画演示 2014-04-16 List<Graphic> graphics = new ...
- WPF动画之路径动画(3)
XAML代码: <Window x:Class="路径动画.MainWindow" xmlns="http://schemas.microsoft.com/winf ...
- 利用GPU实现大规模动画角色的渲染
0x00 前言 我想很多开发游戏的小伙伴都希望自己的场景内能渲染越多物体越好,甚至是能同时渲染成千上万个有自己动作的游戏角色就更好了. 但不幸的是,渲染和管理大量的游戏对象是以牺牲CPU和GPU性能为 ...
随机推荐
- 【蜂窝】at+qcfg="band"的计算和使用
查询附件 Quectel_EC25_LTE_模块产品规格书_V1.6 可知当前的蜂窝模块所对应的band频带是什么? eg.1 EC25-AU 当前选择4G 优先, FDD LTE 可看手册QCFG命 ...
- 模仿DotnetCore中间件的方式,做一个列表过滤的功能
我们的很多功能当中都会遇到对版本进行过滤的场合,例如你可能需要对列表中的数据的时间进行过滤.版本过滤.渠道以及地区信息进行过滤. 原本的做法:设计很多个过滤方法,通过枚举的方式组合,选择需要过滤哪些方 ...
- 安全学习概览——恶意软件分析、web渗透、漏洞利用和挖掘、内网渗透、IoT安全分析、区块链、黑灰产对抗
1 基础知识1.1 网络熟悉常见网络协议:https://www.ietf.org/standards/rfcs/1.2 操作系统1.3 编程2 恶意软件分析2.1 分类2.1.1 木马2.1.2 B ...
- 《AlwaysRun!》第五次作业:项目需求分析改进与系统设计
项目 内容 这个作业属于哪个课程 2016级软件工程(西北师范大学) 这个作业的要求在哪里 实验九 团队作业5—团队项目需求改进与系统设计 团队名称 Always Run! 作业学习目标 (1)掌握 ...
- 【CCF CSP】 20171203 行车路线 Java(有问题)80分
问题描述 小明和小芳出去乡村玩,小明负责开车,小芳来导航. 小芳将可能的道路分为大道和小道.大道比较好走,每走1公里小明会增加1的疲劳度.小道不好走,如果连续走小道,小明的疲劳值会快速增加,连续走s公 ...
- GitHub常用命令及使用
GitHub使用介绍 摘要: 常用命令: git init 新建一个空的仓库git status 查看状态git add . 添加文件git commit -m '注释' 提交添加的文件并备注说明gi ...
- Django REST framework+Vue 打造生鲜电商项目(笔记三)
(PS:转载自http://www.cnblogs.com/derek1184405959/p/8810591.html 有修改) 一.drf的过滤 (1)添加到app里面 INSTALLED_AP ...
- 使用Keras训练神经网络备忘录
小书匠深度学习 文章太长,放个目录: 1.优化函数的选择 2.损失函数的选择 2.2常用的损失函数 2.2自定义函数 2.1实践 2.2将损失函数自定义为网络层 3.模型的保存 3.1同时保持结构和权 ...
- UOJ 449 【集训队作业2018】喂鸽子 【生成函数,min-max容斥】
这是第100篇博客,所以肯定是要水过去的. 首先看到这种形式的东西首先min-max容斥一波,设\(f_{c,s}\)表示在\(c\)只咕咕中,经过\(s\)秒之后并没有喂饱任何一只的概率. \[ \ ...
- cas系列-自定义异常提示(五)
cas对于异常提示可以支持多语言,默认是英语,具体文件格式大同小异.这里以cas5.x版本为例. 官方推荐使用overlay方式部署,这样你只需要关注你自定义的配置即可. 获取自定义配置文件方式: 执 ...