Bezier Curve 贝塞尔曲线 - 在Unity中实现路径编辑

这篇具有很好参考价值的文章主要介绍了Bezier Curve 贝塞尔曲线 - 在Unity中实现路径编辑。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


简介

贝塞尔曲线(Bezier Curve),又称贝兹曲线或贝济埃曲线,是计算机图形学中相当重要的参数曲线,在我们常用的软件如Photo Shop中就有贝塞尔曲线工具,本文简单介绍贝塞尔曲线在Unity中的实现与应用。

一阶贝塞尔曲线

给顶点P0、P1,只是一条两点之间的直线,公式如下:

B(t) = P0 + (P1 - P0) t = (1 - t) P0 + t P1, t ∈ [0, 1]

等同于线性插值,代码实现如下:

/// <summary>
/// 一阶贝塞尔曲线
/// </summary>
/// <param name="p0">起点</param>
/// <param name="p1">终点</param>
/// <param name="t">[0,1]</param>
/// <returns></returns>
public static Vector3 Bezier1(Vector3 p0, Vector3 p1, float t)
{
    return (1 - t) * p0 + t * p1;
}

二阶贝塞尔曲线

路径由给定点P0、P1、P2的函数计算,公式如下:

B(t) = (1 - t)2 P0 + 2t (1 - t) P1 + t2P2, t ∈[0, 1]

代码实现如下:

/// <summary>
/// 二阶贝塞尔曲线
/// </summary>
/// <param name="p0">起点</param>
/// <param name="p1">控制点</param>
/// <param name="p2">终点</param>
/// <param name="t">[0,1]</param>
/// <returns></returns>
public static Vector3 Bezier2(Vector3 p0, Vector3 p1, Vector3 p2, float t)
{
    Vector3 p0p1 = (1 - t) * p0 + t * p1;
    Vector3 p1p2 = (1 - t) * p1 + t * p2;
    return (1 - t) * p0p1 + t * p1p2;
}

三阶贝塞尔曲线

P0、P1、P2、P3四个点在平面或三维空间中定义了三次方贝塞尔曲线。曲线起始于P0走向P1,并从P2的方向来到P3,一般不会经过P1、P2,这两个点只是提供方向信息,可以将P1、P2理解为控制点。P0和P1之间的间距,决定了曲线在转而趋近P3之前,走向P2的长度有多长,公式如下:

B(t) = P0(1 - t)3 + 3P1t(1 - t)2 + 3P2t2(1 - t) + P3t3, t ∈ [0, 1]

代码实现如下:

/// <summary>
/// 三阶贝塞尔曲线
/// </summary>
/// <param name="p0">起点</param>
/// <param name="p1">控制点1</param>
/// <param name="p2">控制点2</param>
/// <param name="p3">终点</param>
/// <param name="t">[0,1]</param>
/// <returns></returns>
public static Vector3 Bezier3(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
    Vector3 p0p1 = (1 - t) * p0 + t * p1;
    Vector3 p1p2 = (1 - t) * p1 + t * p2;
    Vector3 p2p3 = (1 - t) * p2 + t * p3;
    Vector3 p0p1p2 = (1 - t) * p0p1 + t * p1p2;
    Vector3 p1p2p3 = (1 - t) * p1p2 + t * p2p3;
    return (1 - t) * p0p1p2 + t * p1p2p3;
}

图形理解 Bezier Curve

使用Gizmos绘制Bezier Curve,通过图形理解贝塞尔曲线:

一阶贝塞尔曲线

P0为起点,P1为终点,t从0到1时,在贝塞尔曲线上对应的点为Pt,可以将t为理解为动画播放中的normalized time

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

代码如下:

using UnityEngine;
using SK.Framework;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class Example : MonoBehaviour
{
    private float t;

    private void Update()
    {
        if (t < 1f)
        {
            t += Time.deltaTime * .2f;
            t = Mathf.Clamp01(t);
        }
    }

#if UNITY_EDITOR
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.grey;
        Vector3 p0 = Vector3.left * 5f;
        Vector3 p1 = Vector3.right * 5f;
        Gizmos.DrawLine(p0, p1);
        Handles.Label(p0, "P0");
        Handles.Label(p1, "P1");
        Handles.SphereHandleCap(0, p0, Quaternion.identity, .1f, EventType.Repaint);
        Handles.SphereHandleCap(0, p1, Quaternion.identity, .1f, EventType.Repaint);
        Vector3 pt = BezierCurveUtility.Bezier1(p0, p1, t);
        Gizmos.color = Color.red;
        Gizmos.DrawLine(p0, pt);
        Handles.Label(pt, string.Format("Pt (t = {0})", t));
        Handles.SphereHandleCap(0, pt, Quaternion.identity, .1f, EventType.Repaint);
    }
#endif
}

二阶贝塞尔曲线

P0为起点,P1为控制点,P2为终点,t从0到1时,在贝塞尔曲线上对应的点为Pt

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

代码如下:

using UnityEngine;
using SK.Framework;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class Example : MonoBehaviour
{
    private float t;

    private void Update()
    {
        if (t < 1f)
        {
            t += Time.deltaTime * .2f;
            t = Mathf.Clamp01(t);
        }
    }

#if UNITY_EDITOR
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.grey;
        Vector3 p0 = Vector3.left * 5f;
        Vector3 p1 = Vector3.left * 2f + Vector3.forward * 2f;
        Vector3 p2 = Vector3.right * 5f;
        Gizmos.DrawLine(p0, p1);
        Gizmos.DrawLine(p2, p1);
        Handles.Label(p0, "P0");
        Handles.Label(p1, "P1");
        Handles.Label(p2, "P2");
        Handles.SphereHandleCap(0, p0, Quaternion.identity, .1f, EventType.Repaint);
        Handles.SphereHandleCap(0, p1, Quaternion.identity, .1f, EventType.Repaint);
        Handles.SphereHandleCap(0, p2, Quaternion.identity, .1f, EventType.Repaint);

        Gizmos.color = Color.green;
        for (int i = 0; i < 100; i++)
        {
            Vector3 curr = BezierCurveUtility.Bezier2(p0, p1, p2, i / 100f);
            Vector3 next = BezierCurveUtility.Bezier2(p0, p1, p2, (i + 1) / 100f);
            Gizmos.color = t > (i / 100f) ? Color.red : Color.green;
            Gizmos.DrawLine(curr, next);
        }
        Vector3 pt = BezierCurveUtility.Bezier2(p0, p1, p2, t);
        Handles.Label(pt, string.Format("Pt (t = {0})", t));
        Handles.SphereHandleCap(0, pt, Quaternion.identity, .1f, EventType.Repaint);
    }
#endif
}

三阶贝塞尔曲线

P0为起点,P1为第一个控制点,P2为第二个控制点,P3为终点,t从0到1时,在贝塞尔曲线上对应的点为Pt

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

代码如下:

using UnityEngine;
using SK.Framework;

#if UNITY_EDITOR
using UnityEditor;
#endif

public class Example : MonoBehaviour
{
    private float t;

    private void Update()
    {
        if (t < 1f)
        {
            t += Time.deltaTime * .2f;
            t = Mathf.Clamp01(t);
        }
    }

#if UNITY_EDITOR
    private void OnDrawGizmos()
    {
        Gizmos.color = Color.grey;
        Vector3 p0 = Vector3.left * 5f;
        Vector3 p1 = Vector3.left * 2f + Vector3.forward * 2f;
        Vector3 p2 = Vector3.right * 3f + Vector3.back * 4f;
        Vector3 p3 = Vector3.right * 5f;
        Gizmos.DrawLine(p0, p1);
        Gizmos.DrawLine(p1, p2);
        Gizmos.DrawLine(p2, p3);
        Handles.Label(p0, "P0");
        Handles.Label(p1, "P1");
        Handles.Label(p2, "P2");
        Handles.Label(p3, "P3");
        Handles.SphereHandleCap(0, p0, Quaternion.identity, .1f, EventType.Repaint);
        Handles.SphereHandleCap(0, p1, Quaternion.identity, .1f, EventType.Repaint);
        Handles.SphereHandleCap(0, p2, Quaternion.identity, .1f, EventType.Repaint);
        Handles.SphereHandleCap(0, p3, Quaternion.identity, .1f, EventType.Repaint);

        Gizmos.color = Color.green;
        for (int i = 0; i < 100; i++)
        {
            Vector3 curr = BezierCurveUtility.Bezier3(p0, p1, p2, p3, i / 100f);
            Vector3 next = BezierCurveUtility.Bezier3(p0, p1, p2, p3, (i + 1) / 100f);
            Gizmos.color = t > (i / 100f) ? Color.red : Color.green;
            Gizmos.DrawLine(curr, next);
        }
        Vector3 pt = BezierCurveUtility.Bezier3(p0, p1, p2, p3, t);
        Handles.Label(pt, string.Format("Pt (t = {0})", t));
        Handles.SphereHandleCap(0, pt, Quaternion.identity, .1f, EventType.Repaint);
    }
#endif
}

应用

常见的如道路编辑、河流编辑功能都可以通过贝塞尔曲线实现:

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

本文以一个简单的路径编辑为例,通过使用三阶贝塞尔曲线实现路径的编辑:

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

Bezier Curve

  • segments:贝塞尔曲线的段数,值越大曲线精度越高;
  • loop:是否循环(首尾相连);
  • points :点集合(结构体中包含坐标点和控制点);
using System;
using UnityEngine;
using System.Collections.Generic;

namespace SK.Framework
{
    /// <summary>
    /// 贝塞尔曲线
    /// </summary>
    [Serializable]
    public class BezierCurve
    {
        /// <summary>
        /// 段数
        /// </summary>
        [Range(1, 100)] public int segments = 10;

        /// <summary>
        /// 是否循环
        /// </summary>
        public bool loop;

        /// <summary>
        /// 点集合
        /// </summary>
        public List<BezierCurvePoint> points = new List<BezierCurvePoint>(2)
        {
            new BezierCurvePoint() { position = Vector3.back * 5f, tangent = Vector3.back * 5f + Vector3.left * 3f },
            new BezierCurvePoint() { position = Vector3.forward * 5f, tangent = Vector3.forward * 5f + Vector3.right * 3f }
        };

        /// <summary>
        /// 根据归一化位置值获取对应的贝塞尔曲线上的点
        /// </summary>
        /// <param name="t">归一化位置值 [0,1]</param>
        /// <returns></returns>
        public Vector3 EvaluatePosition(float t)
        {
            Vector3 retVal = Vector3.zero;
            if (points.Count > 0)
            {
                float max = points.Count - 1 < 1 ? 0 : (loop ? points.Count : points.Count - 1);
                float standardized = (loop && max > 0) ? ((t %= max) + (t < 0 ? max : 0)) : Mathf.Clamp(t, 0, max);
                int rounded = Mathf.RoundToInt(standardized);
                int i1, i2;
                if (Mathf.Abs(standardized - rounded) < Mathf.Epsilon)
                    i1 = i2 = (rounded == points.Count) ? 0 : rounded;
                else
                {
                    i1 = Mathf.FloorToInt(standardized);
                    if (i1 >= points.Count)
                    {
                        standardized -= max;
                        i1 = 0;
                    }
                    i2 = Mathf.CeilToInt(standardized);
                    i2 = i2 >= points.Count ? 0 : i2;
                }
                retVal = i1 == i2 ? points[i1].position : BezierCurveUtility.Bezier3(points[i1].position,
                    points[i1].position + points[i1].tangent, points[i2].position
                    - points[i2].tangent, points[i2].position, standardized - i1);
            }
            return retVal;
        }
    }
}
using System;
using UnityEngine;

namespace SK.Framework
{
    [Serializable]
    public struct BezierCurvePoint
    {
        /// <summary>
        /// 坐标点
        /// </summary>
        public Vector3 position;

        /// <summary>
        /// 控制点 与坐标点形成切线
        /// </summary>
        public Vector3 tangent;
    }
}

SimpleBezierCurvePath

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

using UnityEngine;
using System.Collections.Generic;

#if UNITY_EDITOR
using UnityEditor;
#endif

namespace SK.Framework
{
    /// <summary>
    /// 贝塞尔曲线路径
    /// </summary>
    public class SimpleBezierCurvePath : MonoBehaviour
    {
        [SerializeField] private BezierCurve curve;

        public bool Loop { get { return curve.loop; } }

        public List<BezierCurvePoint> Points { get { return curve.points; } }

        /// <summary>
        /// 根据归一化位置值获取对应的贝塞尔曲线上的点
        /// </summary>
        /// <param name="t">归一化位置值 [0,1]</param>
        /// <returns></returns>
        public Vector3 EvaluatePosition(float t)
        {
            return curve.EvaluatePosition(t);
        }

#if UNITY_EDITOR
        /// <summary>
        /// 路径颜色(Gizmos)
        /// </summary>
        public Color pathColor = Color.green;

        private void OnDrawGizmos()
        {
            if (curve.points.Count == 0) return;
            //缓存颜色
            Color cacheColor = Gizmos.color;
            //路径绘制颜色
            Gizmos.color = pathColor;
            //步长
            float step = 1f / curve.segments;
            //缓存上个坐标点
            Vector3 lastPos = transform.TransformPoint(curve.EvaluatePosition(0f));
            float end = (curve.points.Count - 1 < 1 ? 0 : (curve.loop ? curve.points.Count : curve.points.Count - 1)) + step * .5f;
            for (float t = step; t <= end; t += step)
            {
                //计算位置
                Vector3 p = transform.TransformPoint(curve.EvaluatePosition(t));
                //绘制曲线
                Gizmos.DrawLine(lastPos, p);
                //记录
                lastPos = p;
            }
            //恢复颜色
            Gizmos.color = cacheColor;
        }
#endif
    }

#if UNITY_EDITOR
    [CustomEditor(typeof(SimpleBezierCurvePath))]
    public class SimpleBezierCurvePathEditor : Editor
    {
        private SimpleBezierCurvePath path;
        private const float sphereHandleCapSize = .2f;

        private void OnEnable()
        {
            path = target as SimpleBezierCurvePath;
        }

        private void OnSceneGUI()
        {
            //路径点集合为空
            if (path.Points == null || path.Points.Count == 0) return;
            //当前选中工具非移动工具
            if (Tools.current != Tool.Move) return;
            //颜色缓存
            Color cacheColor = Handles.color;
            Handles.color = Color.yellow;
            //遍历路径点集合
            for (int i = 0; i < path.Points.Count; i++)
            {
                DrawPositionHandle(i);
                DrawTangentHandle(i);

                BezierCurvePoint point = path.Points[i];
                //局部转全局坐标 路径点、控制点 
                Vector3 position = path.transform.TransformPoint(point.position);
                Vector3 controlPoint = path.transform.TransformPoint(point.tangent);
                //绘制切线
                Handles.DrawDottedLine(position, controlPoint + position, 1f);
            }
            //恢复颜色
            Handles.color = cacheColor;
        }

        //路径点操作柄绘制
        private void DrawPositionHandle(int index)
        {
            BezierCurvePoint point = path.Points[index];
            //局部转全局坐标
            Vector3 position = path.transform.TransformPoint(point.position);
            //操作柄的旋转类型
            Quaternion rotation = Tools.pivotRotation == PivotRotation.Local
                ? path.transform.rotation : Quaternion.identity;
            //操作柄的大小
            float size = HandleUtility.GetHandleSize(position) * sphereHandleCapSize;
            //在该路径点绘制一个球形
            Handles.color = Color.white;
            Handles.SphereHandleCap(0, position, rotation, size, EventType.Repaint);
            Handles.Label(position, string.Format("Point{0}", index));
            //检测变更
            EditorGUI.BeginChangeCheck();
            //坐标操作柄
            position = Handles.PositionHandle(position, rotation);
            //变更检测结束 如果发生变更 更新路径点
            if (EditorGUI.EndChangeCheck())
            {
                //记录操作
                Undo.RecordObject(path, "Position Changed");
                //全局转局部坐标
                point.position = path.transform.InverseTransformPoint(position);
                //更新路径点
                path.Points[index] = point;
            }
        }

        //控制点操作柄绘制
        private void DrawTangentHandle(int index)
        {
            BezierCurvePoint point = path.Points[index];
            //局部转全局坐标
            Vector3 cp = path.transform.TransformPoint(point.position + point.tangent);
            //操作柄的旋转类型
            Quaternion rotation = Tools.pivotRotation == PivotRotation.Local
                ? path.transform.rotation : Quaternion.identity;
            //操作柄的大小
            float size = HandleUtility.GetHandleSize(cp) * sphereHandleCapSize;
            //在该控制点绘制一个球形
            Handles.color = Color.yellow;
            Handles.SphereHandleCap(0, cp, rotation, size, EventType.Repaint);
            //检测变更
            EditorGUI.BeginChangeCheck();
            //坐标操作柄
            cp = Handles.PositionHandle(cp, rotation);
            //变更检测结束 如果发生变更 更新路径点
            if (EditorGUI.EndChangeCheck())
            {
                //记录操作
                Undo.RecordObject(path, "Control Point Changed");
                //全局转局部坐标
                point.tangent = path.transform.InverseTransformPoint(cp) - point.position;
                //更新路径点
                path.Points[index] = point;
            }
        }
    }
#endif
}

SimpleBezierCurvePathAlonger

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

  • path:贝塞尔曲线路径;
  • speed:移动速度;
  • update Mode:更新方式(FixedUpdate、Update、LateUpdate)
using UnityEngine;

namespace SK.Framework
{
    public class SimpleBezierCurvePathAlonger : MonoBehaviour
    {
        public enum UpdateMode
        {
            FixedUpdate,
            Update,
            LateUpdate,
        }

        [SerializeField] private SimpleBezierCurvePath path;

        [SerializeField] private float speed = .1f;

        [SerializeField] private UpdateMode updateMode = UpdateMode.Update;

        private float normalized = 0f;

        private Vector3 lastPosition;

        private void FixedUpdate()
        {
            if (updateMode == UpdateMode.FixedUpdate && path != null)
                MoveAlongPath();
        }

        private void Update()
        {
            if (updateMode == UpdateMode.Update && path != null)
                MoveAlongPath();
        }

        private void LateUpdate()
        {
            if (updateMode == UpdateMode.LateUpdate && path != null)
                MoveAlongPath();
        }

        private void MoveAlongPath()
        {
            float t = normalized + speed * Time.deltaTime;
            float max = path.Points.Count - 1 < 1 ? 0 : (path.Loop ? path.Points.Count : path.Points.Count - 1);
            normalized = (path.Loop && max > 0) ? ((t %= max) + (t < 0 ? max : 0)) : Mathf.Clamp(t, 0, max);
            transform.position = path.EvaluatePosition(normalized);
            Vector3 forward = transform.position - lastPosition;
            transform.forward = forward != Vector3.zero ? forward : transform.forward;
            lastPosition = transform.position;
        }
    }
}

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

源码已上传至SKFramework框架Package Manager中:

unity 贝塞尔曲线编辑器,Unity 开发日志,Unity Editor,Unity,贝塞尔曲线,路径编辑,动画

参考链接:文章来源地址https://www.toymoban.com/news/detail-818242.html

  1. 贝塞尔曲线 - 百度百科
  2. Unity Cinemachine Path
  3. Unity 贝塞尔曲线(Beizer curve)的原理与运用

到了这里,关于Bezier Curve 贝塞尔曲线 - 在Unity中实现路径编辑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • unity 曲线可视化图表制作(lineRenderer + 贝塞尔曲线)

    需求要实现一个动态变化的曲线 思路: 分为两部分:画线和平滑曲线 首先解决画线问题: 1.lineRenderer 2.texture的setpixel 肯定选已经做好的轮子1啦 平滑曲线思路: 1.抛物线 2.贝塞尔曲线 抛物线做连续的曲线太抽象了 肯定选贝塞尔曲线 先了解一下贝塞尔曲线 一次贝塞尔 对应

    2023年04月08日
    浏览(51)
  • Unity ——使用贝塞尔曲线对三维管状物体进行弯曲

    参考链接:【Unity】弹性鱼竿简单实现-通过贝塞尔曲线修改Mesh - 简书 参考论文:吴晓亮, 黄襄念. Unity 中使用贝塞尔曲线对三维物体进行弯曲[J]. 现代计算机, 2016 (5): 57-59. unity项目下载:https://download.csdn.net/download/weixin_43042683/87690343 效果图 随着虚拟现实的发展,在游戏引擎中

    2024年02月11日
    浏览(63)
  • 【游戏开发实战】Unity实现类似GitHub地球射线的效果(LineRenderer | 贝塞尔曲线)

    一、前言 嗨,大家伙,我是新发。 好久不见,这是2022年第一篇博客,今天有同学私信我,问我在 Unity 中如何实现这种地球辐射线的效果, 这一看,我就想到了 GitHub 主页的地球射线, 那么,今天就来讲讲如何实现这个效果吧~ 本文最终效果如下: 本文工程源码见文章末尾

    2024年02月06日
    浏览(96)
  • 【unity小技巧】使用贝塞尔曲线实现导弹随机攻击敌人,也可以用于平滑拾取物品

    参考原视频链接: 【视频】:https://www.bilibili.com/video/BV1aU4y1v7yM/ 注意 :本文为学习笔记记录,推荐支持原作者,去看原视频自己手敲代码理解更加深入

    2024年02月13日
    浏览(39)
  • Unity实现杀戮尖塔出牌效果( 三. 贝塞尔曲线引导箭头绘制,卡牌使用效果制作)

    1. 攻击类型卡牌 ①拖拽超过一定高度之后卡牌会移动到手牌中心位置 ②出现攻击引导箭头 (塞贝尔曲线) ③成功指向目标怪物后打出 2. 技能能力类型卡牌 ①可自由拖动 ②脱离手牌高度后打出 这里只展示此效果核心代码内容,重复代码不做赘述,上期(二.鼠标指向卡牌时,

    2024年04月12日
    浏览(64)
  • 二阶贝塞尔曲线生成弧线

    本文分享一个二阶贝塞尔曲线曲线生成弧线的算法。 示例使用openlayers实现。

    2024年01月22日
    浏览(47)
  • 【LVGL笔记】-- 贝塞尔曲线绘制

    什么是贝塞尔曲线 贝塞尔曲线 (Bézier Curve,也被称为贝塞尔多项式(Bézier Polynomial),是由一系列控制点(Control Point)所定义的一条平滑曲线。 Pierre Bézier 于1960年开始利用该曲线设计雷诺的车身线条,故命名为贝塞尔曲线。目前,贝塞尔曲线被广泛应用于图形设计、路径

    2024年02月02日
    浏览(44)
  • c++计算贝塞尔曲线(折线平滑为曲线)坐标方法

    效果可查看上一篇博文: js手动画平滑曲线,贝塞尔曲线拟合 【代码】js手动画平滑曲线,贝塞尔曲线拟合。 https://blog.csdn.net/qiufeng_xinqing/article/details/131711963?spm=1001.2014.3001.5502 代码如下:

    2024年02月16日
    浏览(37)
  • CSS动画中的贝塞尔曲线

    最近在学习CSS动画,其中动画时间函数的部分涉及到了 贝塞尔曲线 的相关知识。对于这部分知识,之前一直没有好好学习过,正好借着这个机会学习下。 首先简单介绍下贝塞尔曲线。 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲

    2024年02月09日
    浏览(69)
  • 彻底搞懂贝塞尔曲线的原理

    贝塞尔曲线介绍 我们在前面讲了绘制自定义曲线,而实际开发过程还会遇到更复杂的图形绘制,比如下面的这些图形: 这时候就需要用到贝塞尔曲线了。下面是百科关于贝塞尔曲线的介绍。 贝塞尔曲线就是这样的一条曲线,它是依据四个位置任意的点坐标绘制出的一条光滑

    2024年02月20日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包