前言内容
以前通过自定义view可以绘制出各种效果,但这些效果多数还是存在于规则的图像,今天学习贝塞尔曲线,来绘制一些更特别的线条。
简单来说贝塞尔曲线通过控制点,可以绘制出各种路径。一般我们常用的二阶贝塞尔和三阶贝塞尔(对应的控制点数量不同)。这也是Android提供给我们的方法。
网上介绍的资料很多,可以全面了解下。下面我用二阶贝塞尔曲线绘制一个正弦曲线,然后在让曲线动起来,来模仿波浪吧。
内容部分
代码超级少,先从原理来简单分析下我们要做什么。
-
最重要的是计算绘制路线的点的集合,这里我们需要确定波开始的位置,和波峰波谷高度,还有就是波长
下面隐藏波长只是为了,移动的时候看起来是连续的。
注意:
一个连续的波需要四个点来完成。最后一个波说五个点,然后因为需要移动所以我们多加了一个波。所以公式是 4*n+5,这里的n是波峰,一个完整的波由一个波峰和一个波谷组成。
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) if (!isMeasured) { isMeasured = true viewWidth = measuredWidth viewHeight = measuredHeight //底部开始 mStartPoint = measuredHeight.toFloat() / 2 //波峰高度 mCrestHeight = viewHeight / 15f //波峰长度 mCrestWidth = measuredWidth / 2 //隐藏一个波长 mLeftHide = -mCrestWidth.toFloat() //几个波峰 val n = (viewWidth / mCrestWidth + 0.5).roundToInt() for (i in 0..n * 4 + 4) { //x坐标开始的位置为负的一个波长开始 var x = (i * mCrestWidth / 4).toFloat() - mCrestWidth var y = 0f when (i % 4) { 0, 2 -> y = mStartPoint 1 -> y = mStartPoint + mCrestHeight 3 -> y = mStartPoint - mCrestHeight } pointList.add(Point(x, y)) } } }
-
拿到运动的点的集合后就是绘制,这里需要调用quadTo方法传入两个点。然后是让绘制好曲线平移就可以看到波浪的效果了(很多动画效果都是通过改变view的坐标完成,特别是页面动画效果很多的时候)。
这里是绘制一个path,主要是顶部是一个波浪的形状。
注意:
- 每两个点就绘制出一个半个正弦图了。所以循环是两个点为一组开始的
- 然后绘制完成后要闭合找个path
- 发送消息不断移动x的数值,就可以动起来了
override fun onDraw(canvas: Canvas?) { mRipplePath.reset() mRipplePath.moveTo(pointList[0].x, pointList[0].y) Log.d("RippleView", pointList.size.toString()) for (i in 0..(pointList.size - 3) step 2) { Log.d("RippleView", i.toString()) mRipplePath.quadTo(pointList[i + 1].x, pointList[i + 1].y, pointList[i + 2].x, pointList[i + 2].y) } mRipplePath.lineTo(pointList.get(pointList.size - 1).getX(), viewHeight.toFloat()) mRipplePath.lineTo(mLeftHide, viewHeight.toFloat()) mRipplePath.close() canvas!!.drawPath(mRipplePath, mPaint) mHandler.sendEmptyMessageDelayed(1, 10) }
总的来说就是上面两个步骤。
其实没什么内容,因为很简单。
结束部分
Android内容有点多,总之还是学点是点吧。各位加油