이번 글에서는 캔버스를 사용하여 아름다운 비 효과를 그리는 방법에 대해 설명합니다. 최종 효과를 살펴보겠습니다.
렌더링
설명하다우리가 달성해야 할 효과를 분석하려면 그림을보십시오.
1. 빗방울 떨어지는 효과, 마우스를 움직여 떨어지는 방향을 제어하세요.
2. 빗방울이 떨어져서 작은 물방울로 흩어집니다. 작은 물방울의 이동 방향은 마우스의 이동 방향과 같습니다.
3. 빗방울은 마우스 좌표의 특정 범위 내에 떨어지며 작은 물방울로 흩어집니다. 마찬가지로 작은 물방울의 이동 방향은 마우스의 이동 방향과 동일합니다.
좋습니다. 전체 효과를 대략적으로 세 가지 효과로 나누고 이 세 가지 효과를 달성하면 완료됩니다.
단계별로 해봅시다.
1. 빗방울 떨어지는 효과, 마우스를 움직여 떨어지는 방향을 제어하세요.전체 효과를 달성하려는 아이디어는,
초기 시간빗방울 객체를 저장하려면 배열을 사용하세요.
빗방울 객체에는 빗방울의 x 좌표, y 좌표, 길이, 낙하 속도, 색상, 삭제 여부를 결정하는 플래그를 나타내는 데 사용되는 다양한 속성이 있습니다.
애니메이션을 업데이트할 때배열에 일정한 수의 빗방울 개체를 추가한 다음 배열을 순회하고 각 빗방울 개체의 x좌표와 y좌표를 수정한 다음 캔버스를 사용하여 빗방울 개체의 좌표를 기준으로 두 점을 그리면 연결됩니다. 빗방울이 형성됩니다.
따라서 효과 달성의 초점은 좌표에 있습니다.
빗방울을 초기화할 때빗방울 x좌표: 임의의 숫자
빗방울 y 좌표: -100, 가시 영역 외부에서 빗방울이 들어올 수 있도록 합니다.
애니메이션을 업데이트할 때 빗방울 x 좌표:原x坐标的值+ speed * speedx
속도는 빗방울이 떨어지는 속도를 나타내는 고정된 값입니다.
speedx는 마우스 이동 방향과 관련된 변수로, speedx = speedx + (maxspeedx - speedx) / 50
그리고 maxspeedx는 마우스 이동 방향에 따라 구해지는 값이다.
maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2)
,
e.clientX: 가시 영역 왼쪽까지의 마우스 거리 값
canvasEl.clientWidth: 전체 시각적 영역의 너비
즉, speedx는 점점 maxspeedx에 가까워지는 값이다.
maxspeedx의 값 범위는 -1부터 1까지이다. 값이 -1에 가까울수록 방향은 더 왼쪽으로, 값이 1에 가까울수록 방향은 더 오른쪽으로 향한다.
왜 maxspeedx를 사용하지 않습니까?
이는 빗방울의 방향이 너무 빨리 바뀌는 것을 방지하기 위한 것입니다. 마우스를 변경한 직후에 방향을 바꾸는 대신 약간의 지연을 두어 좀 더 보기 좋게 만들어야 합니다.
maxspeedx를 사용하면 효과는 이렇습니다
speedx를 사용하면 효과는 이렇습니다
빗방울 y 좌표:原y坐标的值+ speed
속도는 위의 x 좌표에서 언급한 것과 동일하며, 빗방울이 떨어지는 속도를 나타내는 고정된 값입니다.
자, 마지막으로 캔버스를 사용하여 빗방울 개체의 좌표에 따라 두 점을 그린 다음 이를 연결하면 빗방울이 그려집니다.
첫 번째 점 좌표는 상대적으로 간단하며, 이 점의 좌표인 빗방울 객체의 x 좌표와 y 좌표를 직접 구합니다.
두 번째 점의 좌표:
x坐标= 雨滴x坐标的值+ 雨滴长度* speedx
y坐标= 雨滴y坐标的值+ 雨滴长度
마지막으로 이 두 점을 연결하면 빗방울인 선이 생깁니다.
x 좌표를 설정할 때, 빗방울 방향과 빗방울이 떨어지는 방향을 동일하게 만들기 위해 가변 속도x를 다시 사용합니다.
speedx를 사용하지 않을 때는 이렇습니다.
speedx를 사용하면 이런 경우가 발생합니다.
2. 빗방울이 떨어져서 작은 물방울로 흩어집니다. 작은 물방울의 이동 방향은 마우스의 이동 방향과 같습니다.여기의 아이디어는 실제로 위의 효과와 다소 유사합니다.
초기 시간작은 물방울 개체를 저장하려면 배열을 사용하세요.
작은 물방울은 실제로 원호입니다.
작은 물방울 객체는 작은 물방울의 좌표, x축 이동 속도, y축 이동 속도, 원의 반지름, 삭제 여부를 결정하는 플래그를 나타내는 데 사용되는 다양한 속성을 가지고 있습니다.
애니메이션을 업데이트할 때특정 수의 작은 물방울 개체를 배열에 추가한 다음 배열을 탐색하고 각 작은 물방울 개체의 x 좌표와 y 좌표를 수정하고 캔버스를 사용하여 작은 물방울 개체의 좌표 속성과 반경 속성을 기반으로 호를 그립니다. 물방울 개체.
따라서 효과 달성의 초점은 여전히 좌표에 있습니다.
작은 물방울을 초기화할 때빗방울이 사라지면 작은 물방울이 나타나기 때문에 작은 물방울의 좌표도 빗방울의 좌표를 기준으로 하게 됩니다. 빗방울을 삭제하면 작은 물방울이 몇 개 나타나며 작은 물방울의 이동 방향은 다음과 같습니다. 빗방울이 떨어지는 방향도 마찬가지입니다. 마우스 이동 방향은 동일하므로 위에서 언급한 가변 속도x가 여전히 필요합니다.
小水珠x坐标: 删除的雨滴x坐标+ 删除的雨滴长度* speedx
小水珠y坐标:删除的雨滴y坐标+ 删除的雨滴长度
여기서는 작은 물방울 객체 vx(x축 값의 변화 속도)와 vy(y축 값의 변화 속도)의 두 가지 속성을 사용해야 합니다.
작은 물방울의 x좌표
vx = vx + speedx / 2
小水珠的x坐标=原x坐标+ vx
,
speedx: 위에서 언급한 마우스 이동 방향과 관련된 변수 여기서의 기능은 다른 방향과 동일한 방향으로 작은 물방울의 이동 방향을 제어하는 것입니다.
speedx / 2
2로 나누는 목적은 x축에 있는 작은 물방울의 이동 거리를 더 짧게 만들어 좀 더 사실적으로 보이도록 하기 위한 것입니다.
작은 물방울의 y 좌표
vy = vy + gravity
小水珠的y坐标= 原y坐标+ vy;
vy: 음수
중력(Gravity): 중력(양수)은 전체 코드에서 0.5로 설정됩니다.
원래 y 좌표는 양수이므로 작은 물방울의 y 좌표 값이 먼저 감소한 다음 증가합니다. 이는 작은 물방울이 먼저 상승한 다음 떨어지는 효과를 얻기 위한 것입니다.
마지막으로 캔버스를 사용하여 작은 물방울의 좌표 속성과 반경 속성을 기반으로 호를 그립니다. 호는 무작위입니다.
3. 빗방울은 마우스 좌표의 특정 범위 내에 떨어지며 작은 물방울로 흩어집니다. 마찬가지로 작은 물방울의 이동 방향은 마우스의 이동 방향과 동일합니다.
그림에서 원의 크기를 결정하는 것은 쉽습니다. 원의 반지름이 35라고 가정합니다. 마우스의 좌표를 원의 중심으로 하고 35를 반지름으로 하면 됩니다. , 우리는 원의 크기를 결정할 수 있습니다.
핵심은 빗방울이 이 범위에 들어왔는지 판단하는 방법입니다. 이를 위해서는 피타고라스 정리를 사용해야 합니다.
빗방울은 두 점을 연결한 선이므로 빗방울이 이 범위에 들어왔는지 확인하려면 빗방울 아래 점의 좌표를 살펴봐야 합니다. 사진 속 AB.
피타고라스 정리: 직각삼각형의 직각 두 변의 제곱의 합은 빗변의 제곱과 같습니다.
AB = Math.sqrt(BC BC + AC AC)
BC = 빗방울 x좌표 - 마우스 x좌표
AC = 빗방울 y 좌표 - 마우스 y 좌표
Math.sqrt() 메소드는 숫자의 제곱근을 계산하는 데 사용됩니다.
빗방울에서 마우스까지의 직선 거리를 알고 나면 이를 원의 반지름과 비교하여 반지름보다 크면 범위 내에 있지 않은 것이고 그렇지 않으면 범위 안에 있습니다.
범위 내에 있으면 빗방울을 삭제하고 작은 물방울을 그립니다.
요약
이 효과를 얻으려면 방향, 빗방울의 방향, 빗방울의 방향, 작은 물방울의 이동 방향이 모두 마우스 이동 방향과 관련이 있습니다. 캔버스를 사용하여 거리에 따라 선을 계속 그립니다.
완전한 코드
<!doctype html><html lang=en><head> <meta charset=UTF-8> <style> * { 여백: 0 패딩: 0 } </style></head><body> <캔버스 ID; =canvas style=position: 절대; 높이: 100%; 너비:100%;></canvas> <script> window.onload = main() { // 캔버스 요소 가져오기 var canvasEl = document.getElementById('canvas'); var ctx = canvasEl.getContext('2d'); // 캔버스 캔버스의 배경색 var backgroundColor = '#000'; // 캔버스 캔버스의 너비는 시각적 영역의 너비 canvasEl.width = canvasEl.clientWidth; // 캔버스의 높이는 보이는 영역의 높이와 같습니다. canvasEl.height = canvasEl.clientHeight // 작은 물방울을 저장하는 배열 // 빗방울은 떨어진 후 작은 물방울로 흩어집니다. var dropList = []; // 중력 // 빗방울이 떨어진 후 작은 물방울이 먼저 솟아오릅니다. 그런 다음 주로 중력 때문에 떨어집니다. var 중력 = 0.5; // 빗방울 배열을 저장합니다. // 각 빗방울은 선으로 그려집니다. var linelist = [] // 마우스 좌표를 저장합니다. ] x축 값을 나타내고, mousePos[1]은 y축 값을 나타냅니다. var mousePos = [0, 0] // 마우스를 따라가면 mouseDis 크기 영역의 빗방울이 사라져 산란 효과가 나타납니다. // mousePos를 원의 중심으로 하고 mouseDis는 Radius이며 이 범위 내의 빗방울은 퍼져서 많은 작은 물방울을 형성합니다. var mouseDis = 35; // 애니메이션을 한 번 업데이트하고 lineNum 빗방울을 그립니다. , 비의 밀도가 높아질 것입니다. lineNum = 3; // 마우스 방향을 따라 비 방향의 속도를 변경합니다. // 마우스가 이동한 후 비의 방향은 주로 변수 speedx에 따라 천천히 변경됩니다. var speedx = 0 // maxspeedx; speedx가 취할 수 있는 최대값입니다. // speedx = maxspeedx일 때 마우스 이동 방향에 따라 비의 방향이 즉시 변경됩니다. var maxspeedx = 0; // 페이지 크기가 변경되면 캔버스 크기를 재설정합니다. window.onresize = function () { canvasEl.width = canvasEl.clientWidth; canvasEl.height = canvasEl.clientHeight; } //이벤트를 트리거하기 위해 마우스를 움직입니다. window.onmousemove = function (e) { //mousePos를 마우스 좌표와 동일하게 설정합니다. // e.clientX는 브라우저 창의 가시 영역 왼쪽 거리 // e.clientY는 브라우저 창의 가시 영역 상단으로부터의 거리입니다. mousePos[0] = e.clientX[1] = e.clientY; // 마우스 위치를 통해 maxspeedx 값을 설정합니다. 값 범위는 -1~1입니다. // maxspeedx 값은 // 1. 빗방울의 방향에 관련됩니다. // 2. 빗방울의 방향 빗방울 // 3. 마우스 이동 방향에 따라 빗방울 떨어지는 방향이 바뀌는 속도 // 4. 작은 물방울의 이동 방향 // 값이 1에 가까울수록 방향은 더 오른쪽으로 갑니다 / / 값이 -1에 가까울수록 왼쪽으로 향하는 방향이 커짐 maxspeedx = (e.clientX - canvasEl.clientWidth / 2) / (canvasEl.clientWidth / 2) } // 매개변수에 따라 빗방울의 색상을 설정하는 데 사용되는 rgb 색상을 반환합니다. function getRgb(r, g, b) { return rgb( + r + , + g + , + b + ) } // 빗방울(선) 그리기 function createLine(e) { // 빗방울의 길이를 무작위로 생성 var temp = 0.25 * (50 + Math.random() * 100); // 빗방울을 나타내는 선 객체 var line = { // 빗방울 낙하 속도 속도: 5.5 * (Math.random() * 6 + 3), / / 삭제 여부를 결정하고, 값이 true이면 삭제 die: false, // Raindrop x 좌표 posx: e, // Raindrop y 좌표 posy: -50, // Raindrop 길이 h: temp, // 빗방울 색상 color: getRgb(Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75), Math.floor(temp * 255 / 75)) } // 굿 생성 line(raindrop) 객체, 빗방울이 담긴 배열에 추가됨 linelist.push(line) } // 작은 물방울 그리기(빗방울이 흩어진 후의 작은 물방울은 호) function createDrop(x, y) { // 호를 나타내는 드롭 객체 var drop = { // 삭제 여부 결정, value true인 경우 삭제 die: false, // 원호 중심의 x 좌표 posx: x, // 원호 중심의 y 좌표 posy: y, // vx는 x축 값이 변경되는 속도를 나타냅니다. vx: (Math.random ( ) - 0.5) * 8, // vy는 y축 값의 변화 속도 범위를 나타냅니다: -3 ~ -9 vy: Math.random() * (-6) - 3, // 호 반경의 반경 : Math.random() * 1.5 + 1 }; return drop; } // 일정한 수의 작은 물방울을 그립니다. function madedrops(x, y) { // 무작위로 숫자 생성 maxi // maxi 그려질 작은 물방울의 수를 나타냅니다. var maxi = Math.floor(Math.random() * 5 + 5) for (var i = 0; i < maxi; i++) { dropList.push(createDrop(x, y) ); } } // 애니메이션 업데이트를 위해 업데이트 함수 호출 시작 window.requestAnimationFrame(update); // 애니메이션 업데이트 업데이트() { // 작은 물방울을 담고 있는 배열에 콘텐츠가 있는 경우 (dropList.length > 0) { // 작은 물방울이 담긴 배열을 탐색합니다. dropList.forEach(function (e) { //e.vx를 설정하고, vx는 x 좌표 변화의 속도를 나타냅니다. // (speedx)/2는 for, x축의 작은 물방울의 이동 거리를 짧게 만들어 좀 더 사실적으로 보이도록 // 또한 작은 물방울의 이동 방향을 빗방울의 방향, 빗방울이 떨어지는 방향과 동일하게 만들고, 마우스의 이동 방향 e.vx = e.vx + (speedx / 2) e.posx = e.posx + e.vx; //e.vy를 설정하고, vy는 y 좌표의 변화 속도를 나타냅니다. // e.vy의 범위는 -3 ~ -9이며, 이때 e.posy(y 좌표)는 양수 값이어야 하므로 e.posy 값은 먼저 감소한 다음 증가합니다. // 즉, 빗방울은 작은 물방울로 분산되고 작은 물방울은 먼저 상승한 다음 증가합니다. 추락. e.vy = e.vy + e.posy = e.posy + e.vy; // 작은 물방울의 y 좌표가 보이는 영역의 높이보다 크면 die 속성을 true로 설정합니다. // 작은 물방울이 보이는 영역을 벗어나면 삭제합니다. (e. posy > canvasEl.clientHeight) { e .die = true; } }) } // die 속성이 true인 배열 멤버를 삭제합니다. // 가시 영역 외부의 작은 물방울을 삭제합니다. for (var i = dropList.length - 1 ; i >= 0; i- -) { 경우 (dropList[i].die) { dropList.splice(i, 1); } } // 비 방향 변경 속도를 설정합니다. 값 범위: -1 ~ 1 // speedx = maxspeedx일 때 비 방향이 변경됩니다. 마우스 이동 방향 즉시 speedx = speedx + (maxspeedx - speedx) / 50; // lineNum 값에 따라 특정 개수의 빗방울을 그립니다. for (var i = 0; i < lineNum; i++) { // createLine 함수를 호출합니다. 매개변수는 빗방울의 x 좌표입니다. createLine(Math.random() * 2 * canvasEl.width - (0.5 * canvasEl.width)) } // 끝선을 설정합니다. 빗방울이 퍼져서 많은 작은 물방울을 형성합니다. Position var endLine = canvasEl.clientHeight - Math.random() * canvasEl.clientHeight / 5; 빗방울이 담긴 배열을 탐색합니다. linelist.forEach(function (e) { // 피타고라스 정리를 사용하여 빗방울이 퍼져 작은 물방울을 형성하는 범위를 결정합니다. // e.posx + speedx * eh는 x 좌표입니다. raindrop/ / e.posy + eh는 빗방울의 y 좌표입니다. var dis = Math.sqrt(((e.posx + speedx * eh) - mousePos[0]) * ((e.posx + speedx * eh) - mousePos[0]) + (e.posy + eh - mousePos[1]) * (e.posy + eh - mousePos[1])) // mouseDis 영역에 있으면 빗방울을 삭제합니다. 그리고 작은 물방울(호) // 마우스가 빗방울을 건드리면 빗방울이 작은 물방울로 흩어지는 효과를 구현합니다. if (dis < mouseDis) { // 빗방울 삭제 e.die = true // 그리기; 작은 물방울 (원) 호) madedrops(e.posx + speedx * eh, e.posy + eh) } // 빗방울이 끝선을 초과하면 빗방울을 삭제하고 작은 물방울(호)을 그립니다. if ((e.posy + eh) > endLine) { e.die = true; madedrops(e.posx + speedx * eh, e.posy + eh) } // 빗방울의 y 좌표가 보이는 영역의 높이보다 큰 경우 주사위를 설정합니다. true 속성 // 빗방울이 보이는 영역을 초과하면 삭제합니다. if (e.posy >= canvasEl.clientHeight) { e.die = true; } else { // 빗방울의 y 좌표 값을 점차적으로 늘립니다. e.posy = e. posy + e.speed ; // 빗방울의 x 좌표 변경 // * speedx는 빗방울의 낙하 방향을 제어하는 데 사용됩니다. // 빗방울의 낙하 방향을 마우스 이동 방향과 동일하게 만듭니다. e.posx = e .posx + e.speed * 속도x } }); die 속성이 true인 배열 멤버를 삭제합니다. // 마우스 영역, 끝 선 너머, 보이는 영역 외부의 빗방울을 삭제합니다. for (var i = linelist.length - 1; i >= 0; i--) { if (linelist[i].die) { linelist.splice(i, 1); } } // 렌더링 render(); // 애니메이션 효과를 얻기 위해 업데이트를 반복적으로 호출합니다. window.requestAnimationFrame(update); // 렌더링 함수 render() { // 보이는 영역만큼 직사각형을 그립니다. ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, canvasEl.width, canvasEl.height) // 빗방울 효과를 그립니다. lineWidth = 5; linelist.forEach(function (line) { ctx.StrokeStyle = line.color; ctx.beginPath(); ctx.moveTo(line.posx, line.posy); // * speedx는 빗방울의 방향을 제어하는 데 사용됩니다. // 빗방울의 방향을 마우스 이동 방향과 동일하게 만듭니다. ctx.lineTo(line.posx + line. h * speedx, line.posy + line.h); ctx.strok(); }); // 작은 물방울을 형성하기 위해 퍼지는 빗방울을 그립니다. dropList.forEach(function (e) { ctx.beginPath(); ctx.arc(e.posx, e.posy, e.radius, Math.random() * Math.PI * 2, 1 * Math.PI); ctx.Stroke(); }); // 주석을 제거하면 마우스 범위를 볼 수 있습니다./* ctx.arc(mousePos[0], mousePos[1], mouseDis, 0, 2 * Math.PI) */ } } </script></body></html>
위의 내용은 이 기사의 전체 내용입니다. 모든 분들의 학습에 도움이 되기를 바랍니다. 또한 모든 분들이 VeVb Wulin Network를 지지해 주시길 바랍니다.