转换成java代码如下

float tagX = (float) (Math.sin(Math.toRadians(60)) * mRadius
/ Math.cos(Math.toRadians(30 - swipeAgenl))

  • Math.sin(Math.toRadians(60 - swipeAgenl)));

float tagY = (float) (Math.sin(Math.toRadians(60)) * mRadius
/ Math.cos(Math.toRadians(30 - swipeAgenl))

  • Math.cos(Math.toRadians(60 - swipeAgenl))) - mRadius;

运行看下效果是不是符合预期

4.圆弧

点(0,-R)到(√3/2/R,R/2)点与圆相交处会有个圆弧。这里利用Path.addArc或者canvas.drawArc方法都可以绘制。所传参方式有两种,其实本质都是传入一个矩形然后在矩形框内绘制一个圆弧。

Path.java
public void addArc(RectF oval, float startAngle, float sweepAngle) {
addArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle);
}
Canvas.java
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint) {
drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
paint);
}

startAngle 为开始的角度,sweepAngle为圆弧滑过的角度。代码如下:

RectF oval = new RectF(-mRadius, -mRadius, mRadius, mRadius);
mPaint.setStyle(Paint.Style.FILL);
path.addArc(oval, -90, 60);

5.看看效果

画出了一个,那么6个就很好画,为了方面观察效果,我把每个都整成了不同颜色,方便大家看。

咦,不对劲呀,和我预想的不一样。我们可以再看看UI做的效果图。抛开图形旋转角度的因素,可以观察到,图形是随着时间的变化,红色边线一直拉长而形成的。最大长度是R,最小长度是0,或者你设置任意初始值,还有一点要注意,在红线延伸的过程中,夹角始终是60度。

6.重新计算

依旧是正弦函数,余弦函数,算出点在红线上的位置。

float L1 = (float) Math.sqrt(Math.pow(mRadius, 2.0) -
Math.pow(Math.sin(Math.toRadians(60)) * a, 2.0));

float consL1 = L1 / mRadius;
float sinL1 = (float) Math.sin(Math.toRadians(60)) * a / mRadius;
float L = (float) (L1 + Math.sin(Math.toRadians(30)) * a);

float tagX = L * sinL;
float tagY = L * consL - mRadius;

7.大功告成

/**

  • @authoer create by markfrain
  • @github https://github.com/furuiCQ
  • 高怀见物理 和气得天真
  • 时间: 4/28/21
  • 描述: ShootView
    */
    public class ShootView extends View {
    private static final int DEGREE_60 = 60;

private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
private final RectF mBounds = new RectF();
private int mRadius;
private int mCenterX;
private int mCenterY;

private ValueAnimator mPlayAnimator;
private float swipeAgenl = mRadius;//延伸的距离

private float mShootLineTotalRotateAngle;//旋转角度
private ValueAnimator mPreShootLineTotalRotateAnimator;

private float padding = 20;
private ValueAnimator paddingAnimator;

private float fix = 4;
private ValueAnimator fixAnimator;

private static final float SHOOT_LINE_ROTATE_END_RADIANS = (float) (Math.PI / 6.0);//旋转结束弧度
private static final float SHOOT_LINE_ROTATE_START_RADIANS = (float) (Math.PI / 2.0);//旋转开始弧度
private static final float SHOOT_LINE_ROTATE_START_DEGREE =
(float) Math.toDegrees(SHOOT_LINE_ROTATE_END_RADIANS);//旋转开始角度
private static final int PRE_SHOOT_LINE_TOTAL_ROTATE_DURATION = 1000;

public static final Property<ShootView, Float> SHOOT_LINE_TOTAL_ROTATE_DEGREE =
new Property<ShootView, Float>(Float.class, null) {
@Override
public Float get(ShootView object) {
return object.mShootLineTotalRotateAngle;
}

@Override
public void set(ShootView object, Float value) {
object.mShootLineTotalRotateAngle = value;
object.invalidate();
}
};

public ShootView(Context context) {
this(context, null);
}

public ShootView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}

public ShootView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.parseColor(“#ffc6c6c6”));

paddingAnimator = ValueAnimator.ofFloat(20, 0);
paddingAnimator.setInterpolator(new LinearInterpolator());
paddingAnimator.setDuration(PRE_SHOOT_LINE_TOTAL_ROTATE_DURATION);
paddingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
padding = (float) animation.getAnimatedValue();
invalidate();
}
});
fixAnimator = ValueAnimator.ofFloat(4, 0);
fixAnimator.setInterpolator(new LinearInterpolator());
fixAnimator.setDuration(1200);
fixAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
fix = (float) animation.getAnimatedValue();
invalidate();
}
});

mPreShootLineTotalRotateAnimator =
ValueAnimator.ofFloat(-(SHOOT_LINE_ROTATE_START_DEGREE / 2.0f) - 240.0f,
-(SHOOT_LINE_ROTATE_START_DEGREE / 2.0f) - 120.0f);
mPreShootLineTotalRotateAnimator.setInterpolator(new LinearInterpolator());
mPreShootLineTotalRotateAnimator.setDuration(PRE_SHOOT_LINE_TOTAL_ROTATE_DURATION);
mPreShootLineTotalRotateAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mShootLineTotalRotateAngle = (float) animation.getAnimatedValue();
invalidate();
}
});
}

@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);

// drawTest(canvas);
drawArc(canvas);
drawCircle(canvas);

}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBounds.set(0 + getPaddingLeft(), 0 + getPaddingTop(), w - getPaddingRight(),
h - getPaddingBottom());

mRadius = (int) (Math.min(mBounds.width(), mBounds.height()) / 2);
mCenterX = (int) mBounds.centerX();
mCenterY = (int) mBounds.centerY();
swipeAgenl = mRadius * 2 / 3f;
}

float mStartX;
float mStartY 《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》无偿开源 徽信搜索公众号【编程进阶路】 ;

int colors[] = {Color.RED, Color.GREEN, Color.YELLOW, Color.MAGENTA, Color.CYAN, Color.GRAY};

private void drawTest(Canvas canvas) {
drawCircle(canvas);
canvas.save();
canvas.translate(mCenterX, mCenterY);

int i = 0;
canvas.save();
canvas.rotate(-DEGREE_60 * i);
Path path = new Path();

float stopX = (float) Math.sqrt(3) * mRadius / 2f;
float stopY = -mRadius / 2f;

canvas.drawLine(0, -mRadius, stopX, stopY, mPaint);
mPaint.setColor(Color.RED);
canvas.drawPoint(stopX, stopY, mPaint);
mPaint.setColor(Color.RED);

//canvas.drawLine(0, 0, stopX, stopY, mPaint);

RectF oval = new RectF(-mRadius, -mRadius, mRadius, mRadius);

RectF rectF = new RectF(-mRadius, -2 * mRadius, mRadius, 0);

mPaint.setStyle(Paint.Style.FILL);
path.addArc(oval, -90, 60);

//计算直接点的
float tagX = (float) (Math.sin(Math.toRadians(60)) * mRadius / Math.cos(Math.toRadians(30 - swipeAgenl)) * Math.sin(Math.toRadians(60 - swipeAgenl)));
float tagY = (float) (Math.sin(Math.toRadians(60)) * mRadius / Math.cos(Math.toRadians(30 - swipeAgenl)) * Math.cos(Math.toRadians(60 - swipeAgenl))) - mRadius;

// float tagX = Math.sqrt(Math.pow(mRadius,2.0) - Math.pow(Math.sin(Math.toRadians(60) * swipeAgenl), 2.0));

// float L = (float) Math.sqrt(Math.pow(mRadius, 2.0) - Math.pow(Math.sin(Math.toRadians(60)) * swipeAgenl, 2.0));
/ float tagX = Math.sqrt(Math.pow(mRadius,2.0) - Math.pow(Math.sin(Math.toRadians(60) * swipeAgenl), 2.0));

// float L = (float) Math.sqrt(Math.pow(mRadius, 2.0) - Math.pow(Math.sin(Math.toRadians(60)) * swipeAgenl, 2.0));

【BYM】Android 实现相机快门动画相关推荐

  1. 【BYM】Android 实现相机快门动画,android音视频何俊林

    c.推导公式求解x和y. 辅助线我就不画了,我直接给出推导公式 转换成java代码如下 float tagX = (float) (Math.sin(Math.toRadians(60)) * mRa ...

  2. 【BYM】Android 实现相机快门动画,hashmap底层实现原理

    6.重新计算 依旧是正弦函数,余弦函数,算出点在红线上的位置. float L1 = (float) Math.sqrt(Math.pow(mRadius, 2.0) - Math.pow(Math. ...

  3. Flutter的移动端相机快门动画封装

    Camera Aperture animation for mobile by Flutter Created by Alfonso Cejudo, Saturday, July 13th 2019. ...

  4. 相机快门_向我的智能手机添加远程相机快门的最简单方法是什么?

    相机快门 As smartphone cameras get better and better it's only natural that people would want to enjoy s ...

  5. Android自定义相机

    转载请指明出处@https://blog.csdn.net/qq_41912447 版权归博主所有 /** **本文由自己搜集资料编程 如有错误请指明 **李紫洋著 */ 导引 相机成为了一个app必 ...

  6. 详记Android打开相机拍照流程

    写在前面 本文并不是基于Camera2的,所以想要了解Camera2的同学可以先散了.文题加了详记二字,因为相机整个打开的流程的确是比较复杂的,稍有疏忽可能就会引发一系列问题.我也是看了一下Andro ...

  7. Android调用相机与相册的方法

    Android调用相机与相册的方法 操作流程 点击拍摄 效果图 点击相册选择 效果图 拒绝权限的情况 效果图 功能实现 项目配置 1.先在项目根目录的build.gradle的repositories ...

  8. Android自定义相机拍照、图片裁剪的实现

    原文:Android自定义相机拍照.图片裁剪的实现 最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类 ...

  9. 酷!使用 jQuery Canvas 制作相机快门效果

    在今天的教程中,我们将使用 HTML5 的 Canvas 元素来创建一个简单的摄影作品集,它显示了一组精选照片与相机快门的效果.此功能会以一个简单的 jQuery 插件形式使用,你可以很容易地整合到任 ...

最新文章

  1. ef mysql 插件_EF Core 插件 —— ToSql
  2. Echarts柱状图顶部加数量显示
  3. C++动态数组(转)
  4. 十二月份找工作好找吗_注会过两门好找工作吗?好找
  5. 华为4g无线路由器虚拟服务器设置方法,华为4g2pro路由器虚拟服务器设置
  6. TI DSP simulator 种类选择
  7. 更快学习 JavaScript的6个思维技巧
  8. bootstrap table中文文档_用Python完成一件小事:自动生成文档报告
  9. MYSQL 主从复制读写分离实现
  10. npm 包管理器的使用
  11. 【TSP】基于matlab GUI遗传算法求解旅行商问题【含Matlab源码 1333期】
  12. ORCLE conn连接报错
  13. 算法:Merge k Sorted Lists(合并 k 个排序链表)
  14. 全自动抠图换背景软件下载_抠图换背景的证件照软件
  15. 电路串联和并联图解_怎样画串联和并联电路图
  16. 【STM32H7的DSP教程】第12章 DSP基础函数-相反数,偏移,移位,减法和比例因子
  17. 获取海拔高度. 实时气压
  18. Redis基础篇(万丈高楼平地起):核心底层数据结构
  19. XShell下载安装及使用(免费版)
  20. 如何使用OBS开启直播

热门文章

  1. type-c接口边充电边听歌解决方案
  2. 主流手持设备以及芯片
  3. Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255]
  4. 大牛建议——C++学习建议
  5. 控制电机及应用课程简单总结
  6. 精准引流怎么推广:免费的引流推广营销技巧
  7. C++ 游戏开发(二)见缝插针小游戏
  8. NOIP练习赛题目1
  9. 全球及中国云视频会议解决方案行业研究及十四五规划分析报告
  10. 游戏玩家的计算机配置,游戏玩家的PC都爱用什么配置?Steam十一月硬件调查数据告诉你...