实现原理

依靠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. tensorboard merge报错_什么是TensorBoard?
  2. 直播卡顿原因详解及优化
  3. oracle asm dd命令,使用dd命令复制ASM磁盘的spfile
  4. ubuntu12.04下NFS链接开发板并测试交叉编译的第一个应用
  5. cell重用的几种方式
  6. H.264入门级概念之I、B、P帧
  7. java技术不行有复试怎么办_复试答不上来怎么办?记住这四点不慌!
  8. 网吧无盘最新服务器配置,80-100台网吧无盘服务器配置方案建议
  9. 10068---谈谈Runtime类中的freeMemory,totalMemory,maxMemory几个方法
  10. Bootstrap插件(一)——模态框(modal.js)
  11. 《金阁寺》金阁美之于幻想,我用摧毁它来成就其美
  12. [No000019A]【波浪理论精典教学课程】
  13. 微信截图不能截微信界面
  14. 数据库优化之降龙十八掌
  15. JM模型I帧帧内预测流程
  16. 送你一个励志故事(转载)
  17. RemoteViews的使用
  18. linux网络编程--Web Server and HTTP
  19. 餐厅点餐系统需求分析
  20. prepay id为空php,微信公众号支付踩坑笔记

热门文章

  1. JavaScript 介绍
  2. word论文格式管理和孤行控制
  3. python编程 迷你世界_迷你世界迷你编程下载
  4. mysql表disable_[MySQL优化案例]系列 -- DISABLE/ENABLE KEYS的作用
  5. OpenPose(一):根据关键点生成置信图(Confidence Map)
  6. Kaggle: Tweet Sentiment Extraction 方法总结 Part 1/2: 常用方法总结
  7. 可拖拽排序的GridView(高仿今日头条编辑频道效果)
  8. VMware虚拟机 扩展Ubuntu系统磁盘空间方法
  9. “东数西算”取得新进展,发改委等四部门发文构建国家算力网络体系 | 产业区块链发展周报...
  10. Global Mapper20生成可以进CAD的国家2000坐标系的DXF等高线