贝塞尔曲线理解与应用
贝塞尔曲线并非是由贝塞尔发明的,但是是因为他把这个东西应用到当时的汽车领域而闻名的,所以取名为贝塞尔曲线。
在我看来,用简单的话来理解一下贝塞尔曲线,他是通过少量几个点,使用一套公式,生成一条平滑曲线。
原理
先盗用人家的图,嘿嘿。
平面ABC 3个点。
在AB上找一个点D,在BC上找一个点E,使得AD:AB = BE:BC
然后在DE上找一个点F,使得DF:DE = AD:AB = BE:BC 接着,我们将D点从A点 --> B点慢慢移动,在这个过程中,会产生一系列的F点,将这些F点相连,就会形成一条曲线,嘿嘿,就是我们的贝塞尔曲线,
从这里可以看出,这里有3个关键点,起始点、终止点、控制点。 数学上的推理验证,这里就不讲了,直接给出公式。
二阶贝塞尔曲线,一个控制点
三阶贝塞尔曲线,二个控制点
一阶贝塞尔曲线,就是一条直线
为了完整性,我给出贝塞尔曲线的n阶通式
想看这个公式推导,我给出一个文章链接 n公式推导推导。 但是在一般应用中,二阶,三阶贝塞尔曲线是已经够用了。
应用
先简单的来使用一下,通过公式来描绘曲线。
***d2(){this.name = '二次贝赛尔曲线方程';let _this = this;let oCanvas = document.querySelector("#canvas"),oGc = oCanvas.getContext('2d');let percent = 0;function animate() {oGc.clearRect(0, 0, 800, 800);oGc.beginPath();oGc.strokeStyle = 'red';oGc.moveTo( 40, 80 );//oGc.quadraticCurveTo( 137, 80, 140, 280 );_this.d2_(oGc,[40, 80],[137, 80],[140, 280],percent);oGc.stroke();percent = (percent 1) % 100;requestAnimationFrame(animate);}animate()},d2_(oGc,start,cp,end, percent){for (var t = 0; t <= percent / 100; t = 0.01) { var x = this.quadraticBezier(start[0], cp[0], end[0], t); var y = this.quadraticBezier(start[1], cp[1], end[1], t);oGc.lineTo(x, y);} },quadraticBezier(p0, p1, p2, t) {var k = 1 - t;return k * k * p0 2 * (1 - t) * t * p1 t * t * p2; // 这个方程就是二次贝赛尔曲线方程 },***
这个就是根据公式描述出相关的点,然后连接起来。 但是在实际应用中,很大程度上会在canvas中绘图,canvas提供2个api,
quadraticCurveTo:二阶贝塞尔曲线,参数是 控制点,结束点
bezierCurveTo :三阶贝塞尔曲线,参数是 控制点1,控制点2,结束点
你们发现没,它们没有开始点,它们的开始点是画笔开始的位置。
在举一个例子,画起伏波浪
直接讲思路,就是先画一个静止的波浪
好,现在来看一下,这个该怎么入手,先把这个轮廓描绘出来,要描绘,先拆分, 它是由一条曲线,3条直接拼接而成,有了这个思路,已经完成了一半, 那条曲线该如何绘制,其实我觉得思路不止一种,我们应该先自己给这个曲线下定义,我认为他应该是半圆的弧连接,应该是椭圆的弧链接,应该是其他。我先给它下一个定义
我用二阶和三阶分别来描述这个曲线,1,2,3,4这4个点描述出来了,那么这个曲线也就绘制完成了
1: (0.5d,waveH)
2: (d, 0)
3: (1.5d,-waveH)
4: (2d,0)
我选择的这个规则是很中规中矩的,上一个波形是画2个二阶贝塞尔曲线,下一个波形是画一个3阶贝塞尔曲线。这个就可以把静止的波形给绘制出来了,然后你想象一个给这个坐标加横向偏移,加纵向偏移,他就可以起伏波动了
***init2(){this.name = '2阶';let c = document.getElementById("myCanvas"),ctx = c.getContext("2d"),waveWidth = 800,offset = 0, //xwaveHeight = 20, // 波浪大小waveCount = 5,startX = -200,startY = 208,progress = 0, //高度progressStep = 0.5,d2 = waveWidth / waveCount,d = d2 / 2,hd = d / 2;ctx.fillStyle = "rgba(0,222,255, 0.2)";function tick() {offset -= 4; // x 移动progress = progressStep;if (progress > 220 || progress < 0) progressStep *= -1;if (-1 * offset === d2) offset = 0;ctx.clearRect(0, 0, c.width, c.height);ctx.beginPath();let offsetY = startY - progress; //y 坐标高低ctx.moveTo(startX - offset, offsetY);for (var i = 0; i < waveCount; i ) {var dx = i * d2;var offsetX = dx startX - offset;ctx.quadraticCurveTo(offsetX hd, offsetY waveHeight, offsetX d, offsetY);ctx.quadraticCurveTo(offsetX hd d, offsetY - waveHeight, offsetX d2, offsetY);}ctx.lineTo(startX waveWidth, 300);ctx.lineTo(startX, 300);ctx.fill();requestAnimationFrame(tick);}tick();},
***
上面是二阶贝塞尔曲线,用三阶画的话,就是
ctx.quadraticCurveTo(offsetX hd, offsetY waveHeight, offsetX d, offsetY);
ctx.quadraticCurveTo(offsetX hd d, offsetY - waveHeight, offsetX d2, offsetY);
换成
ctx.bezierCurveTo(offsetX hd, offsetY waveHeight, offsetX d hd, offsetY-waveHeight, offsetX d2, offsetY );
就可以了。
其实我觉得贝塞尔曲线在使用过程中,最关键的是控制点的选择,不同点的选择,会展现不同的效果,但是选择控制点,是一件挺有意思的事。
下面我们再来看一个案例,粘性拖动
要实现这个功能,来理一下思路,首先来描绘一下这个轮廓,一样的套路,是不是,来,思考一下,这个图形是由什么组成的。
画的丑,别介意,这么看这个轮廓,是不是出来了,你可以想象,是由2个半圆的圆弧和2条曲线,可以先画ABCD这个路径,再画2个圆,这样这个轮廓就出来了。接下来,再看这个曲线如何完成。这个曲线开始和结束点已经有了,再找一个控制点也能画出来,那么控制点在哪里,我下的定义简单粗暴,在2圆心的链接线的终点,然后再把ABCD 4个点描述出来,这个路径就解决了,如何描述ABCD,请允许我盗图
如何让这个图形动起来,可以这么想第一个圆,可以是手开始触摸的点,也可以自己先写死,另一个圆是手拖动的位置,所以只要动态的改变第二个圆心的位置,那么这个拖动的效果就出来了。 我在拖动的时候,d的距离在改变,那么制定一个规则,d越大,第一个圆的半径就越小,那么基本上就可以实现了。
***data() {return {radius: 7,x: 300,//手移动y: 300,//手移动anchorX: 200,// 控制点anchorY: 200,// 控制点startX: 100, //开始startY: 100,//开始}},mounted() {document.removeEventListener('touchstart', this.wrapTouchStart);document.addEventListener("touchstart", this.wrapTouchStart);document.removeEventListener('touchmove', this.wrapTouchMove);document.addEventListener('touchmove', this.wrapTouchMove);document.removeEventListener('touchend', this.wrapTouchEnd);document.addEventListener('touchend', this.wrapTouchEnd);document.removeEventListener('touchcancel', this.wrapTouchCancel);document.addEventListener('touchcancel', this.wrapTouchCancel);},methods: {wrapTouchStart(e) {},wrapTouchMove(e) {this.x = e.changedTouches[0].clientX;this.y = e.changedTouches[0].clientY;this.anchorX = (e.changedTouches[0].clientX this.startX) / 2;this.anchorY = (e.changedTouches[0].clientY this.startY) / 2;this.d2();},wrapTouchEnd() {this.radius = 20;// 手势坐标this.x = 300;this.y = 300;// 控制点坐标this.anchorX = 200;this.anchorY = 200;// 起点坐标this.startX = 100;this.startY = 100;},wrapTouchCancel() {let oCanvas = document.querySelector("#canvas"),ctx = oCanvas.getContext('2d');ctx.clearRect(0, 0, 360, 600);},d2() {let _this = this;let oCanvas = document.querySelector("#canvas");ctx = oCanvas.getContext('2d');ctx.strokeStyle = 'red';var distance = Math.sqrt(Math.pow(this.y - this.startY, 2) Math.pow(this.x - this.startX, 2));this.radius = -distance / 15 20;// 当气泡拉到一定程度,断开链条且链条消失//if (this.radius < 7) {if(distance > 250){ctx.clearRect(0, 0, 360, 600);ctx.beginPath();ctx.arc(this.x, this.y, 20, 0, 2 * Math.PI);ctx.strokeStyle = 'red';ctx.fill();console.log('end');return;}let sin = (this.x - this.startX) / distance;let cos = (this.y - this.startY) / distance;var x1 = this.startX - this.radius * cos;var y1 = this.startY this.radius * sin;var x2 = this.x - 20 * cos;var y2 = this.y 20 * sin;var x3 = this.x 20 * cos;var y3 = this.y - 20 * sin;var x4 = this.startX this.radius * cos;var y4 = this.startY - this.radius * sin;ctx.clearRect(0, 0, 360, 600);ctx.beginPath();ctx.moveTo(x1, y1);ctx.quadraticCurveTo(this.anchorX, this.anchorY, x2, y2);ctx.lineTo(x3, y3);ctx.quadraticCurveTo(this.anchorX, this.anchorY, x4, y4);ctx.lineTo(x1, y1);ctx.fillStyle = 'red'; ctx.stroke();ctx.fill();// 两圆圈ctx.beginPath();ctx.arc(this.startX, this.startY, this.radius, 0, 2 * Math.PI)ctx.arc(this.x, this.y, 20, 0, 2 * Math.PI)ctx.strokeStyle = 'red';ctx.fill();},}***
到这里,应该要结束了,但是我想说这控制点,其实还有其他选择,还有一种是是AC连线的中点,和BD连线的中点,具体的项目我晚一点附上地址。
by cs
贝塞尔曲线理解与应用相关推荐
- Android Studio Canvas 实现鼠标贝塞尔曲线拖尾特效
Android Studio Canvas 实现鼠标贝塞尔曲线拖尾特效 特效预览图 什么是贝塞尔曲线? 百度百科: 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图 ...
- Android Studio Canvas 实现鼠标贝塞尔曲线拖尾特效(富文本编辑器)
特效预览图 什么是贝塞尔曲线? 百度百科: 贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线.一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段 ...
- 教你直白的理解贝塞尔曲线???
序言 这是第一篇在掘金写的文章,写的不对的或者不好的地方希望友人能够指出便于修改与其他人分享. =.= 实在不善于表达啊 阿西吧... 一.什么是贝塞尔曲线? (百度百科你就知道) 贝塞尔曲线(Béz ...
- 简单粗暴通俗易懂的理解贝塞尔曲线
在Android开发和面试中(尤其是一些中高级岗位面试),面试官可能会问你自定义控件的详细内容,我们知道自定义控件这一块涉及到的内容很多,回答的越多越深入,那么面试的印象会更好.自定义控件涉及的内容比 ...
- 必须要理解掌握的贝塞尔曲线
在Android开发和面试中(尤其是一些中高级岗位面试),面试官可能会问你自定义控件的详细内容,我们知道自定义控件这一块涉及到的内容很多,回答的越多越深入,那么面试的印象会更好.自定义控件涉及的内容比 ...
- html5贝塞尔曲线,用canvas绘制一个曲线动画——深入理解贝塞尔曲线
前言 在前端开发中,贝赛尔曲线无处不在: 它可以用来绘制曲线,在svg和canvas中,原生提供的曲线绘制都是使用贝赛尔曲线 它也可以用来描述一个缓动算法,设置css的transition-timin ...
- android 贝塞尔曲线点击区域,白话经典贝塞尔曲线及其在 Android 中的应用
一.前言 谈到贝塞尔曲线可能不少人会浮现它高大上的数学公式.然而,在实际应用中,并不需要我们去完全理解或者推导出公式才能应用得上.实际情况是,即使真的只是一个学渣,我们应该也能很轻松的掌握贝塞尔曲线的 ...
- 贝塞尔曲线 花束直播点赞效果
1. 效果 先说一下这种效果都用到了哪些东西: 1.自定义View的一些基础: 2.随机数的使用: 3.插补器的使用: 4.属性动画的一些高级用法 5.贝塞尔曲线应用到属性动画 2.分析和实现 2.1 ...
- android 详解画图,android画图之贝塞尔曲线讲解详解
首先对于<赛贝尔曲线>不是很了解的童鞋,请自觉白度百科.google等等... 为了方便偷懒的童鞋,这里给个<贝赛尔曲线>百科地址,以及一段话简述<贝赛尔曲线>: ...
最新文章
- 工具栏对象GUI Status 与GUI Title
- Centos普通用户提权至ROOT
- js使用ajax发送post json,javascript-如何用ajaxpost复杂json数据
- [My B.S paper draft]我的本科答辩论文草稿
- python批量导入MongoDB数据库
- Git之深入解析如何重写提交历史
- 全国计算机等级考试题库二级C操作题100套(第61套)
- Unity3D笔记十七 Unity3D生命周期
- 3D建模吃香到底是真是假?
- python基础语法手册-python语法大全,python语法手册
- win10关机后cpu风扇还在转_win10电脑关机后cpu风扇还在转动_网站服务器运行维护...
- 1709意思_期货m1709是什么意思
- python3调用arcpy地理加权回归_混合地理加权回归python实现代码
- Oracle标准成本差异,标准成本与实际成本比较
- 微信小程序加入购物车动画
- 关于电脑显示器分辨率只有两个选项1024×768和800×600的解决办法,本人电脑亲测可用
- 彻底理解原型对象与原型链机制
- 浅谈:Java和C语言各自的学习难度
- Carla学习(一) 小车简单直线行走
- MessageBox提示框自动关闭