自定义控件详解(八):贝塞尔曲线

简介: Path类有4个贝塞尔曲线相关方法://二阶贝赛尔 public void quadTo(float x1, float y1, float x2, float y2) public void rQuadTo(float dx1, float dy1, float dx2, float ...

Path类有4个贝塞尔曲线相关方法:

//二阶贝赛尔  
public void quadTo(float x1, float y1, float x2, float y2)  
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)  
//三阶贝赛尔  
public void cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)  
public void rCubicTo(float x1, float y1, float x2, float y2,float x3, float y3)  

 

关于贝塞尔曲线的概念就不讲了,直接看代码使用。

 一、 下面的方法中 ,参数中(x1,y1)是控制点坐标,(x2,y2)是终点坐标 

public void quadTo(float x1, float y1, float x2, float y2)  

 大家看到和Path.lineTo()方法有些不一样,它没有起始坐标。

 实际上连续使用quadTo()方法的时候,上一次使用的终点坐标即下一次的起始坐标

 而一开始我们需要用moveTo()来指定一个起始坐标,如果不指定的话,起始坐标默认为左上角(0,0)

 

 下面通过实现绘图板功能来看一下使用。

  

public class BSELineView extends View{
    Path path = new Path();
    float mX;
    float mY;
    public BSELineView(Context context) {
        super(context);
    }

    public BSELineView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN: {
                path.moveTo(event.getX(), event.getY());   // 触摸按下的时候,记录起始坐标
                mX = event.getX();
                mY = event.getY();
                return true;
            }
            case MotionEvent.ACTION_MOVE: {                // 触摸过程中,用贝塞尔曲线方法 quadTo()记录路径
                path.quadTo(mX, mY, (mX + event.getX()) / 2, (mY + event.getY()) / 2);
                mX = event.getX();
                mY = event.getY();
                invalidate();                              // 刷新view 注意是在UI线程中
                break;
            }
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.set
        Color(Color.GREEN);
        paint.setStrokeWidth(6);

        canvas.drawPath(path,paint);
    }

    public void reset(){   // 重置功能,清除绘制内容,刷新View
        path.reset();
        postInvalidate();
    }
}

 



可以看到我们绘制出来的View 线条比较华润,没有弯折的生硬感。

二、绘制波浪线
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)  
dx1:控制点X坐标,表示相对上一个终点X坐标的位移坐标,可为负值,正值表示相加,负值表示相减;
dy1:控制点Y坐标,相对上一个终点Y坐标的位移坐标。同样可为负值,正值表示相加,负值表示相减;
dx2:终点X坐标,同样是一个相对坐标,相对上一个终点X坐标的位移值,可为负值,正值表示相加,负值表示相减;
dy2:终点Y坐标,同样是一个相对,相对上一个终点Y坐标的位移值。可为负值,正值表示相加,负值表示相减;
这四个参数都是传递的都是相对值,都是相对上一个终点的位移值。 

 举例:

path.moveTo(100,100);  
path.quadTo(300,50,500,500); 

相等于

path.moveTo(100,100);  
path.rQuadTo(200,-50,400,400) 

 

 实现一个波浪线。

 初始点假设(orginX , orginY) , 控制点(x,rangY)  ,终点(x*2 , 0)    ,  就绘制了一条开口向下的曲线

                                              接着控制点(x,-rangY) , 终点(x*2,0)   ,就接着绘制了一条开口向上的曲线

 

        int originY = 300;  // 初始点y轴坐标
        int rangeY = 50 ;    // y轴幅度
        int rangeX = 50; //x轴幅度
        path.moveTo(0,originY);
        for (int i = 0; i < getWidth(); i++) {  // x 轴范围小与屏幕宽度
            path.rQuadTo(rangeX,rangeY,rangeX*2,0);
            path.rQuadTo(rangeX,-rangeY,rangeX*2,0);
            i+=(rangeX*2);
        }

完整代码:

public class WaveView extends View{
    Paint paint ;
    Path path;

    public WaveView(Context context) {
        super(context);
    }

    public WaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        path = new Path();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(6);
        paint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        path.reset();
        int originY = 300;  // 初始点y轴坐标
        int rangeY = 50 ;    // y轴幅度
        int rangeX = 50; //x轴幅度
        path.moveTo(0,originY);
        for (int i = 0; i < getWidth(); i++) {  // x 轴范围小与屏幕宽度
            path.rQuadTo(rangeX,rangeY,rangeX*2,0);
            path.rQuadTo(rangeX,-rangeY,rangeX*2,0);
            i+=(rangeX*2);
        }

        canvas.drawPath(path,paint);
    }
}
效果图:

 


绘制移动的波形图:
public class WaveView extends View{
    Paint paint ;
    Path path;
    int change;
    public WaveView(Context context) {
        super(context);
    }

    public WaveView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        path = new Path();
        paint.setColor(Color.GREEN);
        paint.setStrokeWidth(6);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        path.reset();
        int originY = 300;  // 初始点y轴坐标
        int rangeY = 50 ;    // y轴幅度
        int rangeX = 50; //x轴幅度
        path.moveTo(-rangeX*4+change,originY); // 让初始点在界面左侧4*rangX处, change是移动距离,没2000毫秒重新绘制
        for (int i = 0; i < getWidth(); i+=(rangeX*2)) {  // x 轴范围小与屏幕宽度
            path.rQuadTo(rangeX,rangeY,rangeX*2,0);
            path.rQuadTo(rangeX,-rangeY,rangeX*2,0);

        }
        path.lineTo(getWidth(),getHeight());
        path.lineTo(0,getHeight());
        path.close();

        canvas.drawPath(path,paint);
    }
    public void startAnim(){
        ValueAnimator animator = ValueAnimator.ofInt(0 , 200);
        animator.setDuration(2000);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setInterpolator(new LinearInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                change = (int) animation.getAnimatedValue();
                postInvalidate();
            }
        });
        animator.start();
    }
}

 







 

相关文章
|
5月前
|
XML 前端开发 Java
Android Studio App自定义控件中自定义视图的绘制讲解及实战(附源码 包括自定义绘制各种图形)
Android Studio App自定义控件中自定义视图的绘制讲解及实战(附源码 包括自定义绘制各种图形)
77 1
|
计算机视觉
我的Qt作品(6)使用Qt完整解析dxf文件并绘制(支持椭圆和样条曲线)
我的Qt作品(6)使用Qt完整解析dxf文件并绘制(支持椭圆和样条曲线)
1107 0
我的Qt作品(6)使用Qt完整解析dxf文件并绘制(支持椭圆和样条曲线)
|
数据可视化 计算机视觉
VTK 基础(一) — 常用控件介绍及实现圆锥体绘制
最近在做医学图像的相关处理,其中用到了可视化程序包 VTK,在学习过程中,准备写一系列相关教程,一方面用于巩固自己所学,主要自己太笨图片,另一方面加强一下知识理解。 利用 VTK 进行绘制物体时,常用到的组件有下面几种,为了加深理解,VTK 把一个物体的渲染过程比喻成了一场演出(真的很形象图片):
VTK 基础(一) — 常用控件介绍及实现圆锥体绘制
|
Android开发
简单实现安卓圆形按钮及(圆形)波纹效果
简单实现安卓圆形按钮及(圆形)波纹效果
207 0
简单实现安卓圆形按钮及(圆形)波纹效果
MFC自定义环形进度条的实现
MFC自定义环形进度条的实现
426 0
MFC自定义环形进度条的实现
|
程序员
Qt编写自定义控件63-水波效果
一、前言 几年前就一直考虑过写这个控件了,在9年前用C#的时候,就看到过别人用C#写了个水波效果的控件,挺好玩的,当时看了下代码用的二维数组来存储变换的图像像素数据,自从学了Qt以后,有过几次想要用Qt写一个版本,当时功力尚浅,尝试过了没写成功,我记得还有个用汇编写的dll提供调用,那个效率贼高,用CPU绘制的话效率相对来说低很多。
1299 0
|
程序员 C语言
Qt编写自定义控件56-波浪曲线
一、前言 波浪曲线控件,其实是之前一个水波进度条控件的一个核心,其实就是利用正弦曲线来生成对应的坐标进行绘制,把这个功能单独提取出来,是为了更详细的研究各种正弦余弦等拓展效果,当时写这个效果的时候,参考的是网上android绘制的水波效果的代码,然后自己重新理解以后,整理成Qt的版本,拓展了部分效果比如可以设置浪的高度,浪的密度,密度越大越浪,^_^,演示控件效果提供了滑块来设置对应的参数。
1184 0
|
程序员 C语言 开发工具
Qt编写自定义控件57-直方波形图
一、前言 直方波形图控件非原创控件,控件大全中大概有20-30个控件非自己原创,而是参考了网上开源的代码,自己加以整理和完善,新增了插件的代码使得可以直接集成到QtDesigner或者QtCreator中。
1177 0
|
程序员 开发工具 C语言
Qt编写自定义控件45-柱状标尺控件
一、前言 这个控件写了很久了,是最早期的一批控件中的一个,和温度计控件类似,都是垂直的进度条,可以设置不同的背景颜色,左侧的刻度也可以自由设定,还提供了动画效果,其实就是开启定时器慢慢的进度到设定的目标值,如果设定的值比当前值大,则递增,反之递减。
1123 0