著名的贝塞尔曲线,确实是很美,很美。本文记录对贝塞尔曲线的点滴认识
二次贝塞尔曲线,求最高点,反向求控制点
求 二次贝塞尔的 最高点
<pre>
/**
* 计算 二阶贝塞尔曲线的坐标
*
* @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;
}
</pre>
反向 求二次贝塞尔曲线 的控制点
<pre>
/**
* 根据 最高点,获取贝塞尔曲线的 控制点
*
* @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;
}
</pre>
开始 仿 QQ“一键退朝”
代码,来说,没有什么好讲的,网上的教程,也是比较多的,记录一下,算法的实现过程吧。
先找到两个圆的 外切点
sin(γ) = (R - r) / oP0; 因为 R - r 和 原点 到 P0的距离,都是已知条件,所以根据反正弦函数,可以得出γ的大小;
因为 α + γ + 90 + β = 180;所以可以得出,β的大小;
再已知 r 和 β的大小,就可以得出 P1 的坐标,从而也能推理得出 P2, P3,P4的坐标;
找两个控制点 P5 和 P6
所有的点,都找好了,开始画贝塞尔曲线
- 先将路径移到P1
path.moveTo(stickTangent0PointF.x, stickTangent0PointF.y); - 画二次贝塞尔曲线,起点是P1,控制点是P5,结束点是P2
path.quadTo(control0PointF.x, control0PointF.y, dragTangent0PointF.x, dragTangent0PointF.y); - P2到P4画一条直线
path.lineTo(dragTangent1PointF.x, dragTangent1PointF.y); - 画二次贝塞尔曲线,起点是P4,控制点事P6,结束点是P3
path.quadTo(control1PointF.x, control1PointF.y, stickTangent1PointF.x, stickTangent1PointF.y);
此时,就算画完了,看一下镂空的效果
先看最终的效果, 仿 QQ“一键退朝”,我该怎么做?
先看布局文件
<pre>
<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" />
</pre>
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