이번에는 캔버스에 그려진 폴리라인 선분의 가장자리와 모서리를 부드럽게 하는 방법, 즉 베지어 곡선을 각 드로잉 포인트에 통과시켜 원본 폴리라인 그래프를 대체하는 방법을 공유하겠습니다.
폴리선 세그먼트를 부드럽게 맞추는 이유먼저 Echarts 아래 꺾은선형 차트의 렌더링 효과를 살펴보겠습니다.
처음에는 이 폴리라인 세그먼트가 실제로 이를 통과하는 곡선이라는 사실을 눈치채지 못했습니다. 단순한 점 그리기인 줄 알았기 때문에 처음에 구현한 단순(추악)하고 쉬운(추악) 버전은 다음과 같았습니다.
스타일에 신경 쓰지 마세요. 핵심은 구현 후 Echarts 구현이 매우 원활해 보인다는 점을 발견했으며 이로 인해 후속 논의도 촉발되었습니다. 부드러운 곡선을 정기적으로 그리는 방법은 무엇입니까?
렌더링
먼저 최종 모방의 구현을 살펴보겠습니다.
Echarts가 내부적으로 어떻게 구현되는지 모르기 때문에 (Escape
그것은 이미 우리의 원래 비전에 매우 가깝고 매우 둥글게 보입니다. 곡선이 그리기 점을 통과하는지 살펴보겠습니다.
좋아요! 결과는 분명합니다. 이제 구현을 살펴보겠습니다.
구현 프로세스
시뮬레이션된 데이터
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: { 색상: 'rgb(255, 158, 68)' }, 데이터: 데이터 } };꺾은선형 차트 그리기
먼저 생성자를 초기화하여 필요한 데이터를 배치합니다.
function LinearGradient(옵션) { 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를 선택했지만 결국 그는 수학을 잘하지 못합니다. :). 특정 알고리즘에 관심이 있는 학생들은 이에 대해 자세히 알아볼 수 있습니다. 이제 제어점 계산의 결론에 대해 이야기하겠습니다.
위 수식은 현재점, 이전점, 다음 2점의 4개의 좌표점을 포함하며, 좌표값이 아래 그림과 같을 때 그려지는 곡선은 다음과 같습니다.
그런데 이 공식을 시작점과 끝점으로 사용할 수 없다는 문제가 있는데, 해당 글에서는 경계값을 처리하는 방법도 제시하고 있습니다.
따라서 폴리라인을 부드러운 곡선으로 변경할 때 경계값과 기타 제어점을 계산하고 이를 베셀 함수에 대입합니다.
//핵심 구현 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) * 스케일, 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) * 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까지는 그려야 할 곡선이 없기 때문입니다. 인덱스 = 1부터 시작하여 0부터 1까지 곡선을 그리기 시작할 수 있습니다. 인덱스 = 1일 때 앞에 두 번째 점이 없기 때문에 특별한 계산이 필요한 경계 값 지점이고 마지막으로 A 지점입니다. . 나머지는 일반 공식에 따라 AB의 xy 좌표를 계산하고 이를 Bessel 함수에 대입하면 됩니다.
마침내여기에서 소스코드를 확인하세요
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.