实现原理

依靠canvas 2d的api方法context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);来实现绘制曲线。

实现目标

具体过程

代码

Vector2,一般用来表示向量,但有的时候也用来当作点来进行一计算。

var Vector2 = function(x, y) {this.x = x;this.y = y;
}
Vector2.prototype = {"length": function () {return Math.sqrt(this.x * this.x + this.y * this.y);},"normalize": function () {var inv = 1 / this.length();return new Vector2(this.x * inv, this.y * inv);},"add": function (v) {return new Vector2(this.x + v.x, this.y + v.y);},"multiply": function (f) {return new Vector2(this.x * f, this.y * f);},"dot": function (v) {return this.x * v.x + this.y * v.y;},"angle": function (v) {return Math.acos(this.dot(v) / (this.length() *v.length())) * 180 / Math.PI;}
}
  • length求向量长度

  • normalize转单位向量

  • add向量叠加

  • multiply向量翻倍

  • dot内积

  • angle方法用来求两个向量的夹角

    核心方法 根据path上的点,求出所有贝塞尔曲线控制点。

function getControlPoint(path) {var rt = 0.3;var i = 0, count = path.length - 2;var arr = [];for (; i < count; i++) {var a = path[i], b = path[i + 1], c = path[i + 2];var v1 = new Vector2(a.x - b.x, a.y - b.y);var v2 = new Vector2(c.x - b.x, c.y - b.y);var v1Len = v1.length(), v2Len = v2.length();var centerV = v1.normalize().add(v2.normalize()).normalize();var ncp1 = new Vector2(centerV.y, centerV.x * -1);var ncp2 = new Vector2(centerV.y * -1, centerV.x);if (ncp1.angle(v1) < 90) {var p1 = ncp1.multiply(v1Len * rt).add(b);var p2 = ncp2.multiply(v2Len * rt).add(b);arr.push(p1, p2)} else {var p1 = ncp1.multiply(v2Len * rt).add(b);var p2 = ncp2.multiply(v1Len * rt).add(b);arr.push(p2, p1)}}return arr;
}

案例


代码:


<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<canvas id="c" width="1000" height="800"></canvas><script>var ctx=document.getElementById("c").getContext("2d");var points =[{ x: 50, y: 50 }, { x: 200, y: 100 }, { x: 250, y: 50 }, { x: 350, y: 150 }, { x: 370, y: 100 }, { x: 570, y: 200 }];ctx.lineWidth=3;ctx.strokeStyle="#cccccc";drawPath(points,ctx);function drawPath(path,ctx){var Vector2 = function(x, y) {this.x = x;this.y = y;};Vector2.prototype = {"length": function () {return Math.sqrt(this.x * this.x + this.y * this.y);},"normalize": function () {var inv = 1 / this.length();return new Vector2(this.x * inv, this.y * inv);},"add": function (v) {return new Vector2(this.x + v.x, this.y + v.y);},"multiply": function (f) {return new Vector2(this.x * f, this.y * f);},"dot": function (v) {return this.x * v.x + this.y * v.y;},"angle": function (v) {return Math.acos(this.dot(v) / (this.length() *v.length())) * 180 / Math.PI;}};function getControlPoint(path) {var rt = 0.3;var i = 0, count = path.length - 2;var arr = [];for (; i < count; i++) {var a = path[i], b = path[i + 1], c = path[i + 2];var v1 = new Vector2(a.x - b.x, a.y - b.y);var v2 = new Vector2(c.x - b.x, c.y - b.y);var v1Len = v1.length(), v2Len = v2.length();var centerV = v1.normalize().add(v2.normalize()).normalize();var ncp1 = new Vector2(centerV.y, centerV.x * -1);var ncp2 = new Vector2(centerV.y * -1, centerV.x);if (ncp1.angle(v1) < 90) {var p1 = ncp1.multiply(v1Len * rt).add(b);var p2 = ncp2.multiply(v2Len * rt).add(b);arr.push(p1, p2)}else {var p1 = ncp1.multiply(v2Len * rt).add(b);var p2 = ncp2.multiply(v1Len * rt).add(b);arr.push(p2, p1)}}return arr;}var point=getControlPoint(path);console.log(point);var points = path;ctx.beginPath();var int=0;for(var i =0;i<points.length;i++){if(i==0){ctx.moveTo(points[0].x,points[0].y);ctx.quadraticCurveTo(point[0].x,point[0].y,points[1].x,points[1].y);int=int+1;}else if(i<points.length-2){ctx.moveTo(points[i].x,points[i].y);ctx.bezierCurveTo(point[int].x,point[int].y,point[int+1].x,point[int+1].y,points[i+1].x,points[i+1].y);int+=2;}else if(i==points.length-2){ctx.moveTo(points[points.length-2].x,points[points.length-2].y);ctx.quadraticCurveTo(point[point.length-1].x,point[point.length-1].y,points[points.length-1].x,points[points.length-1].y);}}ctx.stroke();ctx.closePath();ctx.beginPath();for(i =0;i<points.length;i++){ctx.beginPath();ctx.arc(points[i].x,points[i].y,5,0,2*Math.PI);ctx.fillStyle="#cccccc";ctx.fill();ctx.closePath();}}
</script>
</body>
</html>

嫌麻烦直接将值传入,调用drawPath()方法,就可以实现效果。

代码转至:https://www.cnblogs.com/iamzhanglei/p/4809431.html

canvas 将折线转换成曲线相关推荐

  1. 使用的是html5的canvas将文字转换成图片

    当前功能的运用场景是:用户需要传文件给他人,在用户选择文件之后需要显示一个文件图标和所选文件的名称. 当前代码部分是摘自网上,但是已经忘记在什么地方获取的,如有侵权联系小弟后自当删除. 注意:必须在h ...

  2. 使用Canvas把照片转换成素描画

    一.引子 话说前阵子想把一张照片转换成素描,然后发个微博.结果发现mac上没找到能直接转换素描的软件(PS不算,可要好几步呢),坑爹啊--google 了下,Web上竟然也是没有直接把照片转换成素描的 ...

  3. 使用canvas画图,转换成图片路径

    let canvas= document.createElement('canvas'); //创建canvas 对象canvas.width = 500; canvas.height = 500;l ...

  4. React生成二维码并将canvas转换成img格式

    1. 导入包生成二维码 npm install qrcode.react npm包链接: https://www.npmjs.com/package/qrcode.react 1.1 生成二维码: i ...

  5. 前端使用canvas实现昵称首个文字转换成图片功能

    最近在用腾讯会议的时,看到要是没有设置自定义头像时会有个默认头像,就是昵称的第一个字母.上班摸鱼时突然想用原生的画布实现这个功能. canvas有能够转换成bas64的功能,说以直接写js代码就行,直 ...

  6. 如何使用Python语言将测量数据曲线动起来? matplotlib转换成 GIF文件

    简 介: 本文就如何使用的Python中的Matplotlib绘制的图运动起来进行讨论.实际上是生成多个图片,将它们合成一个动图.编写了PlotGIF函数,将matplotlib绘制的图片存储,然后生 ...

  7. 【Python】递归绘制科赫曲线及科赫雪花及转换成可执行文件打包

    科赫曲线 ----------- 绘制科赫曲线 import turtle def koch(size, n):if n == 0:turtle.fd(size)else:for angle in [ ...

  8. 三次Bezier曲线/B样条曲线转换成隐函数方程的方法

    引言 这个问题在我做相关研究的时候一直很困惑,研究过很久很久,而且网上真的很难找到这方面的答案,在知乎问过(知乎那个问题就是我问的),无大佬知道.后来无意在看别人的硕士论文发现了其实是有方法的. 问题 ...

  9. Android Canvas画布上放图片,保存图片为黑色,转换成PNG格式还是黑色,画布设置白色则图片不显示,特例出完美的解决办法

    网上都说 bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);替换成bitmap.compress(Bitmap.CompressFormat.J ...

最新文章

  1. 树hash树BtreeB+tree
  2. 后端直接跳转前端页面_WEB前端开发中页面跳转等待时间过长如何解决?
  3. 解析xml数据存入bean映射到数据库的 需求解决过程
  4. java有道云,有道云笔记链接——JAVA面向对象的学习
  5. 超硬核!躺进BAT以后我总结了出现最多的15道数组题
  6. 初学者选黑卡还是微单_零基础,一篇读懂单反和微单
  7. 转载-----Java Longest Palindromic Substring(最长回文字符串)
  8. 人体特征点检测解决方案
  9. KMP模式匹配 三(弦)
  10. cookies时效由谁决定_胎儿的性别,是什么时候定下来的,又是由谁决定的?
  11. zen brush 2 android,Zen Brush 2 才不仅仅是个练字 App 那么简单
  12. 《Web程序设计》学习笔记1——web基础知识简述
  13. 人体神经元细胞分布图片,神经元人体分布大图
  14. AM5728设备数的描述
  15. 计算机科学与技术的年崭,计算机科学与信息技术学院举行2019届毕业典礼暨表彰大会...
  16. 如何在WORD中插入可播放的视频
  17. Centos7下安装FastDFS服务
  18. Keil5新建工程项目
  19. 你要怎么切你的披萨?
  20. 孤立词语音识别(3)——计算MFCC系数

热门文章

  1. 记一次 Intellij IDEA 的外观改造过程 - 好看的代码样式 + 炫酷的键入效果
  2. Ruby学习之日期 时间(Date Time)范围(Range)的定义和使用
  3. 中国石油大学《中国当代散文》共享课程考试
  4. 去中心化金融的无常损失
  5. odoo12企业版修改邮箱配置
  6. java 完全匹配_全序列匹配(java)
  7. lazada按关键字搜索商品
  8. CVPR 2021 | Involution:超越卷积和自注意力的神经网络新算子
  9. 新手使用APICloud可视化开发搭建商城主页
  10. 如何修改游戏服务器ip地址吗,怎么修改游戏服务器ip地址