canvas使用贝塞尔曲线平滑拟合折线段的方法详解

本文主要介绍了基于canvas使用贝塞尔曲线平滑拟合折线段的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能帮助到大家。

写在最前

本次分享一下在canvas中将绘制出来的折线段的棱角“磨平”,也就是通过贝塞尔曲线穿过各个描点来代替原有的折线图。

为什么要平滑拟合折线段

先来看下Echarts下折线图的渲染效果:

canvas使用贝塞尔曲线平滑拟合折线段的方法详解 

一开始我没注意到其实这个折线段是曲线穿过去的,只认为是单纯的描点绘图,所以起初我实现的“简(丑)易(陋)”版本是这样的:

canvas使用贝塞尔曲线平滑拟合折线段的方法详解

不要关注样式,重点就是实现之后才发现看起来人家Echarts的实现描点非常的圆滑,也由此引发了之后的探讨。怎么有规律的画平滑曲线?

效果图

先来看下最终模仿的实现:

因为我也不知道Echarts内部怎么实现的(逃

canvas使用贝塞尔曲线平滑拟合折线段的方法详解 

canvas使用贝塞尔曲线平滑拟合折线段的方法详解 

看起来已经非常圆润了,和我们最初的设想十分接近了。再看下曲线是否穿过了描点:

canvas使用贝塞尔曲线平滑拟合折线段的方法详解 

好的!结果很明显现在来重新看下我们的实现方式。

实现过程

绘制折线图

贝塞尔曲线平滑拟合

模拟数据

var data = [Math.random() * 300];        for (var i = 1; i < 50; i++) { //按照echarts            data.push(Math.round((Math.random() - 0.5) * 20 + data[i - 1]));        }        option = {            canvas:{                id: 'canvas'            },            series: {                name: '模拟数据',                itemStyle: {                    color: 'rgb(255, 70, 131)'                },                areaStyle: {                    color: 'rgb(255, 158, 68)'                },                data: data            }        };

绘制折线图

首先初始化一个构造函数来放置需要用到的数据:

function LinearGradient(option) {    this.canvas = document.getElementById(option.canvas.id)    this.ctx = this.canvas.getContext('2d')    this.width = this.canvas.width    this.height = this.canvas.height    this.tooltip = option.tooltip    this.title = option.text    this.series = option.series //存放模拟数据}

绘制折线图:

LinearGradient.prototype.draw1 = function() { //折线参考线    ...     //要考虑到canvas中的原点是左上角,    //所以下面要做一些换算,    //diff为x,y轴被数据最大值和最小值的取值范围所平分的等份。    this.series.data.forEach(function(item, index) {        var x = diffX * index,            y = Math.floor(self.height - diffY * (item - dataMin))        self.ctx.lineTo(x, y) //绘制各个数据点    })    ...}

贝塞尔曲线平滑拟合

贝塞尔曲线的关键点在于控制点的选择,这个网站可以动态的展现控制点不同而绘制的不同的曲线。而对于控制点的计算。。作者还是选择了百度一下毕竟数学不好:)。具体算法有兴趣的同学可以深入了解下,现在直接说下计算控制点的结论。

canvas使用贝塞尔曲线平滑拟合折线段的方法详解

上面的公式涉及到四个坐标点,当前点,前一个点以及后两个点,而当坐标值为下图展示的时候绘制出来的曲线如下所示:

canvas使用贝塞尔曲线平滑拟合折线段的方法详解

不过会有一个问题就是起始点和最后一个点不能用这个公式,不过那篇文章也给出了边界值的处理办法:

canvas使用贝塞尔曲线平滑拟合折线段的方法详解 

所以在将折线换成平滑曲线的时候,将边界值以及其他控制点计算好之后代入到贝塞尔函数中就完成了:

//核心实现this.series.data.forEach(function(item, index) { //找到前一个点到下一个点中间的控制点    var scale = 0.1 //分别对于ab控制点的一个正数,可以分别自行调整    var last1X = diffX * (index - 1),        last1Y = Math.floor(self.height - diffY * (self.series.data[index - 1] - dataMin)),        //前一个点坐标        last2X = diffX * (index - 2),        last2Y = Math.floor(self.height - diffY * (self.series.data[index - 2] - dataMin)),        //前两个点坐标        nowX = diffX * (index),        nowY = Math.floor(self.height - diffY * (self.series.data[index] - dataMin)),        //当期点坐标        nextX = diffX * (index + 1),        nextY = Math.floor(self.height - diffY * (self.series.data[index + 1] - dataMin)),        //下一个点坐标        cAx = last1X + (nowX - last2X) * scale,        cAy = last1Y + (nowY - last2Y) * scale,        cBx = nowX - (nextX - last1X) * scale,        cBy = nowY - (nextY - last1Y) * scale     if(index === 0) {        self.ctx.lineTo(nowX, nowY)        return    } else if(index ===1) {        cAx = last1X + (nowX - 0) * scale        cAy = last1Y + (nowY - self.height) * scale     } else if(index === self.series.data.length - 1) {        cBx = nowX - (nowX - last1X) * scale        cBy = nowY - (nowY - last1Y) * scale    }         self.ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowY);        //绘制出上一个点到当前点的贝塞尔曲线    })

由于我每次遍历的点都是当前点,但是文章中给出的公式是计算会知道下一个点的控制点算法,故在代码实现中我将所有点的计算挪前了一位。当index = 0时也就是初始点是不需要曲线绘制的,因为我们绘制的是从前一个点到当前点的曲线,没有到0的曲线需要绘制。从index = 1开始我们就可以正常开始绘制,从0到1的曲线,由于index = 1时是没有在他前面第二个点的故其属于边界值点,也就是需要特殊进行计算,以及最后一个点。其余均按照正常公式算出AB的xy坐标代入贝塞尔函数即可。

相关推荐:

canvas实现高阶贝塞尔曲线

使用CSS做贝塞尔曲线

贝塞尔曲线的应用详解

以上就是canvas使用贝塞尔曲线平滑拟合折线段的方法详解的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1545506.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月21日 17:01:27
下一篇 2025年12月21日 17:01:48

相关推荐

  • HTML5里Canvas常用的绘图技巧

    在h5里我们会常用到canvas这个元素来绘制图形。那么我们今天就来介绍一下canvas怎么使用,canvas在哪些情形下可以使用。以及canvas的绘画技巧 canvas 用于在页面上 绘制图形 canvas概述: html5 canvas元素和javascript配合使用在页面上绘制图形 can…

    好文分享 2025年12月21日
    000
  • 如何解决html5 canvas 绘制字体、图片与图形模糊问题

    html5 canvas 绘制字体、图片与图形模糊问题 发生情况 多出现在高dpi设备,这意味着每平方英寸有更多的像素,如手机,平板电脑。当然很多高端台式电脑也有高分辨率高dpi的显示器。  canvas在浏览器中的缩放原理 如果没有设置style那么就以html的属性width,height作为尺…

    好文分享 2025年12月21日
    000
  • 实例详解html5使用canvas实现图片下载功能

    这篇文章主要介绍了html5使用canvas实现图片下载功能的示例代码,非常具有实用价值,需要的朋友可以参考下 最近项目中需要实现一个下载图片的功能(如下图) 一开始考虑使用a标签的download属性进行下载: 下载海报 但是通过测试,发现再safari中,下载的文件不能带上拓展名,所以只好换一个…

    2025年12月21日
    000
  • 使用Canvas实现高性能的动画效果

    使用requestAnimationFrame实现流畅动画,通过减少重绘区域、预渲染静态内容到离屏Canvas、避免重排与GPU开销,优化绘制节奏与资源管理,从而提升Canvas动画性能。 在现代网页开发中,实现流畅且高性能的动画效果是提升用户体验的关键。当需要处理大量图形或复杂视觉效果时,Canv…

    2025年12月21日
    000
  • JavaScript Canvas性能优化

    答案:优化Canvas性能需减少绘制调用、仅重绘变化区、避免频繁像素操作、使用requestAnimationFrame、优化图像绘制。核心是“少画、准画、快画”,通过合并路径、分层管理、缓存和预加载等手段提升渲染效率。 在使用 JavaScript Canvas 进行图形绘制时,随着绘制内容增多,…

    2025年12月20日
    000
  • JavaScript Canvas高级图形编程

    掌握Canvas高级编程需理解复杂路径、变换状态、离屏渲染、像素操作与动画优化。首先,使用路径和贝塞尔曲线绘制自定义图形,quadraticCurveTo和bezierCurveTo分别支持单双控制点曲线,适合创建平滑轮廓或模拟自然轨迹。其次,通过translate、rotate、scale进行坐标…

    2025年12月20日
    000
  • 如何利用JavaScript与Canvas进行高性能图形绘制?

    通过局部重绘减少开销,仅清除变化区域;2. 利用离屏Canvas预渲染复杂图形,提升绘制效率;3. 批量处理相同样式,降低状态切换成本;4. 使用requestAnimationFrame实现流畅动画调度。综合策略可显著提升Canvas性能。 在Web前端开发中,JavaScript结合Canvas…

    2025年12月20日
    000
  • 如何实现一个基于Canvas的2D游戏引擎?

    答案:基于Canvas的2D游戏引擎通过初始化渲染上下文、构建游戏循环、设计GameObject基类、管理图层渲染、处理用户输入与碰撞检测,实现结构清晰、可扩展的轻量级框架,支持后续添加动画、音效与场景管理模块。 实现一个基于Canvas的2D游戏引擎,核心是构建一套可复用、结构清晰的系统,用来处理…

    2025年12月20日
    000
  • 如何用Canvas实现高性能的实时数据可视化?

    实时数据可视化首选Canvas因其直接操作像素的优势。通过减少重绘区域与频率、使用离屏Canvas预渲染静态内容、精简绘图操作并分组绘制、结合数据降采样与视口裁剪,可显著提升性能。核心是“少画、快画、聪明地画”,实现每秒上千次更新的高效渲染。 实时数据可视化对性能要求高,Canvas 是比 DOM …

    2025年12月20日
    000
  • 前端可视化:使用Canvas实现高级动画

    答案:Canvas提供像素级控制,适合高性能、复杂动画如粒子系统和物理模拟,需通过requestAnimationFrame实现流畅动画循环,并采用脏矩形、对象池等优化策略提升性能。 前端可视化,当我们谈到高级动画时,Canvas绝对是一个绕不开的话题。它不像CSS动画那样声明式,也不像SVG那样面…

    2025年12月20日
    100
  • Canvas的基本用法是什么

    canvas的性能优化策略包括:1. 使用requestanimationframe控制重绘频率,避免不必要的刷新;2. 采用离屏canvas或脏矩形技术,只重绘变化区域;3. 减少像素操作,通过imagedata对象批量处理像素数据;4. 缓存静态内容,避免重复绘制;5. 优先使用高效的api如d…

    2025年12月20日
    000
  • js如何操作canvas

    canvas是html中用于绘图的元素,通过javascript操作其2d上下文可实现绘图与动画。1. 获取canvas上下文:const canvas = document.getelementbyid(‘mycanvas’); const ctx = canvas.get…

    2025年12月20日 好文分享
    000
  • js 怎样绘制Canvas图形

    canvas绘制的基础要素包括:1. 渲染上下文,即通过getcontext(‘2d’)获取的绘图环境,是所有绘制操作的基础;2. 路径,使用beginpath()开始,通过moveto()、lineto()、arc()等方法定义图形轮廓,再用fill()或stroke()填…

    2025年12月20日
    000
  • js如何实现粒子动画效果 Canvas打造炫酷粒子特效

    如何实现粒子动画效果?1.使用javascript操作canvas,初始化canvas元素并获取上下文;2.定义particle类,包含位置、速度、大小、颜色等属性,并实现draw()和update()方法;3.创建粒子数组,随机生成多个粒子实例;4.使用requestanimationframe创…

    2025年12月20日 好文分享
    000
  • js如何实现视频截图功能 基于Canvas的视频截图方案

    视频截图是通过js配合canvas实现的。首先获取视频元素,接着创建canvas并设置其尺寸与视频一致,然后获取上下文并绘制视频帧到canvas上,最后将canvas内容转换为data url并显示图片。可能遇到的问题包括截图黑色、跨域问题、视频未播放等,需确保视频加载完成、服务器配置cors或部署…

    2025年12月20日 好文分享
    000
  • js如何实现手写签名 基于Canvas的手写签名实现

    手写签名功能可通过js结合canvas实现,核心步骤为监听鼠标或触摸事件并绘制轨迹。具体包括:1. 监听mousedown/touchstart开始绘制,moveto记录起始点;2. 监听mousemove/touchmove持续绘制线条,使用lineto连接坐标点;3. stroke方法描边路径;…

    2025年12月20日 好文分享
    000
  • js怎么实现画板涂鸦功能 Canvas实现自由绘制画板

    实现javascript画板涂鸦功能的核心在于利用canvas元素与鼠标或触摸事件结合进行绘图。具体步骤如下:1. 创建包含canvas和控制元素的html结构;2. 使用getcontext(‘2d’)获取2d渲染上下文;3. 监听mousedown、mousemove、m…

    2025年12月20日 好文分享
    000
  • js如何实现粒子动画 Canvas粒子动画效果制作指南

    canvas粒子动画效果通过canvas绘制能力与javascript定时器及数学函数结合实现。首先创建canvas元素并获取2d上下文,接着定义particle类设置粒子属性,然后创建多个particle实例存入数组,最后使用requestanimationframe循环更新并重绘画布。为优化性能…

    2025年12月20日 好文分享
    000
  • python中canvas提供哪些功能

    提供的功能有绘制基本图形、绘制复杂图形、显示图像、事件处理、样式和颜色、坐标变换、动画和过渡效果等。详细介绍:1、绘制基本图形:Canvas组件通常提供绘制直线、矩形、圆、椭圆等基本图形的方法;2、绘制复杂图形:除了基本图形,Canvas组件还提供绘制复杂图形的方法,例如多边形、曲线、折线等;3、显…

    2025年12月13日
    000
  • 如何使用CSS实现数据标记连线—canvas绘制技巧

    要使用css实现数据标记连线,主要有两种方案。1. css定位与边框模拟连线:通过绝对定位和transform: rotate()模拟直线连线,适用于静态节点和简单样式;2. canvas绘制连线:利用canvas api实现更复杂的连线效果,如曲线、箭头、虚线等,并支持动态更新和性能优化。canv…

    2025年12月2日 web前端
    000

发表回复

登录后才能评论
关注微信