您当前的位置: 首页 >  ui

命运之手

暂无认证

  • 1浏览

    0关注

    747博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【高级UI】【010】使用贝塞尔曲线,绘制经过若干固定点的平滑曲线

命运之手 发布时间:2021-10-21 21:23:50 ,浏览量:1

前言

前篇我们已经见过贝塞尔曲线的功能,原理,公式,和推导过程

这节课我们来讲实际应用:如何通过贝塞尔曲线,绘制经过若干固定点的平滑曲线

首先,我们要明确需求,我们的目标是画一条平滑曲线,不是求一条贝塞尔曲线,经过所有点

可以是通过多条贝塞尔曲线来拼接成一条平滑曲线

然后,经过若干点的贝塞尔曲线,可能是有无数条的,并不是唯一解

所以我们的目标,是找一个简单的方案,能画出平滑曲线就行

并不是由曲线上的点,求一个万能的曲线公式,千万别弄错了

方案

  • 每两个点之间画一条贝塞尔曲线,然后所有曲线连接成一条平滑曲线(之所以这么设计,是因为这个想法最简单)
  • 多条曲线想要连成一条平滑曲线,那么在曲线交点,也就是顶点两侧,曲线的斜率或切线方向,一定得是一致的
  • 我们就用x方向,作为所有顶点处,曲线切线的方向(之所以这么设计,是因为这样最简单)
  • 第一个控制点,一定在起点切线上,最后一个控制点,一定在终点切线上(贝塞尔曲线特性决定的)
  • 选用三阶贝塞尔曲线,在起点和终点切线上,随便选个点作为控制点(之所以这么设计,是因为这样最简单)
  • 让曲线两端,控制点到顶点的距离相等(这样曲线就比较匀称,不会出现很突兀的情况)
  • 画出所有顶点之间的贝塞尔曲线,得到最终的平滑曲线

流程示意图

确定切线和控制点 在这里插入图片描述 画三阶贝塞尔曲线 在这里插入图片描述 最终结果 在这里插入图片描述 方案说明

  • 由于所有切线方向,都是沿x方向,看起来会像是沿x方向的波形图,所以实际应用中,最好是根据数据实际走向来确定切线方向
  • 控制点离顶点越近,曲线越接趋于直线
  • 控制点离顶点越远,曲线越接趋于波形
  • 两端控制点离顶点距离,相差越小,曲线越对称(我们是完全相等,则完全对称)

Android平滑曲线绘制代码


	package com.android.architecture;
	
	import android.content.Context;
	import android.graphics.Canvas;
	import android.graphics.DashPathEffect;
	import android.graphics.Paint;
	import android.graphics.Path;
	import android.util.AttributeSet;
	import android.view.View;
	
	import com.easing.commons.android.value.color.Colors;
	import com.easing.commons.android.value.measure.FPos;
	
	import java.util.ArrayList;
	import java.util.List;
	
	@SuppressWarnings("all")
	public class BezierCurve extends View {
	
	    final List posList = new ArrayList();
	
	    final List controlPosList = new ArrayList();
	
	    final Paint posPaint = new Paint();
	    final Paint linePaint = new Paint();
	    final Paint tangentPaint = new Paint();
	    final Paint bezierPaint = new Paint();
	
	    public BezierCurve(Context context) {
	        this(context, null);
	    }
	
	    public BezierCurve(Context context, AttributeSet attributeSet) {
	        super(context, attributeSet);
	        init(context, attributeSet);
	    }
	
	    protected void init(Context context, AttributeSet attributeSet) {
	        //创建初始点
	        posList.add(new FPos(100, 100));
	        posList.add(new FPos(300, 200));
	        posList.add(new FPos(560, 300));
	        posList.add(new FPos(720, 350));
	        posList.add(new FPos(900, 600));
	        posList.add(new FPos(1200, 650));
	        posList.add(new FPos(1300, 700));
	        //初始化点画笔
	        posPaint.setColor(Colors.RED);
	        posPaint.setStrokeWidth(10);
	        posPaint.setStyle(Paint.Style.STROKE);
	        posPaint.setStrokeCap(Paint.Cap.ROUND);
	        //初始化折线画笔
	        linePaint.setColor(Colors.LIGHT_BLUE);
	        linePaint.setStrokeWidth(2);
	        linePaint.setStyle(Paint.Style.STROKE);
	        //初始化切线画笔
	        tangentPaint.setColor(Colors.LIGHT_GREY);
	        tangentPaint.setStrokeWidth(4);
	        tangentPaint.setStyle(Paint.Style.STROKE);
	        tangentPaint.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0));
	        //初始化曲线画笔
	        bezierPaint.setColor(Colors.ORANGE);
	        bezierPaint.setStrokeWidth(2);
	        bezierPaint.setStyle(Paint.Style.STROKE);
	        //计算控制点
	        final float ratio = 0.3F;
	        for (int i = 0; i             
关注
打赏
1654938663
查看更多评论
0.0487s