На этот раз я расскажу, как сгладить края и углы нарисованных сегментов полилинии на холсте, то есть заменить исходный график полилинии, проведя кривую Безье через каждую точку рисования.
Зачем сглаживать подходящие сегменты полилинийДавайте сначала посмотрим на эффект рендеринга линейного графика в Echarts:
Сначала я не заметил, что этот сегмент полилинии на самом деле был проходящей через него кривой, я просто подумал, что это простой точечный рисунок, поэтому простая (уродливая) и легкая (уродливая) версия, которую я реализовал сначала, была такой:
Не обращайте внимания на стиль. Ключевым моментом является то, что после реализации я обнаружил, что реализация Echarts кажется очень гладкой, что также вызвало последующие обсуждения. Как регулярно рисовать плавные кривые?
визуализации
Давайте сначала посмотрим на реализацию финальной имитации:
Потому что я не знаю, как Echarts реализован внутри (побег
Это уже выглядит очень округленно, очень близко к нашему первоначальному видению. Посмотрим, проходит ли кривая через точку рисования:
ХОРОШО! Результат очевиден. Теперь давайте посмотрим на нашу реализацию.
Процесс реализации
смоделированные данные
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 = { холст:{ 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() { //Опорная линия ломаной линии... //Следует учитывать, что началом координат является верхний левый угол, //Поэтому необходимо выполнить некоторые преобразования ниже, //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) //Построение отдельных точек данных}) ...} Плавная установка кривой БезьеКлючевым моментом кривой Безье является выбор контрольных точек. Этот веб-сайт может динамически отображать различные кривые, построенные с разными контрольными точками. И для расчёта контрольных точек. . Автор все-таки выбрал Baidu, все-таки с математикой он не силен :). Студенты, интересующиеся конкретным алгоритмом, могут узнать о нем больше. Теперь поговорим о выводе расчета контрольных точек.
Приведенная выше формула включает четыре точки координат: текущую точку, предыдущую точку и следующие две точки. Когда значения координат такие, как показано на рисунке ниже, нарисованная кривая выглядит следующим образом:
Однако есть проблема: эту формулу нельзя использовать для начальной и последней точки, но в этой статье также дан метод обработки граничных значений:
Поэтому при изменении полилинии на плавную кривую рассчитайте граничные значения и другие контрольные точки и подставьте их в функцию Бесселя:
//Основная реализация this.series.data.forEach(function(item, index) { //Находим контрольную точку между предыдущей точкой и следующей точкой var Scale = 0.1 //Для положительного числа контрольных точек ab вы можете Корректировка var Last1X = diffX * (индекс - 1), Last1Y = Math.floor(self.height - diffY * (self.series.data[index - 1] - dataMin)), //Координаты предыдущей точки Last2X = diffX * (индекс - 2), last2Y = Math.floor(self.height - diffY * (self.series.data[index - 2] - dataMin)), //Координаты первых двух точек nowX = diffX * (индекс) , 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) * масштаб, cAy = Last1Y + (nowY - Last2Y) * масштаб, cBx = nowX - (nextX - Last1X) * масштаб, cBy = nowY - (nextY - Last1Y) * масштаб if(index === 0) { self.ctx.lineTo(nowX, nowY) return } else if(index ===1) { cAx = Last1X + (nowX - 0) * масштаб cAy = Last1Y + (nowY - self.height) * масштаб } else if (index === self.series.data.length - 1) { cBx = nowX - (nowX - Last1X) * масштаб cBy = nowY - (nowY - Last1Y) * масштаб } self.ctx.bezierCurveTo(cAx, cAy, cBx, cBy, nowX, nowY //Рисуем кривую Безье от предыдущей точки до текущей точки})Поскольку точка, которую я прохожу каждый раз, является текущей точкой, а формула, приведенная в статье, представляет собой алгоритм контрольной точки, вычисляющий следующую точку, поэтому в реализации кода я перенес расчет всех точек на одну позицию вперед. Когда индекс = 0, который является начальной точкой, рисовать кривую не требуется, поскольку мы рисуем кривую от предыдущей точки до текущей точки, и нет никакой кривой до 0, которую нужно было бы рисовать. Начиная с индекса = 1, мы можем начать нормально рисовать кривую от 0 до 1, поскольку при индексе = 1 перед ней нет второй точки, это точка граничного значения, которая требует специального расчета, и, наконец, точка А. . В остальном просто вычислите координаты xy AB по обычной формуле и подставьте их в функцию Бесселя.
наконецСмотрите исходный код здесь
Выше приведено все содержание этой статьи. Я надеюсь, что она будет полезна для изучения всеми. Я также надеюсь, что все поддержат сеть VeVb Wulin.