Cet article présente principalement les informations pertinentes sur la méthode d'ajustement en douceur des segments de polyligne à l'aide de la courbe de Bézier basée sur le canevas. L'éditeur pense que c'est assez bon, je vais donc le partager avec vous maintenant et le donner comme référence. Suivons l'éditeur et jetons un œil. J'espère que cela pourra aider tout le monde.
Écrivez-le d'abord
Cette fois, je vais partager comment "lisser" les bords et les coins des segments de polyligne dessinés dans le canevas, c'est-à-dire passer par le Bézier courbe Chaque point tracé remplace le graphique linéaire d'origine.
Pourquoi devrions-nous ajuster en douceur les segments de polyligne ?
Jetons d'abord un coup d'œil à l'effet de rendu du graphique linéaire sous Echarts :
Au début, je n'ai pas remarqué que ce segment de polyligne était en fait traversé par une courbe. Je pensais juste que c'était un simple dessin de points, alors au début j'ai implémenté le « simple (moche) facile (moche) ». " version comme celle-ci :
Ne faites pas attention au style. Le point clé est qu'après la mise en œuvre, j'ai découvert que la mise en œuvre d'Echarts semble être très fluide, ce qui a également déclenché des discussions ultérieures. Comment dessiner régulièrement des courbes douces ?
Rendu
Regardons l'implémentation finale de l'imitation :
Parce que je ne sais pas comment Echarts est implémenté en interne (escape
Ça a l'air très rond, très proche de notre idée originale. Voyons si la courbe passe par le point de dessin :
D'accord ! Regardons maintenant à nouveau notre implémentation.>Ajustement en douceur de la courbe de Bézier
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) //绘制各个数据点 }) ... }
La formule ci-dessus implique quatre points de coordonnées, le point actuel, le point précédent et les deux points suivants, et lorsque la valeur des coordonnées est celle indiquée dans la figure ci-dessous, elle est tracé La courbe est la suivante :
Cependant, il y a un problème car cette formule ne peut pas être utilisée pour le point de départ et le dernier point, mais cet article donne également un façon de gérer les valeurs limites. : Ainsi, lorsque vous changez la polyligne en une courbe lisse, calculez les valeurs limites et autres points de contrôle et remplacez-les dans la fonction Bessel. :Puisque le point que je traverse à chaque fois est le point actuel, mais la formule donnée dans l'article est un algorithme de point de contrôle qui calcule le point suivant, donc dans le code Dans l'implémentation, j'ai avancé le calcul de tous les points. Lorsque l'indice = 0, qui est le point initial, aucune courbe n'est nécessaire pour être tracée, car nous dessinons une courbe du point précédent au point actuel, et il n'y a aucune courbe vers 0 qui doit être tracée. À partir d'index = 1, nous pouvons commencer à dessiner normalement la courbe de 0 à 1, car il n'y a pas de deuxième point devant lorsque l'index = 1, c'est un point de valeur limite, ce qui nécessite un calcul spécial, et enfin Un point. Pour le reste, calculez simplement les coordonnées xy de AB selon la formule normale et remplacez-les dans la fonction Bessel.
Recommandations associées :
Canvas implémente des courbes de Bézier d'ordre élevé
//核心实现 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); //绘制出上一个点到当前点的贝塞尔曲线 })
Explication détaillée de l'application de la courbe de Bézier
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!