Cette fois, je vais vous expliquer comment lisser les bords et les coins des segments de polyligne dessinés dans le canevas, c'est-à-dire remplacer le graphique polyligne d'origine en faisant passer la courbe de Bézier par chaque point de dessin.
Pourquoi des segments de polyligne à ajustement lisseRegardons d'abord l'effet de rendu du graphique en courbes sous Echarts :
Au début, je n'avais pas remarqué que ce segment de polyligne était en fait une courbe qui le traversait. Je pensais juste que c'était un simple dessin de points, donc la version simple (moche) et facile (moche) que j'ai implémentée au début ressemblait à ceci :
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 ?
rendus
Voyons d’abord la mise en œuvre de l’imitation finale :
Parce que je ne sais pas comment Echarts est implémenté en interne (évasion
Cela semble déjà très arrondi, très proche de notre vision originale. Voyons si la courbe passe par le point de dessin :
D'ACCORD! Le résultat est évident. Examinons maintenant notre implémentation.
Processus de mise en œuvre
données simulées
var data = [Math.random() * 300]; for (var i = 1; i < 50; i++) { //Suivre les graphiques data.push(Math.round((Math.random() - 0.5) * 20 + data[i - 1])); } option = { canvas:{ id: 'canvas' }, series: { name: 'Données simulées', itemStyle: { color: 'rgb(255, 70, 131)' }, zoneStyle : { couleur : 'rgb(255, 158, 68)' }, data : data } } ;Dessiner un graphique linéaire
Initialisez d’abord un constructeur pour placer les données dont vous avez besoin :
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 //Données de simulation de stockage}Dessinez un graphique linéaire :
LinearGradient.prototype.draw1 = function() { //Ligne de référence polyligne... //Il faut considérer que l'origine du canevas est le coin supérieur gauche, //Certaines conversions doivent donc être effectuées en dessous, //diff est x, l'axe y correspond aux données Les parties égales de la plage des valeurs maximales et minimales. this.series.data.forEach(function(item, index) { var x = diffX * index, y = Math.floor(self.height - diffY * (item - dataMin)) self.ctx.lineTo(x, y) // Tracer des points de données individuels}) ...} Raccord lisse courbe de BézierLe point clé de la courbe de Bézier est la sélection des points de contrôle. Ce site permet d'afficher dynamiquement différentes courbes dessinées avec différents points de contrôle. Et pour le calcul des points de contrôle. . L'auteur a quand même choisi Baidu, après tout, il n'est pas bon en mathématiques :). Les étudiants intéressés par l’algorithme spécifique peuvent en apprendre davantage. Parlons maintenant de la conclusion du calcul des points de contrôle.
La formule ci-dessus implique quatre points de coordonnées, le point actuel, le point précédent et les deux points suivants. Lorsque les valeurs des coordonnées sont telles qu'indiquées dans la figure ci-dessous, la courbe tracée 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 une méthode de traitement des valeurs limites :
Ainsi, lorsque vous remplacez la polyligne par une courbe lisse, calculez les valeurs limites et autres points de contrôle et remplacez-les dans la fonction Bessel :
//Implémentation principale this.series.data.forEach(function(item, index) { //Trouver le point de contrôle entre le point précédent et le point suivant var scale = 0.1 //Pour un nombre positif de point de contrôle ab, vous pouvez Ajuster var last1X = diffX * (index - 1), last1Y = Math.floor(self.height - diffY * (self.series.data[index - 1] - dataMin)), //Les coordonnées du point précédent last2X = diffX * (index - 2), last2Y = Math.floor(self.height - diffY * (self.series.data[index - 2] - dataMin)), //Les deux premières coordonnées de points nowX = diffX * (index) , nowY = Math.floor(self.height - diffY * (self.series.data[index] - dataMin)), //Coordonnées du point actuel nextX = diffX * (index + 1), nextY = Math.floor(self.height - diffY * (self.series.data[index + 1] - dataMin)), //Coordonnée du point suivant cAx = last1X + (nowX - last2X) * échelle, cAy = last1Y + (nowY - last2Y) * échelle, cBx = nowX - (nextX - last1X) * échelle, cBy = nowY - (nextY - last1Y) * échelle 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) * échelle cBy = nowY - (nowY - last1Y) * échelle } self.ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowYY) //Dessine la courbe de Bézier du point précédent au point actuel})Étant donné que le point que je traverse à chaque fois est le point actuel, mais que la formule donnée dans l'article est un algorithme de point de contrôle qui calcule le point suivant, donc dans l'implémentation du code, j'ai avancé le calcul de tous les points d'une place. 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. A partir d'index = 1, on peut commencer à dessiner normalement la courbe de 0 à 1, car il n'y a pas de deuxième point devant quand index = 1, c'est un point valeur limite, qui nécessite un calcul particulier, 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.
enfinVoir le code source ici
Ce qui précède représente l’intégralité du contenu de cet article. J’espère qu’il sera utile à l’étude de chacun. J’espère également que tout le monde soutiendra le réseau VeVb Wulin.