최근 프로젝트에서 UI가 물결 효과를 적용한 배경 애니메이션을 디자인했는데 gif나 svg 애니메이션이 없어서 CSS를 이용해 구현해 보았으나 기본적으로 애니메이션 효과가 별로 좋지 않았습니다. 이를 구현하기 위해 베지어 곡선을 사용했는데, 예전에 봤던 다양한 파형도가 생각나서 삼각함수 이미지를 이용해서 간략하게 시뮬레이션을 해볼까 하는 생각이 들었습니다.
1. sin 함수 이미지를 그립니다.sin 함수의 표현은 다음과 같다.
y=Asin(wx+φ)+h
그 중 A는 진폭을 나타내고, Ω는 각주파수(Ω=2π/T, T는 함수의 주기)를 나타내고, ψ는 초기 위상을 나타내고, h는 영상이 양의 방향으로 이동하는 길이를 나타냅니다. y축(여기서 주목해야 할 점: 수학에서 h는 원래 상향 변환을 의미하지만 화면 좌표계는 캔버스에서 사용됩니다. 즉, 왼쪽 위 모서리가 원점이고 h는 하향 변환을 의미합니다.)
그리기 코드는 다음과 같습니다.
(1) 캔버스 태그 추가
<캔버스 id=캔버스></canvas>
(2) CSS 스타일을 추가하고 캔버스 너비와 높이를 설정합니다.
html,body { 패딩: 0; 여백: 0; 높이: 100%;} 캔버스 { 너비: 100%;
(3) 그리기 기능 이미지
var canvas = document.getElementById(canvas), ctx = canvas.getContext('2d'), width = canvas.width = canvas.offsetWidth, height = canvas.height = canvas.offsetHeight;//매개변수 선언 var A=50, W=1 / 50, Q=0, H= 높이 / 2;//그리기 방법 (function draw(){ ctx.clearRect(0, 0, width, height);//캔버스 지우기 ctx.beginPath(); //시작 경로 ctx.StrokeStyle=#000; //선 색상 설정 ctx.lineWidth = 1 //선 너비 설정 ctx.moveTo(0, height) /2) ; //(let x = 0; x <= width; x++)에 대한 시작점 위치 {// y = A*Math.sin(W*x+Q) +H에 해당하는 x의 var를 그립니다. ctx.lineTo(x, y) } ctx.Stroke(); //경로를 그립니다. ctx.closePath() //경로를 닫습니다.
이 방법으로 우리는 다음 이미지를 얻습니다.
2. 함수 이미지에 애니메이션 추가위에서 얻은 것은 정적 함수 이미지이며, 우리가 일반적으로 보는 파형 또는 물결은 시간에 따라 지속적으로 변경됩니다. 여기서는 이전 단계의 매개변수 위상 를 사용해야 합니다(코드에서 js는 Q임). 서로 다른 시간에 서로 다른 이미지를 얻으려면 시간에 따라 Φ를 늘리거나 줄입니다. window.requestAnimationFrame을 사용하여 프레임 애니메이션을 구현합니다.
위의 코드를 다음과 같이 수정하세요.
var canvas = document.getElementById(canvas), ctx = canvas.getContext('2d'), width = canvas.width = canvas.offsetWidth, height = canvas.height = canvas.offsetHeight;//매개변수 선언 var A=50, W=1 / 50, Q=0, H= 높이 / 2;//그리기 방법 (function draw(){ ctx.clearRect(0, 0, width, height);//캔버스 지우기 ctx.beginPath(); //시작 경로 ctx.StrokeStyle=#000; //선 색상 설정 ctx.lineWidth = 1 //선 너비 설정 ctx.moveTo(0, height) /2) ; //(let x = 0; x <= width; x++)에 대한 시작점 위치 {// y = A*Math.sin(W*x+Q) +H에 해당하는 x의 var를 그립니다. ctx.lineTo(x, y) } ctx.Stroke(); //경로를 그립니다. ctx.closePath() //경로를 닫습니다.
효과는 다음과 같습니다(Zhazha 스크린샷 소프트웨어):
3. 완전한 채워진 경로 그리기위의 경로는 닫혀 있지만 채워야 할 부분을 충족하지 못합니다. 직접 채우기의 효과는 다음과 같습니다.
전체 채워진 경로는 다음과 같아야 합니다.
패스를 닫은 후 채우기 색상으로 그라데이션 색상을 만듭니다.
var lingrad = ctx.createLinearGradient(0,0,width,0); lingrad.addColorStop(0, 'rgba(0,186,128,0.8)') lingrad.addColorStop(1, 'rgba(111,224,195,1)'); draw(){ window.requestAnimationFrame(draw); ctx.clearRect(0, 0, 너비, 높이); ctx.StrokeStyle=#000; ctx.lineWidth = 1; =속도; for (x = 0; x <= 너비; x++) { var y = A*Math.sin(W*x+Q) +H; ctx.lineTo(x, y) } ctx.lineTo(width, height)(0, height); .closePath();})()
효과는 다음과 같습니다.
4. 물결 애니메이션 개선1. 먼저 위의 파형에 더 높은 주파수의 파형을 겹쳐서 파형을 불규칙하게 만들 수 있습니다.
var s = 0.1*Math.sin(x/150)+1;var y = A*Math.sin(W*x+Q) +H;y=y*s;
2. 위상 변화가 다른 또 다른 파형을 추가하고 그라데이션 채우기가 이전 그라데이션 방향과 반대되어 겹치는 그림자 효과를 형성하고 경로 겹치기 효과 globalCompositeOperation을 설정합니다.
var canvas = document.getElementById(canvas), ctx = canvas.getContext('2d'), width = canvas.width = canvas.offsetWidth, height = canvas.height = canvas.offsetHeight;var A=30, W=1 / 200, Q=0, H= 높이 / 2;var A2=30, W2=1/300, Q2=0, H2= 높이 / 2;var 속도=-0.01;var 속도2=-0.02;var lingrad = ctx.createLinearGradient(0,0,width,0);lingrad.addColorStop(0, 'rgba(0,186,128,0.8)');lingrad.addColorStop( 1, 'rgba(111,224,195,1)'); var lingrad2 = ctx.createLinearGradient(0,0,width,0);lingrad2.addColorStop(0,'rgba(111,224,195,1)');lingrad2.addColorStop(1, 'rgba(0,186,128,0.8)')(함수 draw(){ window.requestAnimationFrame(draw); ctx.clearRect(0, 0, width, height); ctx.fillStyle = ctx.moveTo(0, height /2); //첫 번째 파형 그리기 for (let x = 0; x <= 너비; x++) { var s = 0.1*Math.sin(x/150)+1; A*Math.sin(W*x+Q) +H; ctx.lineTo(x, y) } ctx.lineTo(0, 높이); .fill(); ctx.closePath() //오버랩 효과 설정 ctx.globalCompositeOperation = Destination-over //두 번째 파형 그리기 ctx.beginPath(); ctx.fillStyle = lingrad2; Q2+=speed2; for (let x = 0; x < width; x++) { var y = A2*Math.sin(x*W2+Q2) +H2; ; } ctx.lineTo(너비, 높이); ctx.lineTo(0,height); ctx.closePath();})()
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.