크레이지 캔버스 애니메이션

읽기 전에: 저는 canvas의 전문가라고 주장하지 않습니다. 그러나 수년에 걸쳐 나는 그것에 약간 손을 대었고 이것이 내 발견 중 일부입니다. 당신은 또한 갈 수 있습니다 straight to the fun stuff

최근에 나는 구식 Windows 투쟁을 생각하게 만드는 매우 멋진 패턴을 가진 새 프로젝트를 시작했습니다. 컴퓨터가 정말 바쁠 때 다운로드 창을 전체 화면 위로 드래그하면 제대로 렌더링되지 않는다는 사실을 기억하십니까?
나는 몇 달 전에 "간단한"코드 펜을 만들었는데, 재미로 말 그대로 목적이 없습니다.



무의식적으로 이 펜은 내가 실제 고객을 위해 만들고 싶었던 애니메이션을 위해 나를 준비시켰습니다(그럴 때 사랑하세요).

캔버스?



캔버스가 무엇인지 실제로 알지 못한 채 이 기사를 여기까지 왔을 수도 있습니다. 캔버스는 JavaScript로 웹 페이지에 그래픽을 그리는 데 사용할 수 있는 HTML 요소입니다. 그게 이상하게 들린다면, 당신을 잡았습니다. 조금 이상합니다. 하지만 그것은 또한 이벤트와 상호 작용하고 모든 것을 애니메이션화하는 것과 같은 미친 짓을 할 수 있음을 의미합니다!

가장 먼저 해야 할 일은 JS로 캔버스 요소를 선택하고 그리기 개체인 "컨텍스트"를 가져오는 것입니다. 그것은 무언가를 변경할 때 언급할 캔버스의 일부라고 말하는 정말 이상한 방법입니다.

<canvas id="canvas"></canvas>



const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Don't ask me why this is called ctx and canvas is written out entirely, it doesn't make sense but seems to be the standard.


Animage constructor에서는 JavaScript로 이미지를 추가할 수 있습니다. 로드되었는지 확인하기 위해 이벤트 리스너를 추가할 수도 있습니다.

캔버스multiple properties that can be applied to the context가 있습니다.
이미지 로드 시 창 중앙에 이미지를 추가하기 위해 ctx.drawImage()를 사용했습니다. 🧐

const image = new Image();
image.src = 'http://api.cydstumpel.nl/wp-content/uploads/2020/01/graphic.png';

image.addEventListener('load', e => {
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  // in this case I want to make the canvas as high and wide as the window
  ctx.drawImage(image, window.innerWidth / 2 - image.width / 2, window.innerHeight / 2 - image.height / 2, image.width, image.height);
  // calculating the space left and on top of the image to center it on the page by subtracting half of the page by half of the image.
});




마우스/터치 이벤트가 "down", "up"및 "moving"인지 확인하기 위해 일부 이벤트 리스너를 추가했습니다. 이동 이벤트는 마우스가 페이지 위로 마우스를 가져갈 때가 아니라 마우스를 눌렀을 때(클릭) 발생해야 합니다.

효과와 같은 Windows 오류를 추가하기 위해 배열에 발생한 마지막 5개 이벤트의 좌표를 추가합니다.

// [...]
let lastImages = [];
// declare lastImages as an array in the global scope
// [...]

canvas.addEventListener('mousemove', (e) => {
  x = e.clientX - image.width / 2;
  y = e.clientY - image.height / 2;
  // to make sure the image will be centred around the mouse remove half the width and height respectively

  // Save coordinates to last images as long as it's < 5
  if (lastImages.length < 5) {
    lastImages.push({x, y});
  } else {
    // Delete first item in array (first item is last added) and add new coordinates
    lastImages.shift();
    lastImages.push({x, y});
  }
  // The code above makes sure that there are not more than 5 elements on the screen at the time, adding more could definitely slow down your browser.
  if (mouseDown) {
    // check if mouse is down before firing drawIt function
    window.requestAnimationFrame(drawIt);
  }
});


그리기 기능:

function drawIt() {
  if (mouseDown || popping) {
    // Clear entire canvas because clearing just the image doesn't work unfortunately
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    // Draw new image for each item in lastImages array
    // For loops are faster than foreach I read somewhere
    for (let i = 0; i < lastImages.length; i++) {
      // After clearing the entire canvas draw the images from the lastImages array again
      ctx.drawImage(image, lastImages[i].x, lastImages[i].y, image.width, image.height);
    }
  }
}

popIt 함수는 마우스가 올라가거나 나갈 때 호출됩니다.

function popIt() {
  mouseDown = false;
  // Okay this is a bit gross, I know about intervals this just works better:
  for (let i = 0; i < 5; i++) {
    setTimeout(removeLastItems, 50 * (-i * 1.2) );
    // -i * 1.2 creates an increasingly faster timeout simulating a fade in bezier
  }
}


removeFirstItems 함수는 배열의 첫 번째 항목(배열에 추가된 첫 번째 항목과 같음)을 이동(제거)합니다.

if (!mouseDown && lastImages.length > 1) {
  popping = true;
  // Get first drawn image and remove it from array (first drawn is first in array)
  lastImages.shift();
  drawIt();
  // initiate drawIt function without the request keyframe for it's only fired 5 times 
}


재미있는 것들



큰 화면에서 실제로 확인해야 합니다. 드래그할 공간이 많을 때 훨씬 더 잘 작동합니다.



무엇이든 물어보세요



내 말을 이해하지 못하거나 동의하지 않는 경우 주저하지 말고 이 기사에 의견을 추가하십시오. :)
디바운싱 이벤트에 대해 정말로 생각해야 한다고 언급한 지난주 댓글 작성자에게 큰 감사를 드립니다. 하지만 여전히 내 포트폴리오에 실제로 구현해야 합니다😅.

좋은 웹페이지 즐겨찾기