贝塞尔曲线
贝塞尔曲线的几个步骤
1、起始点
2、控制点
3、控制点
4、结束点
为了大家更好地理解这几个概念,附上下图
嗯,我们开始实现沙漏曲线
1、我们看一下,实现的最终的效果图
2、我们分析一下:起始点、控制点、结束点的位置
3、代码实现
我们把 沙漏 的整体部分,分为四部分:
1、上、左部分
2、上、右部分
3、下、左部分
4、下、右部分
各部分的实现原理都相同,实现了其中一个,其余部分也轻而易举的实现出来。
▲上、左部分的实现:
核心代码:
//Top left
Path glassArcPathTopLeft = new Path();
glassArcPathTopLeft.moveTo(hourglassArcStartedPointLeftBound, hourglassArcStartedPointTopBound);
glassArcPathTopLeft.cubicTo(hourglassArcOneControlPoint.x, hourglassArcOneControlPoint.y, hourglassArcTwoControlPoint.x, hourglassArcTwoControlPoint.y, hourglassCenterX, hourglassCenterY);
canvas.drawPath(glassArcPathTopLeft , mHourglassArcPaint);
1、Path.moveTo(startPointX, startPointY);
【startPointX, 起始点的X坐标,startPointY,起始点的Y坐标】
2、Path.cubicTo(controlOnePointX, controlOnePointY, controlTwoPointX, controlTwoPointY, endPointX, endPointY);
【控制点1的X坐标,控制点1的Y坐标,控制点2的X坐标,控制点2的Y坐标,结束点的X坐标,结束点的Y坐标】
3、Canvas.drawPath(Path, Paint);
【绘制】
3.2、全部代码
在开发中我们还要考虑到,padding,wrap_content等诸多情况
下面是全部的绘制核心代码
private void drawGlass(Canvas canvas) {
/*
Canvas rectangle.
*/
int drawableLeftBound = getLeft() + getPaddingLeft();
int drawableTopBound = getTop() + getPaddingTop();
int drawableRightBound = getRight() - getPaddingRight();
int drawableBottomBound = getBottom() - getPaddingBottom();
/*
Save drawable rectangle layer.
*/
RectF rectF = new RectF();
rectF.left = drawableLeftBound;
rectF.top = drawableTopBound;
rectF.right = drawableRightBound;
rectF.bottom = drawableBottomBound;
canvas.saveLayerAlpha(rectF, 200);
float drawableDiameterY = (rectF.bottom - rectF.top);
float drawableRadiusY = drawableDiameterY / 2f;
float drawableDiameterX = (rectF.right - rectF.left);
float drawableRadiusX = drawableDiameterX / 2f;
/*
中心位置
*/
float hourglassCenterX = rectF.left + drawableRadiusX;
float hourglassCenterY = rectF.top + drawableRadiusY;
/*
Bounds
*/
float hourglassLeftBound = rectF.left + mHourglassPaintWidth;
float hourglassTopBound = rectF.top + mHourglassPaintWidth;
float hourglassRightBound = rectF.right + mHourglassPaintWidth;
float hourglassBottomBound = rectF.bottom + mHourglassPaintWidth;
//Arc started bounds.
float hourglassArcStartedPointLeftBound = rectF.left + drawableDiameterY / 8f;
float hourglassArcStartedPointTopBound = rectF.top;
float hourglassArcStartedPointRightBound = rectF.right - drawableDiameterY / 8f;
float hourglassArcStartedPointBottomBound = rectF.bottom;
/*
Eight control point
*/
PointF hourglassArcOneControlPoint = new PointF();
hourglassArcOneControlPoint.x = hourglassLeftBound;
hourglassArcOneControlPoint.y = drawableTopBound + drawableRadiusY / 4F;
PointF hourglassArcTwoControlPoint = new PointF();
hourglassArcTwoControlPoint.x = hourglassLeftBound;
hourglassArcTwoControlPoint.y = drawableTopBound + drawableRadiusY / 2F;
PointF hourglassArcThreeControlPoint = new PointF();
hourglassArcThreeControlPoint.x = hourglassRightBound;
hourglassArcThreeControlPoint.y = drawableTopBound + drawableRadiusY / 4F;
PointF hourglassArcFourControlPoint = new PointF();
hourglassArcFourControlPoint.x = hourglassRightBound;
hourglassArcFourControlPoint.y = drawableTopBound + drawableRadiusY / 2F;
PointF hourglassArcFiveControlPoint = new PointF();
hourglassArcFiveControlPoint.x = hourglassLeftBound;
hourglassArcFiveControlPoint.y = drawableBottomBound - drawableRadiusY / 4F;
PointF hourglassArcSixControlPoint = new PointF();
hourglassArcSixControlPoint.x = hourglassLeftBound;
hourglassArcSixControlPoint.y = drawableBottomBound - drawableRadiusY / 2F;
PointF hourglassArcSevenControlPoint = new PointF();
hourglassArcSevenControlPoint.x = hourglassRightBound;
hourglassArcSevenControlPoint.y = drawableBottomBound - drawableRadiusY / 4F;
PointF hourglassArcEightControlPoint = new PointF();
hourglassArcEightControlPoint.x = hourglassRightBound;
hourglassArcEightControlPoint.y = drawableBottomBound - drawableRadiusY / 2F;
Paint paint = new Paint();
paint.setStrokeWidth(15);
paint.setColor(Color.GREEN);
canvas.drawPoint(hourglassArcOneControlPoint.x, hourglassArcOneControlPoint.y, paint);
canvas.drawPoint(hourglassArcTwoControlPoint.x, hourglassArcTwoControlPoint.y, paint);
canvas.drawPoint(hourglassArcThreeControlPoint.x, hourglassArcThreeControlPoint.y, paint);
canvas.drawPoint(hourglassArcFourControlPoint.x, hourglassArcFourControlPoint.y, paint);
canvas.drawPoint(hourglassArcFiveControlPoint.x, hourglassArcFiveControlPoint.y, paint);
canvas.drawPoint(hourglassArcSixControlPoint.x, hourglassArcSixControlPoint.y, paint);
canvas.drawPoint(hourglassArcSevenControlPoint.x, hourglassArcSevenControlPoint.y, paint);
canvas.drawPoint(hourglassArcEightControlPoint.x, hourglassArcEightControlPoint.y, paint);
/*
Glass top.
*/
//Top left
Path glassArcPathTopLeft = new Path();
glassArcPathTopLeft.moveTo(hourglassArcStartedPointLeftBound, hourglassArcStartedPointTopBound);
glassArcPathTopLeft.cubicTo(hourglassArcOneControlPoint.x, hourglassArcOneControlPoint.y, hourglassArcTwoControlPoint.x, hourglassArcTwoControlPoint.y, hourglassCenterX, hourglassCenterY);
Path glassArcPathTopCenter = new Path();
glassArcPathTopCenter.moveTo(getRight() / 8f, getTop());
glassArcPathTopCenter.lineTo(hourglassRightBound - getRight() / 8f, getTop());
glassArcPathTopCenter.lineTo(hourglassCenterX, hourglassCenterY);
//Top right.
Path glassArcPathTopRight = new Path();
glassArcPathTopRight.moveTo(hourglassArcStartedPointRightBound, hourglassArcStartedPointTopBound);
glassArcPathTopRight.cubicTo(hourglassArcThreeControlPoint.x, hourglassArcThreeControlPoint.y, hourglassArcFourControlPoint.x, hourglassArcFourControlPoint.y, hourglassCenterX, hourglassCenterY);
/*
Glass bottom.
*/
//Bottom left.
Path glassArcPathBottomLeft = new Path();
glassArcPathBottomLeft.moveTo(hourglassArcStartedPointLeftBound, hourglassArcStartedPointBottomBound);
glassArcPathBottomLeft.cubicTo(hourglassArcFiveControlPoint.x, hourglassArcFiveControlPoint.y, hourglassArcSixControlPoint.x, hourglassArcSixControlPoint.y, hourglassCenterX, hourglassCenterY);
//Bottom right.
Path glassArcPathBottomRight = new Path();
glassArcPathBottomRight.moveTo(hourglassArcStartedPointRightBound, hourglassArcStartedPointBottomBound);
glassArcPathBottomRight.cubicTo(hourglassArcSevenControlPoint.x, hourglassArcSevenControlPoint.y, hourglassArcEightControlPoint.x, hourglassArcEightControlPoint.y, hourglassCenterX, hourglassCenterY);
/*
The whole glass.
*/
Path glassPath = new Path();
glassPath.addPath(glassArcPathTopLeft);
glassPath.addPath(glassArcPathTopRight);
glassPath.addPath(glassArcPathBottomLeft);
glassPath.addPath(glassArcPathBottomRight);
canvas.drawPath(glassPath, mHourglassArcPaint);
//Close top bottom bounds.
Path glassPathTopClosed = new Path();
glassPathTopClosed.moveTo(hourglassArcStartedPointLeftBound, hourglassArcStartedPointTopBound);
glassPathTopClosed.lineTo(hourglassArcStartedPointRightBound, hourglassArcStartedPointTopBound);
Path glassPathBottomClosed = new Path();
glassPathBottomClosed.moveTo(hourglassArcStartedPointLeftBound, hourglassArcStartedPointBottomBound);
glassPathBottomClosed.lineTo(hourglassArcStartedPointRightBound, hourglassArcStartedPointBottomBound);
Path glassDecorPath = new Path();
glassDecorPath.addPath(glassPathTopClosed);
glassDecorPath.addPath(glassPathBottomClosed);
canvas.drawPath(glassDecorPath, mHourglassDecorPaint);
}
未完待续。。。