11/* eslint-disable react/require-default-props */
2- import React , { useMemo , useRef , useState } from "react" ;
2+ import React , {
3+ useCallback ,
4+ useEffect ,
5+ useMemo ,
6+ useRef ,
7+ useState ,
8+ } from "react" ;
39
410import {
511 useTransformContext ,
612 useTransformEffect ,
713 useTransformInit ,
814} from "hooks" ;
915import { useResize } from "./use-resize.hook" ;
16+ import { ReactZoomPanPinchRef } from "models" ;
1017
1118export type MiniMapProps = {
19+ children : React . ReactNode ;
1220 width ?: number ;
1321 height ?: number ;
14- children : React . ReactNode ;
1522} & React . DetailedHTMLProps <
1623 React . HTMLAttributes < HTMLDivElement > ,
1724 HTMLDivElement
@@ -34,33 +41,37 @@ export const MiniMap: React.FC<MiniMapProps> = ({
3441 children,
3542 ...rest
3643} ) => {
37- const [ size , setSize ] = useState ( { width : 0 , height : 0 } ) ;
44+ const [ initialized , setInitialized ] = useState ( false ) ;
3845 const instance = useTransformContext ( ) ;
46+ const miniMapInstance = useRef < ReactZoomPanPinchRef > ( null ) ;
3947
48+ const mainRef = useRef < HTMLDivElement | null > ( null ) ;
4049 const wrapperRef = useRef < HTMLDivElement | null > ( null ) ;
4150 const previewRef = useRef < HTMLDivElement | null > ( null ) ;
4251
43- const getContentSize = ( ) => {
52+ const getContentSize = useCallback ( ( ) => {
4453 if ( instance . contentComponent ) {
54+ const rect = instance . contentComponent . getBoundingClientRect ( ) ;
55+
4556 return {
46- width : instance . contentComponent . offsetWidth ,
47- height : instance . contentComponent . offsetHeight ,
57+ width : rect . width / instance . transformState . scale ,
58+ height : rect . height / instance . transformState . scale ,
4859 } ;
4960 }
5061 return {
5162 width : 0 ,
5263 height : 0 ,
5364 } ;
54- } ;
65+ } , [ instance . contentComponent , instance . transformState . scale ] ) ;
5566
56- const computeMiniMapScale = ( ) => {
67+ const computeMiniMapScale = useCallback ( ( ) => {
5768 const contentSize = getContentSize ( ) ;
5869 const scaleX = width / contentSize . width ;
5970 const scaleY = height / contentSize . height ;
6071 const scale = scaleY > scaleX ? scaleX : scaleY ;
6172
6273 return scale ;
63- } ;
74+ } , [ getContentSize , height , width ] ) ;
6475
6576 const computeMiniMapSize = ( ) => {
6677 const contentSize = getContentSize ( ) ;
@@ -72,55 +83,53 @@ export const MiniMap: React.FC<MiniMapProps> = ({
7283 return { width : contentSize . width * scaleY , height } ;
7384 } ;
7485
75- const computeWrapperStyle = ( ) => {
76- return {
77- width : instance . contentComponent ?. offsetWidth || 0 ,
78- height : instance . contentComponent ?. offsetHeight || 0 ,
79- } ;
80- } ;
81-
8286 const computeMiniMapStyle = ( ) => {
8387 const scale = computeMiniMapScale ( ) ;
84- return {
88+ const style = {
8589 transform : `scale(${ scale || 1 } )` ,
8690 transformOrigin : "0% 0%" ,
8791 position : "absolute" ,
8892 boxSizing : "border-box" ,
8993 zIndex : 1 ,
9094 overflow : "hidden" ,
9195 } as const ;
96+
97+ Object . keys ( style ) . forEach ( ( key ) => {
98+ if ( wrapperRef . current ) {
99+ wrapperRef . current . style [ key ] = style [ key ] ;
100+ }
101+ } ) ;
92102 } ;
93103
94104 const transformMiniMap = ( ) => {
95- const style = computeWrapperStyle ( ) ;
105+ computeMiniMapStyle ( ) ;
106+ const miniSize = computeMiniMapSize ( ) ;
107+ const wrapSize = getContentSize ( ) ;
96108 if ( wrapperRef . current ) {
97- wrapperRef . current . style . width = `${ style . width } px` ;
98- wrapperRef . current . style . width = `${ style . width } px` ;
99- wrapperRef . current . style . height = `${ style . height } px` ;
109+ wrapperRef . current . style . width = `${ wrapSize . width } px` ;
110+ wrapperRef . current . style . height = `${ wrapSize . height } px` ;
111+ }
112+ if ( mainRef . current ) {
113+ mainRef . current . style . width = `${ miniSize . width } px` ;
114+ mainRef . current . style . height = `${ miniSize . height } px` ;
100115 }
101116 if ( previewRef . current ) {
117+ const size = getContentSize ( ) ;
102118 const scale = computeMiniMapScale ( ) ;
103119 const previewScale = scale * ( 1 / instance . transformState . scale ) ;
104120 const transform = instance . handleTransformStyles (
105121 - instance . transformState . positionX * previewScale ,
106122 - instance . transformState . positionY * previewScale ,
107123 1 ,
108124 ) ;
125+
109126 previewRef . current . style . transform = transform ;
110- previewRef . current . style . width = `${ style . width * previewScale } px` ;
111- previewRef . current . style . height = `${ style . height * previewScale } px` ;
127+ previewRef . current . style . width = `${ size . width * previewScale } px` ;
128+ previewRef . current . style . height = `${ size . height * previewScale } px` ;
112129 }
113130 } ;
114131
115132 const initialize = ( ) => {
116- const style = computeMiniMapStyle ( ) ;
117- const initSize = computeMiniMapSize ( ) ;
118- setSize ( initSize ) ;
119- Object . keys ( style ) . forEach ( ( key ) => {
120- if ( wrapperRef . current ) {
121- wrapperRef . current . style [ key ] = style [ key ] ;
122- }
123- } ) ;
124133 transformMiniMap ( ) ;
125134 } ;
126135
@@ -130,24 +139,37 @@ export const MiniMap: React.FC<MiniMapProps> = ({
130139
131140 useTransformInit ( ( ) => {
132141 initialize ( ) ;
142+ setInitialized ( true ) ;
133143 } ) ;
134144
135- useResize ( instance . contentComponent , ( ) => {
136- initialize ( ) ;
137- } ) ;
145+ useResize ( instance . contentComponent , initialize , [ initialized ] ) ;
146+
147+ useEffect ( ( ) => {
148+ return instance . onChange ( ( zpp ) => {
149+ const scale = computeMiniMapScale ( ) ;
150+ if ( miniMapInstance . current ) {
151+ miniMapInstance . current . instance . transformState . scale =
152+ zpp . instance . transformState . scale ;
153+ miniMapInstance . current . instance . transformState . positionX =
154+ zpp . instance . transformState . positionX * scale ;
155+ miniMapInstance . current . instance . transformState . positionY =
156+ zpp . instance . transformState . positionY * scale ;
157+ }
158+ } ) ;
159+ } , [ computeMiniMapScale , instance , miniMapInstance ] ) ;
138160
139161 const wrapperStyle = useMemo ( ( ) => {
140162 return {
141- ...size ,
142163 position : "relative" ,
143164 zIndex : 2 ,
144165 overflow : "hidden" ,
145166 } as const ;
146- } , [ size ] ) ;
167+ } , [ ] ) ;
147168
148169 return (
149170 < div
150171 { ...rest }
172+ ref = { mainRef }
151173 style = { wrapperStyle }
152174 className = { `rzpp-mini-map ${ rest . className || "" } ` }
153175 >
0 commit comments