제가 최근에 구현한 아래 사진의 효과를 여러분과 공유하고 싶습니다.
아래 곡선의 애니메이션을 그리고 싶다면
매번 짧은 선을 그려서 연결하면 아래 그림은 5개 부분으로 나누어져 있습니다.
10문단 더 읽어보세요
분할된 세그먼트 수가 충분할 경우 한 번에 한 세그먼트씩 그리는 것은 곡선 궤적처럼 보입니다.
2차 베지어 곡선/** * 2차 베지어 곡선 애니메이션* @param {Array<number>} 시작 시작점 좌표* @param {Array<number>} 곡률점 좌표(즉, 전환점, 정확한 좌표가 아닌 대략적인 방향) * @param {Array<number>} 끝 끝점 좌표 * @param {number} 퍼센트 그리기 백분율(0-100) */ function drawCurvePath(start, point, end,퍼센트){ ctx.beginPath(); //선 그리기 시작 ctx.moveTo(start[0], start[1]); //펜을 시작점으로 이동합니다. for (var t = 0; t <= 퍼센트 / 100; t += 0.005 ) { //각 시점의 좌표를 구합니다. var x =quadraticBezier(start[0], point[0], end[0], t); quadraticBezier(start[1], point[1], end[1], t); ctx.lineTo(x, y); //이전 시점에서 현재 시점까지 직선을 그립니다.} ctx.strok( ); //Stroke} /** * 2차 베지어 곡선 방정식* @param {Array<number>} 시작 시작점* @param {Array<number>} 곡률점* @param {Array<number>} 끝 끝점 * @param {number} 그리기 진행률(0-1) */ functionquadraticBezier(p0, p1, p2, t) { var k = 1 - t; return k * k * p0 + 2 * (1 - t) * t * p1 + t * t * p2 }
더 자세한 베지어 곡선 내용은 이 블로그를 참고하세요.
완전한 코드로
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width,initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>2차 베지어 곡선 애니메이션</title> <style> body { background: #0f1632 } #canvas { border: 1px solid #ccc; } #img { display: none; <!--img를 직접 숨기면 나중에 직접 인용됩니다--> } </style></head><body> <canvas id=canvas width =1500 높이 =750></canvas> <img id=img src=https://s3.imgsha.com/2019/04/22/light.png> <script> var ctx = document.getElementById('canvas').getContext('2d'); var img = document.getElementById('img'); var rates = 0; var data = { start: [400, 200], point: [ 300, 100], 끝: [100, 400], 부서: '데이터 1', 값: 4321 } 함수 init(){퍼센트 = 0; //매번 프로세스를 재설정합니다. draw(); } function draw(){ ctx.clearRect(0, 0, 1500, 750) //매번 캔버스를 지웁니다. ctx.StrokeStyle = ' # ffffff'; //선 스타일 설정 drawCurvePath(data.start, data.point, data.end,퍼센트); //프로세스가 증가함에 따라 애니메이션 속도를 제어합니다. if (percent <= 100) { //그리기가 완료되지 않은 경우 계속 호출합니다. 그리기가 완료되면 진행 상태가 재설정됩니다. requestAnimationFrame(draw) }else{ init() } } function drawCurvePath(start, point, end, rates) / /... } 함수 이차 베지어( p0, p1, p2, t) { //... } </script></body></html>
애니메이션이 나오네요
앞서 언급했듯이 drawCurvePath(start, point, end, percent)
함수의 point
매개변수는 특정 곡률점이 아니라 일반적인 방향입니다.
point
[200,200]
으로 변경되었을 때의 상황을 살펴보겠습니다.
떨어지는 효과를 얻으려면 높은 곳에서 낮은 곳으로, 먼 곳에서 가까운 곳으로 선에 그라데이션 효과를 추가해야 합니다.
/** * 선형 그래디언트 생성* @param {Array<number>} 시작 시작점* @param {Array<number>} 곡률점* @param {Array<number>} 끝 끝점* @param {number} 도면 진행률( 0-1) */function createLinearGradient(start,end,startColor,endColor){ var lineGradient = ctx.createLinearGradient(...start, ...end); lineGradient.addColorStop(0, startColor); // lineGradient.addColorStop(0.3, '#fff'); lineGradient.addColorStop(1, endColor); return lineGradient}//그리기 함수에 약간의 조정이 필요함 function draw(){ // ctx.스트로크스타일 = '#ffffff'; ctx.스트로크스타일 = createLinearGradient(data.start, data.end, 'rgba(255,255,255,.2)', '#fff' ) //...}
캔버스 그라데이션에 대한 자세한 내용은 MDN을 참조하세요.
머리 후광 머리 후광을 추가하려면 원을 그리고 방사형 그라데이션을 설정해야 합니다. x, y를 가져오고 원의 위치를 재설정하려면 drawCurvePath
함수를 사용하세요.
function createHeadLight(x,y){ ctx.beginPath(); //방사형 그래디언트 생성 var RadialGradient = ctx.createRadialGradient(x, y, 0, x, y, 20) RadialGradient.addColorStop(0, rgba(255,255,255, 1) ))); RadialGradient.addColorStop(.2, rgba(255,255,255,.8)); RadialGradient.addColorStop(1, transparent); ctx.fillStyle = RadialGradient; //원 그리기 ctx.arc(x, y, 20, 0, 2 * 수학 .PI, 거짓); ctx.fill();}//drawCurvePath 함수에는 약간의 조정이 필요합니다. function drawCurvePath(start, point, end,퍼센트){ //... ctx.Stroke() // 스트로크 createHeadLight(x,y) // 그리기 선 주파수를 그리는 것과 같은 원}
원을 그리는 데 필요한 arc
자세한 내용은 MDN을 참조하세요.
텍스트를 추가하는 것은 머리 후광을 추가하는 것과 매우 유사합니다. 둘 다 drawCurvePath
함수를 사용하여 x, y를 얻고 텍스트 블록의 위치를 재설정합니다.
/** * 텍스트 생성* @param {String} 부서 데이터* @param {Number} 데이터* @param {Number} x축 좌표* @param {Number} y축 좌표*/function drawText(department, value, x, y) { ctx.fillStyle = '#fff' ctx.font = 22px Microsoft Yahei(부서, x + 30, y + 20); //후광 x의 오른쪽 하단에 텍스트를 만들려면 y축을 일정 거리만큼 오프셋해야 합니다. var width = ctx.measureText(value).width; 텍스트 ctx.fillStyle = createLinearGradient([x + 30, 0], //텍스트 그래디언트 x축의 렌더링 범위는 [x+30,x+30+text width], [x + 30 + width, 0], //여기서는 텍스트 높이를 얻기 위한 API가 없기 때문에 0으로 설정됩니다. 0을 쓰는 것도 허용됩니다. '#fffd00', '#ff6d00' ); 50 ); } //drawCurvePath 함수에는 약간의 조정이 필요합니다. function drawCurvePath(start, point, end, percent, Department, value) { //... createHeadLight(x,y) drawText(부서, 값, x, y) }애니메이션이 완료된 후 끝 위치에 텍스트와 그림을 추가합니다.
애니메이션이 완료된 후 텍스트와 그림을 추가할 때는 곡선 애니메이션이 완료된 후 즉시 캔버스를 정리한 후 텍스트와 그림을 추가해야 한다는 점에 유의하시기 바랍니다.
/** * 그림 생성* @param {Number} x축 좌표* @param {Number} y축 좌표*/function drawImg(x, y) { ctx.drawImage(img, x - img.width / 2, y - img.height); }//그리기 함수에는 약간의 조정이 필요합니다. draw(){ //... if (percent <= 100) { requestAnimationFrame(draw); }else{ ctx.clearRect(0, 0, 1500, 750); //곡선 애니메이션이 완료된 후 즉시 캔버스를 지웁니다. drawText(data.department, //텍스트 렌더링 data.value, data.end[0], data .end[1 ]) drawImg(data.end[0], data.end[1]) //이미지 렌더링 setTimeout(function(){ //2000ms 후 init() 다시 그리기 },2000) } }마치다
이 예제의 전체 코드
기사의 첫 번째 그림에 있는 예제의 전체 코드
참고 기사: 캔버스를 사용하여 곡선 애니메이션 그리기 - 베지어 곡선에 대한 심층적인 이해
위 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.