En esta ocasión compartiré cómo suavizar los bordes y esquinas de los segmentos de polilínea dibujados en el lienzo, es decir, reemplazar el gráfico de polilínea original pasando la curva de Bézier por cada punto del dibujo.
¿Por qué los segmentos de polilínea se ajustan suavemente?Primero veamos el efecto de representación del gráfico de líneas en Echarts:
Al principio, no me di cuenta de que este segmento de polilínea era en realidad una curva que lo atravesaba. Simplemente pensé que era un simple dibujo de puntos, así que la versión simple (fea) y fácil (fea) que implementé al principio fue así:
No prestes atención al estilo. El punto clave es que después de la implementación, descubrí que la implementación de Echarts parece ser muy fluida, lo que también provocó discusiones posteriores. ¿Cómo dibujar curvas suaves con regularidad?
representaciones
Veamos primero la implementación de la imitación final:
Porque no sé cómo se implementa Echarts internamente (escape
Ya parece muy redondeado, muy cercano a nuestra visión original. Veamos si la curva pasa por el punto de dibujo:
¡DE ACUERDO! El resultado es obvio. Ahora echemos un vistazo a nuestra implementación.
Proceso de implementación
datos simulados
var data = [Math.random() * 300]; for (var i = 1; i < 50; i++) { //Siga echarts data.push(Math.round((Math.random() - 0.5) * 20 + datos[i - 1])); } opción = { lienzo:{ id: 'lienzo' }, serie: { nombre: 'Datos simulados', estilo de elemento: { color: 'rgb(255, 70, 131)' }, áreaStyle: { color: 'rgb(255, 158, 68)' }, datos: datos } };Dibujar un gráfico de líneas
Primero inicializa un constructor para colocar los datos que necesitas:
función LinearGradient(opción) { 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 //Almacenamiento de datos de simulación}Dibuja un gráfico de líneas:
LinearGradient.prototype.draw1 = function() { //Línea de referencia de polilínea... //Se debe considerar que el origen del lienzo es la esquina superior izquierda, //Por lo tanto, algunas conversiones deben realizarse a continuación, //diff son los ejes x, y son los datos Las partes iguales del rango de los valores máximo y mínimo. this.series.data.forEach(function(item, index) { var x = diffX * index, y = Math.floor(self.height - diffY * (item - dataMin)) self.ctx.lineTo(x, y) //Trazar puntos de datos individuales}) ...} Ajuste suave de la curva de BézierEl punto clave de la curva de Bézier es la selección de puntos de control. Este sitio web puede mostrar dinámicamente diferentes curvas dibujadas con diferentes puntos de control. Y para el cálculo de puntos de control. . El autor todavía eligió Baidu, después de todo, no es bueno en matemáticas :). Los estudiantes que estén interesados en el algoritmo específico pueden aprender más sobre él. Ahora hablemos de la conclusión del cálculo de los puntos de control.
La fórmula anterior involucra cuatro puntos de coordenadas, el punto actual, el punto anterior y los dos puntos siguientes. Cuando los valores de las coordenadas se muestran en la figura siguiente, la curva dibujada es la siguiente.
Sin embargo, existe el problema de que esta fórmula no se puede utilizar para el punto inicial y el último punto, pero ese artículo también proporciona un método para procesar valores límite:
Entonces, al cambiar la polilínea a una curva suave, calcule los valores de límite y otros puntos de control y sustitúyalos en la función de Bessel:
//Implementación principal this.series.data.forEach(function(item, index) { //Encontrar el punto de control entre el punto anterior y el siguiente var scale = 0.1 //Para un número positivo de puntos de control ab, puede Ajustar var last1X = diffX * (index - 1), last1Y = Math.floor(self.height - diffY * (self.series.data[index - 1] - dataMin)), //Las coordenadas del punto anterior last2X = diffX * (índice - 2), last2Y = Math.floor(self.height - diffY * (self.series.data[index - 2] - dataMin)), //Las dos primeras coordenadas de puntos ahoraX = diffX * (índice) , nowY = Math.floor(self.height - diffY * (self.series.data[index] - dataMin)), //Coordenadas del punto actual nextX = diffX * (index + 1), nextY = Math.floor(self.height - diffY * (self.series.data[index + 1] - dataMin)), //Coordenada del siguiente punto cAx = last1X + (nowX - last2X) * escala, cAy = last1Y + (nowY - último2Y) * escala, cBx = ahoraX - (siguienteX - último1X) * escala, cBy = ahoraY - (siguienteY - último1Y) * escala si(índice === 0) { self.ctx.lineTo(nowX, nowY) return } else if(index ===1) { cAx = last1X + (nowX - 0) * escala cAy = last1Y + (nowY - self.height) * escala } else if (índice === self.series.data.length - 1) { cBx = ahoraX - (ahoraX - último1X) * escala cBy = ahoraY - (ahoraY - último1Y) * escala } self.ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowY); //Dibuja la curva de Bézier desde el punto anterior hasta el punto actual})Dado que el punto que atravieso cada vez es el punto actual, pero la fórmula dada en el artículo es un algoritmo de punto de control que calcula el siguiente punto, en la implementación del código, moví el cálculo de todos los puntos un lugar hacia adelante. Cuando el índice = 0, que es el punto inicial, no es necesario dibujar ninguna curva, porque estamos dibujando una curva desde el punto anterior hasta el punto actual, y no hay ninguna curva hasta 0 que deba dibujarse. A partir del índice = 1, podemos comenzar a dibujar la curva normalmente de 0 a 1, porque no hay un segundo punto delante cuando el índice = 1, es un punto de valor límite, que requiere un cálculo especial, y finalmente un punto. . Por lo demás, simplemente calcula las coordenadas xy de AB según la fórmula normal y sustitúyelas en la función de Bessel.
por finVer código fuente aquí
Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.