贝塞尔曲线---(沙漏)

贝塞尔曲线

贝塞尔曲线的几个步骤
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);

}

未完待续。。。


   转载规则


《贝塞尔曲线---(沙漏)》 Air 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录