>  기사  >  웹 프론트엔드  >  캔버스의 고정점 확대 축소

캔버스의 고정점 확대 축소

WBOY
WBOY원래의
2024-07-18 05:56:57910검색

스틱 포인트를 사용한 확대/축소는 Figma와 같은 디자인 또는 제작 도구에서 흔히 볼 수 있는 일반적인 사용 사례입니다. 이번 블로그에서는 이를 자바스크립트, HTML, CSS로 처리하기 위한 기본 알고리즘을 제시하겠습니다.

데모

시연

코드 단계별

1. 컨테이너와 확장 가능한 아이템 생성

<div id="app">
      <div class="parent">
        <div class="scalable-child"></div>
      </div>
</div>
.scalable-child {
  width: 300px;
  height: 300px;
  position: relative;
  top: 0;
  left: 0;
  pointer-events: none;
  transform-origin: left top;
  background-image: url('https://cdn4.vectorstock.com/i/1000x1000/17/58/caro-pattern-background-vector-2261758.jpg');
  background-size: contain;
}
.parent {
  position: relative;
  background-color: white;
  width: 100vw;
  height: 100vh;
}

이 예에서는 div를 "scalable-child" 클래스의 확장 가능한 항목으로 사용하고 해당 컨테이너는 "parent" 클래스의 div입니다.
일부 숙소에 대해 참고하세요:

  • 위, 왼쪽: 0이 기본 위치입니다

  • 포인터 이벤트: 없음, 상위 이벤트에 이벤트를 추가하므로 포인터 이벤트 !== 없음인 경우 알고리즘이 실패합니다.

  • Transform-origin : 왼쪽 상단, 좌표 원점을 만들어 위치를 계산하는

2. 휠 이벤트 리스너 추가

const parent = document.querySelector('.parent');
const child = document.querySelector('.scalable-child');

parent.addEventListener('wheel', wheelEventHandler, {
  passive: false,
  capture: true,
});

WheelEvent를 사용하여 확대, 축소 및 자식 이동을 처리합니다

참고: 이 예는 트랙패드에만 해당됩니다. (Ctrl +, Ctr -)나 마우스 등의 단축키에 대한 이벤트도 처리해야 합니다.

let left = 0;
let top = 0;
let scale = 1;

const wheelEventHandler = (e) => {
  e.preventDefault();
  // Handle zoom with touch pad and hot key.
  const isZooming = e.ctrlKey || e.metaKey;
  let newValues = {};
  if (isZooming) {
    newValues = calculateOnZooming(e, scale, left, top);
  } else {
    newValues = calculateOnMoving(e, scale, left, top);
  }

  left = newValues.newLeft;
  top = newValues.newTop;
  scale = newValues.newScale;

  Object.assign(child.style, {
    transform: `scale(${scale})`,
    left: `${left}px`,
    top: `${top}px`,
  });
};

먼저, 하위 요소를 확대/축소하거나 이동하는지 확인하기 위한 isZooming 변수가 있습니다.

그런 다음 하위 요소의 새 위치와 크기를 계산합니다. 온대 변수로는 좌측, 상단, 스케일을 사용하고 있습니다.

이제 알고리즘을 2가지 계산 함수에 집중할 시간입니다.

3. 확대/축소하여 계산

const calculateOnZooming = (e, oldScale, oldLeft, oldTop) => {
  let newScale = oldScale - e.deltaY * oldScale * 0.01;
  newScale = Math.max(newScale, 0.1);
  const newLeft = oldLeft - (e.offsetX - oldLeft) * (newScale / scale - 1);
  const newTop = oldTop - (e.offsetY - oldTop) * (newScale / scale - 1);
  return {
    newScale,
    newLeft,
    newTop,
  };
};

확대/축소 시 휠이벤트는 deltaY를 배율 비율로 반환하며 이를 사용하여 newScale을 계산할 수 있습니다

  • 델타Y > 0 => 축소

  • 델타Y < 0 => 확대
    detalScale = e.deltaY * oldScale * 0.01로 스케일링 속도 제어

newLeft 및 newTop 변수를 계산하는 방법을 더 자세히 이해하려면 아래 이미지를 살펴보겠습니다.

Image description
마우스가 A 지점에 있을 때 하위 항목 확대를 시작합니다. 이때 다음과 같은 값을 얻을 수 있습니다.

  • e.offsetX: 마우스와 부모 왼쪽 가장자리 사이의 거리

  • e.offsetY: 마우스와 부모 상단 가장자리 사이의 거리

  • left: 현재 자식의 왼쪽 스타일 값

  • top: 현재 어린이의 최고 스타일 값

어린이는 scale ratio에서 scale' ratio로 스케일링되고 A점은 A'로 ​​이동합니다.
따라서 A 지점을 (부모와 함께) 고정시키려면 deltaX 및 deltaY를 계산한 다음 정확히 px로 하위 되돌리기를 이동해야 합니다.

detalX = x' - x
= x * (규모' / 규모) - x
= x * (규모' / 규모 - 1)
= (e.offsetX - 왼쪽) * (scale' / scale - 1)

detalY = y' - y
= y * (규모' / 규모) - y
= y * (규모' / 규모 - 1)
= (e.offsetY - 상단) * (scale' / scale - 1)

newLeft = 왼쪽 - detalX
newTop = 상단 - 세부정보

4. 이사시 계산

const calculateOnMoving = (e, oldScale, oldLeft, oldTop) => {
  return {
    newLeft: oldLeft - e.deltaX * 2,
    newTop: oldTop - e.deltaY * 2,
    newScale: oldScale,
  };
};

이동 이벤트에서는 newLeft 및 newTop 값만 계산하면 됩니다. 그리고 속도를 높이기 위해 각 델타 값을 *2로 늘렸습니다.

우리가 처리해야 할 것은 이것이 전부입니다. 도움이 되었기를 바랍니다. 시청해주셔서 감사합니다!
여기에서 전체 소스 코드를 볼 수 있습니다.

위 내용은 캔버스의 고정점 확대 축소의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.