Android自定义View(10) 《贝塞尔曲线简介》

概述

在Android中的图形绘制中,有个很有名的曲线,叫贝塞尔曲线,可以用来完成一系列非常顺滑的线段动画变化操作,这篇文章就简单学习一下Android自带的贝塞尔曲线的绘制方法。

贝塞尔曲线绘制原理

1.一阶贝塞尔曲线

一阶贝塞尔曲线绘制出来就是一段直线,公式如下


824232-20170330144601373-1257210437.png

绘制效果

824232-20170330142921733-15684048.gif

2.二阶贝塞尔曲线

二阶贝塞尔曲线在起点和终点之间多了一个控制点来完成贝塞尔曲线的绘制,公式如下


824232-20170330144747889-2087843436.png

绘制效果


824232-20170330143512014-2132882514.gif

3.三阶贝塞尔曲线

三阶贝塞尔曲线则在起点和终点外有两个点来控制贝塞尔曲线的绘制,公式如下


824232-20170330144819139-1318405514.png

绘制流程如下


824232-20170330143748045-500194673.gif

Android自带绘制贝塞尔曲线的API

Android的SDK主要有以下两个方法用来绘制贝塞尔曲线

  • 绘制二阶贝塞尔曲线
    rQuadTo()中的参数均为偏移量
// 二阶贝塞尔曲线
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)

简单绘制

1.绘制一条二阶贝塞尔曲线

核心代码如下

override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        var path = Path()
        path.moveTo(100f,150f)
        path.quadTo(200f,250f,300f,150f)
        path.quadTo(400f,50f,500f,150f)
        canvas?.drawPath(path,paint)
    }

运行结果

device-2021-09-07-212451.png

用贝塞尔曲线完成手指滑动路径捕捉

package com.tx.camera.view

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.View

/**
 * create by xu.tian
 * @date 2021/9/7
 */
class BezierView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
    var paint : Paint = Paint()
    init {
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = 5f
        paint.color = Color.WHITE
    }

    var preX = 0f
    var preY = 0f
    var path = Path()

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas?.drawPath(path,paint)
    }

    override fun onTouchEvent(event: MotionEvent?): Boolean {
        when (event?.action){
            MotionEvent.ACTION_DOWN -> actionDown(event)
       //   MotionEvent.ACTION_MOVE -> linePathMove(event)
            MotionEvent.ACTION_MOVE -> bezierPathMove(event)
        }
        return true
    }

    private fun actionDown(event: MotionEvent){
        preX = event.x
        preY = event.y
        path.moveTo(preX,preY)
    }
    // 传统路径捕捉
    private fun linePathMove(event: MotionEvent){
        path.lineTo(event.x,event.y)
        postInvalidate()
    }
    // 利用贝塞尔曲线完成路径捕捉
    private fun bezierPathMove(event: MotionEvent){
        path.quadTo(preX,preY,(event.x+preX)/2,(event.y+preY)/2)
        preX = event.x
        preY = event.y
        postInvalidate()
    }
}

运行效果


bezier.gif

上述例子中将普通的lineTo()方式实现的路径捕捉也写进去了,感兴趣的同学可以对比一下两者的差异,正常情况下贝塞尔实现的会更加顺畅一点。

总结

今天就写到这里了,下篇再接着写自定义View的其他内容~

你可能感兴趣的:(Android自定义View(10) 《贝塞尔曲线简介》)