이전의 Component 리팩토링에 있어서 Zoom/Panning이 완전히 적용되지 않는 문제가 있어 관련된 처리를 한다.
현재 코드의 상태 (이전 작업의 마지막 코드를 참조)에서 발생하는 문제는 다음과 같다.
상기 문제들을 해결할 수 있는 코드를 새로 작성한다.
onClick시 발동하는 animation을 다음과 같은 식으로 구현해 보았다.
setState완료시 해당 변수를 갖고 애니메이션을 시도하는 코드이다.
function animatingViewBox(target, x, y, width, height){
gsap.to(target, {
duration: .5,
attr: {viewBox: `${x} ${y} ${width} ${height}`},
ease: "power3.inOut"
});
}
//중략...
onClick(event){
console.log('on click event');
if(event.target.getAttribute('name'))
{
let rect = event.target.getBoundingClientRect();
console.log(event.target.getAttribute('name'));
this.setState({
current_viewbox : {
x : rect.top,
y : rect.bottom,
width : rect.width,
height: rect.height
}
},
() => {
console.log('set state complete')
animatingViewBox(this.svg,
this.state.current_viewbox.x,
this.state.current_viewbox.y,
this.state.current_viewbox.width,
this.state.current_viewbox.height)
})
}
}
동작하지 않는다.
log도 기재해보았지만 log조차 console에 찍히지 않았다.
이벤트 할당 자체가 되지 않은 것.
관련된 정보를 찾는 도중 다음 링크에 대한 정보를 확인하였다.
상기 링크의 경우, React에 최적화되어있는것은 React 자체적으로 사용하는 onClick이지, JS전체에서 사용되는 addEventListener가 아니라는 것이다.
최적화 및 자동 이벤트 해제를 위하여 React 자체적인 Event on~ 변수를 사용하라는 것이 핵심이다.
하지만 이것은 React컴포넌트의 이야기인 것이지, svg 엘리먼트에 대한 이야기가 아니다. 상기 링크는 다음과 같은 이야기인 것이다.
render(){
return <ReactSVG
onClick = {this.onClick.bind(this)}
beforeInjection = {(inject_svg) => {
this.svg = inject_svg;
inject_svg.setAttribute('width',`${this.state.current_viewbox.width}`);
inject_svg.setAttribute('height',`${this.state.current_viewbox.height}`);
inject_svg.setAttribute('viewBox',`${this.state.current_viewbox.x} ${this.state.current_viewbox.y} ${this.state.current_viewbox.width} ${this.state.current_viewbox.height}`);
inject_svg.addEventListener('wheel', this.onZoom.bind(this));
if (window.PointerEvent) {
inject_svg.addEventListener('pointerdown', this.onPointerDown.bind(this)); // Pointer is pressed
inject_svg.addEventListener('pointerup', this.onPointerUp.bind(this)); // Releasing the pointer
inject_svg.addEventListener('pointerleave', this.onPointerUp.bind(this)); // Pointer gets out of the SVG area
inject_svg.addEventListener('pointermove', this.onPointerMove.bind(this)); // Pointer is moving
} else {
// Add all mouse events listeners fallback
inject_svg.addEventListener('mousedown', this.onPointerDown.bind(this)); // Pressing the mouse
inject_svg.addEventListener('mouseup', this.onPointerUp.bind(this)); // Releasing the mouse
inject_svg.addEventListener('mouseleave', this.onPointerUp.bind(this)); // Mouse gets out of the SVG area
inject_svg.addEventListener('mousemove', this.onPointerMove.bind(this)); // Mouse is moving
// Add all touch events listeners fallback
inject_svg.addEventListener('touchstart', this.onPointerDown.bind(this)); // Finger is touching the screen
inject_svg.addEventListener('touchend', this.onPointerUp.bind(this)); // Finger is no longer touching the screen
inject_svg.addEventListener('touchmove', this.onPointerMove.bind(this)); // Finger is moving
}
}
하지만 SVGElement
에만 관심이 있는 것이지, ReactSVG
컴포넌트 자체의 onClick
이벤트는 관심이 없다.
따라서 React
의 Component
에는 onClick
항목을 사용하되, Element에 대해서는 addEventListener
를 고수한다.
조사 결과, 무조건 pointerdown
이벤트를 통하는 것으로 확인되었다.
전반적으로 수정해야 하는 점은 다음과 같다.