贝塞尔曲线相关

二阶贝塞尔曲线绘制:

mPath.quadTo(x1, y1, x2, y2) ;  

解释:(x1,y1) 为控制点,(x2,y2)为结束点。

 

三阶贝塞尔曲线绘制:

mPath.cubicTo(x1, y1, x2, y2, x3, y3) ;  

解释:(x1,y1) 为控制点,(x2,y2)为控制点,(x3,y3) 为结束点。

 

结合二阶和三阶贝塞尔曲线绘制多点曲线:

(关注点放在数据点x、y的处理上即可,剩余中点计算的套用现有代码即可

//*****************贝塞尔曲线数据填充=================
private static final int LINEWIDTH = 5;
private static final int LINE_COLOR = 0xffC959A2;

private Paint mPaint;
private Path mPath;
//即将要穿越的点集合
private List<Point> mPoints = new ArrayList<>();
//中点集合
private List<Point> mMidPoints = new ArrayList<>();
//中点的中点集合
private List<Point> mMidMidPoints = new ArrayList<>();
//移动后的点集合(控制点)
private List<Point> mControlPoints = new ArrayList<>();
private List<ContinuousHeartRateAnalysisBean.HrlistBean> hrList;
//大的单位宽度(分6分)
private int unitBigWidth;
//小的单位宽度(分24分)
private int unitSmallWidth;

private void initChart() {
    //开始x轴
    unitBigWidth = chartWidth / 5;
    //x轴单位区间距离
    unitSmallWidth = (chartWidth - unitBigWidth) / 24;

    mPaint = new Paint();
    mPaint.setStyle(Paint.Style.STROKE);// 空心(保持线条)
    mPaint.setAntiAlias(true);// 抗锯齿
    mPaint.setDither(true);// 防抖动

    mPath = new Path();

    initPoints();
    initMidPoints(this.mPoints);
    initMidMidPoints(this.mMidPoints);
    initControlPoints(this.mPoints, this.mMidPoints, this.mMidMidPoints);

    drawControlPoints(canvas);

    // 画贝塞尔曲线
    drawBezier(canvas);
}

/**
 * 添加即将要穿越的点
 */
private void initPoints() {
    mPoints.clear();
    for (int i = 0; i < hrList.size(); i++) {
        ContinuousHeartRateAnalysisBean.HrlistBean bean = hrList.get(i);
        int x = unitBigWidth + Integer.valueOf(bean.getStartTime().substring(9, 11))*unitSmallWidth;
        int y = (int) ((maxChartValue - bean.getLivehr())*chartHeight/maxChartValue);

        Point point = new Point(x, y);
        mPoints.add(point);
    }
}

/**
 * 初始化中点集合
 */
private void initMidPoints(List<Point> points) {
    mMidPoints.clear();
    for (int i = 0; i < points.size(); i++) {
        Point midPoint = null;
        if (i == points.size() - 1) {
            return;
        } else {
            midPoint = new Point((points.get(i).x + points.get(i + 1).x) / 2, (points.get(i).y + points.get(i + 1).y) / 2);
        }
        mMidPoints.add(midPoint);
    }
}

/**
 * 初始化中点的中点集合
 */
private void initMidMidPoints(List<Point> midPoints) {
    mMidMidPoints.clear();
    for (int i = 0; i < midPoints.size(); i++) {
        Point midMidPoint = null;
        if (i == midPoints.size() - 1) {
            return;
        } else {
            midMidPoint = new Point((midPoints.get(i).x + midPoints.get(i + 1).x) / 2, (midPoints.get(i).y + midPoints.get(i + 1).y) / 2);
        }
        mMidMidPoints.add(midMidPoint);
    }
}

/**
 * 初始化控制点集合
 */
private void initControlPoints(List<Point> points, List<Point> midPoints, List<Point> midMidPoints) {
    mControlPoints.clear();
    for (int i = 0; i < points.size(); i++) {
        if (i == 0 || i == points.size() - 1) {
            continue;
        } else {
            Point before = new Point();
            Point after = new Point();
            before.x = points.get(i).x - midMidPoints.get(i - 1).x + midPoints.get(i - 1).x;
            before.y = points.get(i).y - midMidPoints.get(i - 1).y + midPoints.get(i - 1).y;
            after.x = points.get(i).x - midMidPoints.get(i - 1).x + midPoints.get(i).x;
            after.y = points.get(i).y - midMidPoints.get(i - 1).y + midPoints.get(i).y;
            mControlPoints.add(before);
            mControlPoints.add(after);
        }
    }
}

/** 画控制点 */
private void drawControlPoints(Canvas canvas) {
    mPaint.setColor(Color.GRAY);
    mPaint.setStrokeWidth(14);
    // 画控制点
    for (int i = 0; i < mControlPoints.size(); i++) {
        canvas.drawPoint(mControlPoints.get(i).x, mControlPoints.get(i).y, mPaint);
    }
}


/**
 * 画贝塞尔曲线
 */
private void drawBezier(Canvas canvas) {
    mPaint.setStrokeWidth(LINEWIDTH);
    mPaint.setColor(LINE_COLOR);
    // 重置路径
    mPath.reset();
    for (int i = 0; i < mPoints.size(); i++) {
        if (i == 0) {// 第一条为二阶贝塞尔
            mPath.moveTo(mPoints.get(i).x, mPoints.get(i).y);// 起点
            mPath.quadTo(mControlPoints.get(i).x, mControlPoints.get(i).y,// 控制点
                    mPoints.get(i + 1).x, mPoints.get(i + 1).y);
        } else if (i < mPoints.size() - 2) {// 三阶贝塞尔
            mPath.cubicTo(mControlPoints.get(2 * i - 1).x, mControlPoints.get(2 * i - 1).y,// 控制点
                    mControlPoints.get(2 * i).x, mControlPoints.get(2 * i).y,// 控制点
                    mPoints.get(i + 1).x, mPoints.get(i + 1).y);// 终点
        } else if (i == mPoints.size() - 2) {// 最后一条为二阶贝塞尔
            mPath.moveTo(mPoints.get(i).x, mPoints.get(i).y);// 起点
            mPath.quadTo(mControlPoints.get(mControlPoints.size() - 1).x, mControlPoints.get(mControlPoints.size() - 1).y,
                    mPoints.get(i + 1).x, mPoints.get(i + 1).y);// 终点
        }
    }
    canvas.drawPath(mPath, mPaint);
}

补充:关于Android渐变色

网上参考代码:

LinearGradient gradient;//线型渐变色 一把只能在绘制横竖直线 或者矩形图形的时候效果好。
RadialGradient gradient;//圆形渐变色 就像树了轮廓一样 一环套一环的着色 下一环的半径是比上一环半径的一个radius值
BitmapShader gradient;  位图型渐变色,其实就相当于把位图当颜色。
SweepGradient gradient;
ComposeShader gradient;
gradient = new LinearGradient(0, 0, 0, 100, Color.argb(0, 0, 0, 0), Color.BLACK, Shader.TileMode.CLAMP);
gradient=new LinearGradient(0,0,0,100, Color.argb(0,0,0,0),Color.BLACK, Shader.TileMode.REPEAT);
gradient=new LinearGradient(0,0,0,100, Color.argb(0,0,0,0),Color.BLACK, Shader.TileMode.MIRROR);
gradient=new RadialGradient(0,0,100, Color.argb(0,0,0,0),Color.BLACK, Shader.TileMode.MIRROR);
gradient=new BitmapShader(BitmapFactory.decodeResource(getResources(), R.drawable.locus_line), Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
gradient=new SweepGradient(50,50, Color.argb(0,0,0,0),Color.BLACK);
gradient = new ComposeShader(new LinearGradient(0, 0, 0, 100, Color.argb(0, 0, 0, 0), Color.BLACK, Shader.TileMode.MIRROR),
gradient = new RadialGradient(0, 0, 100, Color.argb(0, 0, 0, 0), Color.BLACK, Shader.TileMode.MIRROR),
        PorterDuff.Mode.ADD);
mPaint.setShader(gradient);

Paint p=new Paint();

 LinearGradient lg=new LinearGradien(0,0,100,100,Color.RED,Color.BLUE,Shader.TileMode.MIRROR);  

参数一为渐变起初点坐标x位置,参数二为y轴位置,参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像

Gradient是基于Shader类,所以我们通过Paint的setShader方法来设置这个渐变,代码如下: mPaint.setShader(lg);

 canvas.drawCicle(0,0,200,mPaint); //参数3为画圆的半径,类型为float型。

它除了定义开始颜色和结束颜色以外还可以定义,多种颜色组成的分段渐变效果

LinearGradient shader = new LinearGradient(0, 0, endX, endY, new int[]{startColor, midleColor, endColor},new float[]{0 , 0.5f, 1.0f}, TileMode.MIRROR);

其中参数new int[]{startColor, midleColor, endColor}是参与渐变效果的颜色集合,

 其中参数new float[]{0 , 0.5f, 1.0f}是定义每个颜色处于的渐变相对位置,

 这个参数可以为null,如果为null表示所有的颜色按顺序均匀的分布

 

public RadialGradient(float x, float y, float radius, int[] colors, float[] positions,Shader.TileMode tile)

float x:  圆心X坐标

float y:  圆心Y坐标

float radius: 半径

int[] colors:  渲染颜色数组

floate[] positions: 相对位置数组,可为null,  若为null,可为null,颜色沿渐变线均匀分布

Shader.TileMode tile:渲染器平铺模式

public RadialGradient(float x, float y, float radius, int color0, int color1,Shader.TileMode tile)

float x:  圆心X坐标

float y:  圆心Y坐标

float radius: 半径

int color0: 圆心颜色

int color1: 圆边缘颜色

Shader.TileMode tile:渲染器平铺模式

发布了100 篇原创文章 · 获赞 5 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览