贝塞尔曲线

bezierCurveTo

在线工具

https://canvature.appspot.com/ [感觉这个好用一些]

https://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html

三次贝塞尔曲线必须包含三个点。前两个点(cp1x,cp1y)(cp2x,cp2y)是在三次贝塞尔曲线计算中使用的控制点,最后一个点(x,y)是曲线的终点。

bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y)

参量 类型 描述
cp1x number 第一个贝塞尔控制点的x坐标。
cp1y number 第一个贝塞尔控制点的y坐标。
cp2x number 第二个贝塞尔控制点的x坐标。
cp2y number 第二个贝塞尔控制点的y坐标。
X number 要添加到当前路径的点的x坐标。
y number 要添加到当前路径的点的y坐标。

  • (0,300)是曲线的起点。[这个用moveTo(x,y)叹气的点]

  • (150,0)即(cp1x,cp1y)是曲线的第一个控制位置。

  • (350,0)即(cp2x,cp2y)是曲线的第二个控制位置。

  • (500,300),即(x,y)是曲线的终点。

quadraticCurveTo

二次贝塞尔曲线,需要两个点,控制点和曲线的终点

  • (0,300)是曲线的起点。
  • (250,0)即(cp1x,cp1y)是曲线的控制位置。
  • (500,300),即(x,y)是曲线的终点。

绘制可视化的二次贝塞尔曲线demo

初始化

<style>
* {
margin: 0;
padding: 0;
} #app {
width: 100vw;
height: 100vh;
min-width: 1100px;
overflow: hidden;
font-family: 'Lato', sans-serif;
background-color: #ffffff;
} #canvas {
border: 1px solid #ccc;
position: absolute;
top: 20px;
left: 20px;
}
#code{
margin-top:20px;
margin-left:520px;
display: inline-block;
padding: 0.5em;
background: #002b36;
color: #839496;
min-height: 11rem;
font-family: Consolas;
font-size: 20px;
}
</style>
<div id="app">
<canvas id="canvas" width="500" height="500"></canvas>
<pre id="code">code</pre>
</div>
  let canvas = document.querySelector('#canvas')
// 代码文本
let code = document.querySelector('#code');
let ctx = canvas.getContext('2d'),
point,
style = {// 原点样式
radius: 10,
width: 2,
color: '#900',
fill: 'rgba(200,200,200,.5)',
arc1: 0,
arc2: 2 * Math.PI
},
drag = null,// 按下的时候 确认鼠标拿的那一个点
dPoint, // 拿到当前点的坐标
cpline = {
width: 1,
color: 'red'
},
curve = {
width: 6,
color: '#333'
}
// 初始化默认数据
function init() {
point = {// 鼠标的三个点
p1: { // moveTo
x: 100, y: 50
},
cp1: { // 贝塞尔第一个点
x: 100, y: 200
},
p2: {// 贝塞尔第二个点
x: 300, y: 200
}
}
}
// 代码文字
function showCode() {
if (code) {
code.firstChild.nodeValue =
"theCanvas = document.getElementById(\"canvas\");\n" +
"ctx = theCanvas.getContext(\"2d\")\n" +
"ctx.lineWidth = " + curve.width +
";\nctx.strokeStyle = \"" + curve.color +
"\";\nctx.beginPath();\n" +
"ctx.moveTo(" + point.p1.x + ", " + point.p1.y + ");\n" +
"ctx.quadraticCurveTo(" + point.cp1.x + ", " + point.cp1.y + ", " + point.p2.x + ", " + point.p2.y + ");"
+
"\nctx.stroke();"
;
}
}

画出页面

  function drawScreen() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.lineWidth = cpline.width;
ctx.strokeStyle = cpline.color;
ctx.beginPath()
ctx.moveTo(point.p1.x, point.p1.y)
ctx.lineTo(point.cp1.x, point.cp1.y)
ctx.lineTo(point.p2.x, point.p2.y)
ctx.stroke();
//中间的弧度
ctx.lineWidth = curve.width;
ctx.strokeStyle = curve.color;
ctx.beginPath();
ctx.moveTo(point.p1.x, point.p1.y)
ctx.quadraticCurveTo(point.cp1.x, point.cp1.y, point.p2.x, point.p2.y)
ctx.stroke();
// 三个原点
for (let p in point) {
console.log(p);
ctx.lineWidth = style.width;
ctx.strokeStyle = style.color;
ctx.fillStyle = style.fill;
ctx.beginPath();
ctx.arc(point[p].x, point[p].y, style.radius, style.arc1, style.arc2, true)
ctx.fill();
ctx.stroke();
}
showCode()
}

拿到鼠标的鼠标

  // 鼠标的坐标
function MousePos(event) {
event = event ? event : window.event;
return {
x: event.pageX - canvas.offsetLeft,
y: event.pageY - canvas.offsetTop
}
}

问个来了,当我们鼠标移动的时候怎么确定鼠标放在圆里面啦

这里又运用了初中数学知识圆的标准方程

 canvas.addEventListener('mousedown', dragStart, false);
canvas.addEventListener('mousemove', dragging, false);
canvas.addEventListener('mouseup', dragEnd, false);
canvas.addEventListener('mouseout', dragEnd, false);

这里我们需要知道点应该在圆内

  鼠标按下的时候
function dragStart(e) {
e = MousePos(e)
let dx, dy;
// 找到鼠标拿到哪一个点
for (let p in point) {
dx = point[p].x - e.x;
dy = point[p].y - e.y;
if ((dx ** 2) + (dy ** 2) < style.radius ** 2) {
// 确定了拿到那个点
drag = p;
// 确定了拿到点的鼠标
dPoint=e;
canvas.style.cursor = 'move';
return;
}
}
}

鼠标移动

 function dragging(e) {
// 这个是用来判断有按下的参数的时候触发
if (drag) {
e = MousePos(e);
// 鼠标的x - 开始鼠标的点
point[drag].x += e.x - dPoint.x;
point[drag].y += e.y - dPoint.y;
dPoint = e;
drawScreen();
}
}

鼠标离开

function dragEnd(e) {
drag = null;
canvas.style.cursor = 'default';
drawScreen();
}

See the Pen Canvas: Quadratic Curve 二次曲线 by 973782523
(@973782523) on CodePen.

再二次贝塞尔曲线的基础上绘制三次贝塞尔曲线

修改1,给html添加一个class

  <canvas id="canvasOne" width="500" height="500" class="bezier"></canvas>

在初始化数据的时候,添加第二个点

 // 初始化默认数据,默认不传参数三次贝塞尔曲线,不默认二次
function init(quadratic) {
....
if (quadratic) {
point.cp1={
x:250,y:100
}
}else{
point.cp1={
x:150,y:100
}
point.cp2={
x:350,y:100
} }

画出屏幕的时候

function drawScreen() {
...
ctx.lineTo(point.cp1.x, point.cp1.y)
// 判断是否有第二个点
if (point.cp2) {
ctx.moveTo(point.p2.x,point.p2.y)
ctx.lineTo(point.cp2.x,point.cp2.y)
}else{
ctx.lineTo(point.p2.x, point.p2.y);
}
...
ctx.moveTo(point.p1.x, point.p1.y)
// 确认二次还是三次
if (point.cp2) {
ctx.bezierCurveTo(point.cp1.x, point.cp1.y, point.cp2.x, point.cp2.y, point.p2.x, point.p2.y)
}else{
ctx.quadraticCurveTo(point.cp1.x, point.cp1.y, point.p2.x, point.p2.y);
}
...
}

修改代码显示的部分

 +(point.cp2 ?
"ctx.bezierCurveTo("+point.cp1.x+", "+point.cp1.y+", "+point.cp2.x+", "+point.cp2.y+", "+point.p2.x+", "+point.p2.y+");" :
"ctx.quadraticCurveTo("+point.cp1.x+", "+point.cp1.y+", "+point.p2.x+", "+point.p2.y+");"
) +

See the Pen Canvas: Bezier Curve by 973782523
(@973782523) on CodePen.

canvas基础[二]教你编写贝塞尔曲线工具的更多相关文章

  1. [js高手之路] html5 canvas系列教程 - arcTo(弧度与二次,三次贝塞尔曲线以及在线工具)

    之前,我写了一个arc函数的用法:[js高手之路] html5 canvas系列教程 - arc绘制曲线图形(曲线,弧线,圆形). arcTo: cxt.arcTo( cx, cy, x2, y2, ...

  2. 用Canvas实现Photoshop的钢笔工具(贝塞尔曲线)

    前两天在用Canvas实现一个绘制路径的小功能.做完之后发现加以完善可以“复刻”一下PS里面的钢笔工具. PS里的钢笔工具对我来说是PS中最好用的工具! 所以本文主要介绍如何用Canvas来实现Pho ...

  3. 贝塞尔曲线(面)二三维可视化(Three+d3)

    贝塞尔曲线(面)二三维可视化(Three+d3) 在学完 games101 几何后开始实践,可视化贝塞尔曲线 我想实现三维的贝塞尔曲线,用 threejs,但是 threejs 控制太麻烦了,因此,我 ...

  4. canvas基础之旅

    canvas 主要使用2D rendering context  API 实现其功能和特效. canvas 一般浏览器都支持,但在ie9之前的是不支持的.(解决办法:添加IxplorerCanvas ...

  5. Android 自定义View高级特效,神奇的贝塞尔曲线

    效果图 效果图中我们实现了一个简单的随手指滑动的二阶贝塞尔曲线,还有一个复杂点的,穿越所有已知点的贝塞尔曲线.学会使用贝塞尔曲线后可以实现例如QQ红点滑动删除啦,360动态球啦,bulabulabul ...

  6. Android - Animation 贝塞尔曲线之美

    概述 贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计.贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau演算 ...

  7. SVG 学习<八> SVG的路径——path(2)贝塞尔曲线命令、光滑贝塞尔曲线命令

    目录 SVG 学习<一>基础图形及线段 SVG 学习<二>进阶 SVG世界,视野,视窗 stroke属性 svg分组 SVG 学习<三>渐变 SVG 学习<四 ...

  8. 第154天:canvas基础(一)

    一.canvas简介 ​ <canvas> 是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素.它可以用来制作照片集或者制作简单(也不是 ...

  9. Canvas 线性图形(三):曲线

    前言 画曲线要用到二次贝塞尔曲线或三次贝塞尔曲线.贝塞尔曲线是计算机图形学中相当重要的参数曲线,在一些比较成熟的位图软件中也有贝塞尔曲线工具,如 PhotoShop. 二次贝塞尔曲线 二次贝塞尔曲线在 ...

随机推荐

  1. RHSA-2017:3075-重要: wget 安全更新(代码执行)

    [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 7.2.1511 (Core) 修复命令: 使用root账号登陆She ...

  2. spring-boot-route(十四)整合Kafka

    在上一章中SpringBoot整合RabbitMQ,已经详细介绍了消息队列的作用,这一种我们直接来学习SpringBoot如何整合kafka发送消息. kafka简介 kafka是用Scala和Jav ...

  3. redis 开启AOF

    找到redis 安装目录 例如 cd /usr/local/redis 打开 redis.conf  修改以下参数: # vi /usr/local/redis/etc/redis.conf appe ...

  4. DM9000裸机驱动程序设计

    对于任何一个硬件模块的设计,首先第一步都是要先了解硬件本身后,再开始程序的软件设计.而由于DM9000的芯片文档内容很多,要驱动好网卡,需要很长时间,特别对于新手比较困难,所以可以参考linux内核代 ...

  5. HCIA——应用层常用协议

    DNS协议 1.什么是DNS协议呢? DNS协议简单来说就是为IP取一个别名的系统(叫域名如www.baidu.com),最终目的是便于我们记忆. 一个域名可能有多个IP,同样一个IP可能也会有多个域 ...

  6. centos8平台使用lsof

    一,lsof的用途 lsof,List Open Files 列出当前系统打开文件的工具. 在linux环境下,任何事物都以文件的形式存在, 所以lsof通过文件不仅仅可以访问常规数据,还可以访问网络 ...

  7. OpenCV开发笔记(七十一):红胖子8分钟带你深入级联分类器训练

    前言   红胖子,来也!  做图像处理,经常头痛的是明明分离出来了(非颜色的),分为几块区域,那怎么知道这几块区域到底哪一块是我们需要的,那么这部分就涉及到需要识别了.  识别可以自己写模板匹配.特征 ...

  8. js和vue方法的相互调用(iframe父子页面的方法相互调用)。

    项目是前后端不分离的,模板引擎使用的JSP. 但是使用了Vue+ElementUI,这里列举一些常用的调用方式,有时候可能. 在js里调用vue方法 我们需要把方法注册到vue对象之外的页面,所以对与 ...

  9. 用node.js给C#写一个数据表的实体类生成工具

    虽然微软提供了T4模板,但是我感觉非常难用.哪儿比得上直接用脚本来写模板来的爽. 因为要给一个老项目做周边的工具,需要连接到数据库. 我习惯性用EntityFrameworkCore来做,因为毕竟从出 ...

  10. js工厂函数

    经常会遇到工厂函数这个词,不过javascript不是严格的面向对象语言,不像java,C#拥有类,所以工厂函数会变得比较模糊. 简单来讲,就是创建一个可以用来创建实例的函数,这样每一个实例都是独立的 ...