贝塞尔曲线

著名的贝塞尔曲线,确实是很美,很美。本文记录对贝塞尔曲线的点滴认识

《贝塞尔曲线》 贝塞尔曲线.gif

二次贝塞尔曲线,求最高点,反向求控制点

《贝塞尔曲线》 二次贝塞尔曲线-反向求控制点.gif

求 二次贝塞尔的 最高点

/\*\*
 \* 计算 二阶贝塞尔曲线的坐标
 \*
 \* @param t             曲线长度比例, 进度比例 [0, 1]
 \* @param startPointF   开始点
 \* @param controlPointF 控制点
 \* @param endPointF     结束点
 \* @return
 \*/
public static PointF getBezierPointF(float t, PointF startPointF, PointF endPointF, PointF controlPointF) {
    PointF pointF = new PointF(0, 0);
    float tmp = 1 - t;
    pointF.x = tmp \* tmp \* startPointF.x + 2 \* t \* tmp \* controlPointF.x + t \* t \* endPointF.x;
    pointF.y = tmp \* tmp \* startPointF.y + 2 \* t \* tmp \* controlPointF.y + t \* t \* endPointF.y;
    return pointF;
}

反向 求二次贝塞尔曲线 的控制点

/\*\*
 \* 根据 最高点,获取贝塞尔曲线的 控制点
 \*
 \* @param startPointF  开始点
 \* @param endPointF    结束点
 \* @param bezierPointF 最高点
 \* @return
 \*/
public static PointF getControlPointF(PointF startPointF, PointF endPointF, PointF bezierPointF) {
    PointF controlPointF = new PointF(0, 0);
    float tmp = 0.5F;
    float t = 0.5F;
    controlPointF.x = (bezierPointF.x - tmp \* tmp \* startPointF.x - t \* t \* endPointF.x) / (2 \* t \* tmp);
    controlPointF.y = (bezierPointF.y - tmp \* tmp \* startPointF.y - t \* t \* endPointF.y) / (2 \* t \* tmp);
    return controlPointF;
}

开始 仿 QQ“一键退朝”

《贝塞尔曲线》 贝塞尔.gif

代码,来说,没有什么好讲的,网上的教程,也是比较多的,记录一下,算法的实现过程吧。

先找到两个圆的 外切点

《贝塞尔曲线》 Paste_Image.png
《贝塞尔曲线》 Paste_Image.png

sin(γ) = (R – r) / oP0; 因为 R – r 和 原点 到 P0的距离,都是已知条件,所以根据反正弦函数,可以得出γ的大小;

因为 α + γ + 90 + β = 180;所以可以得出,β的大小;
再已知 r 和 β的大小,就可以得出 P1 的坐标,从而也能推理得出 P2, P3,P4的坐标;

找两个控制点 P5 和 P6

《贝塞尔曲线》 Paste_Image.png

所有的点,都找好了,开始画贝塞尔曲线

  1. 先将路径移到P1
    path.moveTo(stickTangent0PointF.x, stickTangent0PointF.y);
  2. 画二次贝塞尔曲线,起点是P1,控制点是P5,结束点是P2
    path.quadTo(control0PointF.x, control0PointF.y, dragTangent0PointF.x, dragTangent0PointF.y);
  3. P2到P4画一条直线
    path.lineTo(dragTangent1PointF.x, dragTangent1PointF.y);
  4. 画二次贝塞尔曲线,起点是P4,控制点事P6,结束点是P3
    path.quadTo(control1PointF.x, control1PointF.y, stickTangent1PointF.x, stickTangent1PointF.y);

此时,就算画完了,看一下镂空的效果

《贝塞尔曲线》 Paste_Image.png

先看最终的效果, 仿 QQ“一键退朝”,我该怎么做?

《贝塞尔曲线》 鼻涕虫效果.gif

先看布局文件

<org.alex.viewbadge.WrapTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="32dp"
    app:wv_backgroundColor="#FF0000"
    app:wv_dismissBoomResId="@drawable/tips_bubble"
    app:wv_shape="oval"
    app:wv_text="9"
    app:wv_textColor="#FFFFFF"
    app:wv_textSize="10sp" />

UI上怎么统一?

先在布局上展示一个 包裹内容的 文本控件, 在onTouch 的MotionEvent.ACTION_DOWN 事件,将WrapTextView隐藏掉,再把 DraggingView 添加到windowManager上,同时展示 出来,那么问题来了,WrapTextView 和 DraggingView 是两个 控件,怎么能保证效果上,长得一样呢?这时候,画控件使用的是代理模式,用CanvasHelper去控制View的绘制工作。

两个控件怎么同步状态?

我们采用观察者模式,也就是常说的接口回调,用OnDraggingStatusListener关联二者的状态

听首歌 ,放松一下 风继续吹 – 张国荣

源码地址
参考文章

http://www.jianshu.com/p/2a3167a5a811
http://www.jianshu.com/p/dce9794ed07e
http://www.jianshu.com/p/ec25be92c8fd
http://www.jianshu.com/p/6e8c06df7386
http://www.jianshu.com/p/75db5961b496
http://www.jianshu.com/p/4a022f9bb121
http://www.jianshu.com/p/6d4944d83dc2
http://www.jianshu.com/p/c0d7ad796cee
http://www.jianshu.com/p/3a57ecd949b6
http://www.jianshu.com/p/887b1ef3362d
http://www.jianshu.com/p/55c721887568
http://www.jianshu.com/p/3cb3b5370ae0
http://www.jianshu.com/p/791d3a791ec2
http://gavinliu.cn/2015/03/30/Android-Animation-%E8%B4%9D%E5%A1%9E%E5%B0%94%E6%9B%B2%E7%BA%BF%E4%B9%8B%E7%BE%8E/
http://isux.tencent.com/qq-mobile-off-duty.html
https://github.com/PoplarTang/DragGooView

    原文作者:Alex_Cin
    原文地址: https://www.jianshu.com/p/9eef2a713d33
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞