65 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			65 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								(function () {
							 | 
						||
| 
								 | 
							
								    const EXTREME_ZOOM_MIN = 1e-4;
							 | 
						||
| 
								 | 
							
								    const EXTREME_ZOOM_MAX = 1e4;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								    function applyCustomZoomHandling(cy) {
							 | 
						||
| 
								 | 
							
								      let zoomFramePending = false;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								      if (!cy || typeof cy.zoom !== 'function') {
							 | 
						||
| 
								 | 
							
								        console.warn('🚫 유효하지 않은 Cytoscape 인스턴스입니다.');
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								      cy.userZoomingEnabled(false); // Cytoscape 기본 줌 비활성화
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								      const container = cy.container();
							 | 
						||
| 
								 | 
							
								      if (!container) {
							 | 
						||
| 
								 | 
							
								        console.warn('🚫 Cytoscape container를 찾을 수 없습니다.');
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								      container.addEventListener(
							 | 
						||
| 
								 | 
							
								        'wheel',
							 | 
						||
| 
								 | 
							
								        (event) => {
							 | 
						||
| 
								 | 
							
								          event.preventDefault();
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								          if (zoomFramePending) return;
							 | 
						||
| 
								 | 
							
								          zoomFramePending = true;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								          requestAnimationFrame(() => {
							 | 
						||
| 
								 | 
							
								            const currentZoom = cy.zoom();
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								            const clampedDelta = Math.max(-100, Math.min(100, event.deltaY));
							 | 
						||
| 
								 | 
							
								            const zoomFactor = 1 + (clampedDelta > 0 ? -0.05 : 0.05);
							 | 
						||
| 
								 | 
							
								            const nextZoom = currentZoom * zoomFactor;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								            const isValid =
							 | 
						||
| 
								 | 
							
								              isFinite(nextZoom) &&
							 | 
						||
| 
								 | 
							
								              nextZoom >= EXTREME_ZOOM_MIN &&
							 | 
						||
| 
								 | 
							
								              nextZoom <= EXTREME_ZOOM_MAX;
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								            if (isValid) {
							 | 
						||
| 
								 | 
							
								              const rect = container.getBoundingClientRect();
							 | 
						||
| 
								 | 
							
								              const renderedPosition = {
							 | 
						||
| 
								 | 
							
								                x: event.clientX - rect.left,
							 | 
						||
| 
								 | 
							
								                y: event.clientY - rect.top
							 | 
						||
| 
								 | 
							
								              };
							 | 
						||
| 
								 | 
							
								              cy.zoom({
							 | 
						||
| 
								 | 
							
								                level: nextZoom,
							 | 
						||
| 
								 | 
							
								                renderedPosition
							 | 
						||
| 
								 | 
							
								              });
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								              console.warn("🚫 휠 줌 비정상 값 차단:", nextZoom);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								            zoomFramePending = false;
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        { passive: false }
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								    // ✅ 전역(window)으로 함수 등록
							 | 
						||
| 
								 | 
							
								    window.applyCustomZoomHandling = applyCustomZoomHandling;
							 | 
						||
| 
								 | 
							
								  })();
							 | 
						||
| 
								 | 
							
								  
							 |