Spaces:
Running
Running
fix: prevent page scroll when zooming phylo tree (non-passive wheel listener)
Browse files
bioai-platform/frontend/src/components/phylo/PhyloTreeViewer.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
-
import { useCallback, useMemo, useRef, useState } from 'react'
|
| 4 |
|
| 5 |
// βββ Types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 6 |
|
|
@@ -691,13 +691,9 @@ export default function PhyloTreeViewer({
|
|
| 691 |
downloadBlob(new Blob([newick], { type: 'text/plain' }), `${filename}.nwk`)
|
| 692 |
}, [newick, filename])
|
| 693 |
|
| 694 |
-
const resetView = useCallback(() => {
|
| 695 |
-
setTransform({ scale: 1, x: 0, y: 0 })
|
| 696 |
-
}, [])
|
| 697 |
-
|
| 698 |
// ββ Zoom / pan event handlers ββββββββββββββββββββββββββββββββββββββββββββββ
|
| 699 |
|
| 700 |
-
const handleWheel = useCallback((e:
|
| 701 |
e.preventDefault()
|
| 702 |
const svg = svgRef.current
|
| 703 |
if (!svg) return
|
|
@@ -715,6 +711,18 @@ export default function PhyloTreeViewer({
|
|
| 715 |
})
|
| 716 |
}, [transform])
|
| 717 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 718 |
const handleMouseDown = useCallback((e: React.MouseEvent<SVGSVGElement>) => {
|
| 719 |
if (e.button !== 0) return
|
| 720 |
setIsDragging(true)
|
|
@@ -868,7 +876,6 @@ export default function PhyloTreeViewer({
|
|
| 868 |
width="100%"
|
| 869 |
style={{ maxHeight: '70vh', background: '#04040A', cursor: isDragging ? 'grabbing' : 'grab' }}
|
| 870 |
xmlns="http://www.w3.org/2000/svg"
|
| 871 |
-
onWheel={handleWheel}
|
| 872 |
onMouseDown={handleMouseDown}
|
| 873 |
onMouseMove={handleMouseMove}
|
| 874 |
onMouseUp={handleMouseUp}
|
|
|
|
| 1 |
'use client'
|
| 2 |
|
| 3 |
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
| 4 |
|
| 5 |
// βββ Types ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 6 |
|
|
|
|
| 691 |
downloadBlob(new Blob([newick], { type: 'text/plain' }), `${filename}.nwk`)
|
| 692 |
}, [newick, filename])
|
| 693 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 694 |
// ββ Zoom / pan event handlers ββββββββββββββββββββββββββββββββββββββββββββββ
|
| 695 |
|
| 696 |
+
const handleWheel = useCallback((e: WheelEvent) => {
|
| 697 |
e.preventDefault()
|
| 698 |
const svg = svgRef.current
|
| 699 |
if (!svg) return
|
|
|
|
| 711 |
})
|
| 712 |
}, [transform])
|
| 713 |
|
| 714 |
+
// Attach non-passive wheel listener so e.preventDefault() blocks page scroll
|
| 715 |
+
useEffect(() => {
|
| 716 |
+
const el = svgRef.current
|
| 717 |
+
if (!el) return
|
| 718 |
+
el.addEventListener('wheel', handleWheel, { passive: false })
|
| 719 |
+
return () => el.removeEventListener('wheel', handleWheel)
|
| 720 |
+
}, [handleWheel])
|
| 721 |
+
|
| 722 |
+
const resetView = useCallback(() => {
|
| 723 |
+
setTransform({ scale: 1, x: 0, y: 0 })
|
| 724 |
+
}, [])
|
| 725 |
+
|
| 726 |
const handleMouseDown = useCallback((e: React.MouseEvent<SVGSVGElement>) => {
|
| 727 |
if (e.button !== 0) return
|
| 728 |
setIsDragging(true)
|
|
|
|
| 876 |
width="100%"
|
| 877 |
style={{ maxHeight: '70vh', background: '#04040A', cursor: isDragging ? 'grabbing' : 'grab' }}
|
| 878 |
xmlns="http://www.w3.org/2000/svg"
|
|
|
|
| 879 |
onMouseDown={handleMouseDown}
|
| 880 |
onMouseMove={handleMouseMove}
|
| 881 |
onMouseUp={handleMouseUp}
|