스틱 포인트를 사용한 확대/축소는 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 변수를 계산하는 방법을 더 자세히 이해하려면 아래 이미지를 살펴보겠습니다.
마우스가 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!