JavaScript Canvas의 초공간 여행
42737 단어 beginnersjavascripttutorial
따라서 먼저 html 파일에
canvas
요소를 만들고 javascript를 보관할 script
태그도 만듭니다.<body>
<canvas></canvas>
<script></script>
</body>
그런 다음
script
태그에서 캔버스 요소를 얻습니다.const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
별
이제
Star
에 대한 청사진을 정의해 보겠습니다. 각 별에는 위치 (x,y)
, radius
, color
및 캔버스에 별을 그리는 draw
함수가 있습니다.function Star(x,y,radius,color){
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.draw = function (){
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
ctx.stroke();
ctx.fill();
}
}
별 개체를 보관할 배열을 만들고
const
생성할 별의 수를 지정합니다.const NUMBER_OF_STARS = 1000;
let stars = [];
별을 만드는 함수를 작성하고 임의의 위치를 사용하므로 간단한 난수 생성기를 사용할 수 있습니다.
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min) + min);
}
function createStars() {
for (let counter = 0; counter < NUMBER_OF_STARS; counter++) {
let radius = getRandomInt(1, 3);
let x = getRandomInt(radius, (canvas.width - radius));
let y = getRandomInt(radius, (canvas.height - radius));
let color = "lightblue";
stars.push(
new Star(x, y, radius, color)
);
}
}
화면에 그리는 또 다른 빠른 루프.
createStars();
stars.forEach(star => star.draw());
반지름이 다른 별을 만들면 멀리 있는 사람은 거의 없고 가까이 있는 사람은 거의 없는 것처럼 느껴집니다.
이제 중요한 내용인 초공간으로 점프하는 방법입니다.
움직임
영화 장면에서 우리는 광속으로 여행할 때 각 별이 해당 위치에서 화면 가장자리로 이동한다는 것을 알 수 있지만
angle
또는 linepath
를 계산해야 합니다.이를 단순화하기 위해 중심점을 가정할 수 있으며 중심에서 별까지 선을 그리면 기본적으로 별이 화면 가장자리에 도달할 때까지 따라가는 경로입니다. 아래와 같이
이제 각 라인에 두 개의 포인트가 있습니다. 첫 번째 포인트는 화면의 중심이고 두 번째 포인트는 별의 위치입니다. 다음 공식을 사용하여 나중에 별을 이동하는 데 사용할 수 있는 선의
slope
를 계산할 수 있습니다.m=(y2−y1)(x2−x1)
m =\frac {(y_2-y_1)} {(x_2-x_1)}
m=(x2 −x1 )(y2 −y1 )
따라서
slope
속성을 Star
에 추가하겠습니다.function Star(x,y,radius,color, slope){
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.slope = slope;
this.draw = function (){
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
ctx.stroke();
ctx.fill();
}
}
다음과 같이 함수를 정의합니다.
function slopeFromCenter(x, y) {
let x1 = x;
let y1 = y;
let x2 = centerX;
let y2 = centerY;
return (y2 - y1) / (x2 - x1);
}
이제 Star Object 생성을 다음과 같이 변경하십시오.
stars.push(new Star(x, y, radius, color, slopeFromCenter(x, y)));
애니메이션 루프
애니메이션은 프레임마다 한 번씩 호출되는
requestAnimationFrame
메서드를 사용하고 스페이스바 키를 사용하여 이동을 시작하고 중지하기 위해 다음과 같이 변수travel
를 생성합니다.let travel = null;
기본
jump
메서드도 생성하고 나중에 변경할 수 있습니다.function jump() {
for (let i = 0; i < stars.length; i++) {
const star = stars[i];
ctx.beginPath();
ctx.moveTo(star.x, star.y);
// we will work these in a minute
const nextXY = [star.x + 1, star.y + 1];
const nextX = nextXY[0];
const nextY = nextXY[1];
ctx.lineTo(nextX, nextY);
ctx.strokeStyle = star.color;
ctx.lineWidth = star.radius;
ctx.stroke();
ctx.closePath();
star.x = nextX;
star.y = nextY;
}
}
우리가 하는 일은 단순히
1
를 별의 좌표xy
에 더하는 것뿐입니다.let travel = null;
function animate() {
travel = requestAnimationFrame(animate);
jump();
}
window.addEventListener("keypress", function (event) {
if (event.key === " ") {
if (travel == null) {
travel = window.requestAnimationFrame(animate);
} else {
window.cancelAnimationFrame(travel);
travel = null;
}
}
});
xy
값을 1씩 증가시키면서 별이 오른쪽 하단 모서리로 이동하는 것을 볼 수 있습니다. 이제 다음과 같이 nextStop
함수를 정의하여 실제 이동 코드를 수행해 보겠습니다.function nextStop(currentX, currentY, m, velocity) {
let s = velocity / Math.sqrt(1 + m * m);
let nextX = currentX + s;
let nextY = currentY + m * s;
return [Math.ceil(nextX), Math.ceil(nextY)];
}
이 함수는 단순히
(x,y)
, slope
및 velocity
를 취하고 새로운 좌표를 반환합니다. 속도를 조정하여 이동 속도도 조정할 수 있습니다.다음과 같이
jump
함수를 사용하도록 nextStop
함수를 업데이트합니다.function jump() {
for (let i = 0; i < stars.length; i++) {
const star = stars[i];
ctx.beginPath();
ctx.moveTo(star.x, star.y);
// update the following line
const nextXY = nextStop(star.x, star.y, star.slope, 20);
const nextX = nextXY[0];
const nextY = nextXY[1];
ctx.lineTo(nextX, nextY);
ctx.strokeStyle = star.color;
ctx.lineWidth = star.radius;
ctx.stroke();
ctx.closePath();
star.x = nextX;
star.y = nextY;
}
}
하지만...
보시다시피 오른쪽 절반은 오른쪽이고 왼쪽 절반은 화면이 반전되어 있습니다. 이것은 우리가 계산한 기울기 때문입니다. 해당 업데이트를 수정하려면 다음과 같이
slopeFromCenter
함수를 업데이트하십시오.function slopeFromCenter(x, y) {
let x1 = x;
let y1 = y;
let x2 = centerX;
let y2 = centerY;
let q = null; // Quadrant
let direction = 1;
if (x > centerX && y <= centerY) {
q = "Q1";
} else if (x <= centerX && y <= centerY) {
q = "Q2";
} else if (x <= centerX && y > centerY) {
q = "Q3";
} else if (x > centerX && y > centerY) {
q = "Q4";
}
if (q == "Q2" || q == "Q3") {
direction = -1;
}
return [(y2 - y1) / (x2 - x1), direction];
}
그리고 다음과 같이
createStars
메서드를 업데이트합니다.function createStars() {
for (let counter = 0; counter < NUMBER_OF_STARS; counter++) {
let radius = getRandomInt(1, 4);
let x = getRandomInt(radius, (canvas.width - radius));
let y = getRandomInt(radius, (canvas.height - radius));
let color = "white";
let slopeAndDirection = slopeFromCenter(x, y);
stars.push(
new Star(x, y, radius, slopeAndDirection[0], slopeAndDirection[1], color)
);
}
}
또한
jump
기능을 업데이트하여 방향을 사용하고 별이 화면 가장자리에 도달하면 임의의 위치에서 별을 다시 생성합니다. 새 개체를 만드는 대신 단순히 위치를 변경하여 새 별처럼 느껴지도록 합니다. 메모리 및 성능에 더 좋습니다.function jump() {
for (let i = 0; i < stars.length; i++) {
const star = stars[i];
if (
star.x <= 0 ||
star.x > canvas.width ||
star.y <= 0 ||
star.y > canvas.height
) {
star.x = Math.ceil(
Math.random() * (window.innerWidth - star.radius * 2 + star.radius)
);
star.y = Math.ceil(
Math.random() * (window.innerHeight - star.radius * 2 + star.radius)
);
const slopeAndDirection = slopeFromCenter(star.x, star.y);
star.slope = slopeAndDirection[0];
star.direction = slopeAndDirection[1];
}
ctx.beginPath();
ctx.moveTo(star.x, star.y);
const nextXY = nextStop(
star.x * star.direction,
star.y * star.direction,
star.slope,
20
);
const nextX = nextXY[0];
const nextY = nextXY[1];
ctx.lineTo(nextX * star.direction, nextY * star.direction);
ctx.strokeStyle = star.color;
ctx.lineWidth = star.radius;
ctx.stroke();
ctx.closePath();
star.x = nextX * star.direction;
star.y = nextY * star.direction;
}
}
이제 잘 작동하겠지만... 시간이 지남에 따라 화면이 완전히 채워질 것입니다... 멋진 애니메이션을 만들기 위해
animate
기능을 수정합니다. 여기서는 ctx.fillRect
를 사용하여 화면이 완전히 채워지는 것을 방지하는 검은색 투명 색상으로 화면을 채웁니다.function animate() {
travel = requestAnimationFrame(animate);
ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.fillRect(0, 0, window.innerWidth, innerHeight);
jump();
}
최종 결과에 액세스할 수 있습니다here.
시작하거나 중지하려면
Spacebar
를 누르십시오.+
속도를 높이는 키,-
속도를 늦추고 여행을 즐기는 열쇠 :)기타 개선 사항이 거의 없는 전체 코드가 링크됨here
고맙습니다...
Reference
이 문제에 관하여(JavaScript Canvas의 초공간 여행), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/dillir07/hyperspace-travel-in-javascript-canvas-418g텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)