@@ -147,13 +147,13 @@ export class UIManager {
147147 zoomInBtn . title = "Zoom In" ;
148148 zoomInBtn . type = "button" ;
149149 zoomInBtn . setAttribute ( "aria-label" , "Zoom In" ) ;
150- zoomInBtn . onclick = ( ) => this . panzoom . zoomIn ( ) ;
150+ zoomInBtn . onclick = ( ) => this . zoomFromCenterByStep ( 1 ) ;
151151 const zoomOutBtn = document . createElement ( "button" ) ;
152152 zoomOutBtn . appendChild ( this . createIcon ( "zoom-out" , "Zoom Out" ) ) ;
153153 zoomOutBtn . title = "Zoom Out" ;
154154 zoomOutBtn . type = "button" ;
155155 zoomOutBtn . setAttribute ( "aria-label" , "Zoom Out" ) ;
156- zoomOutBtn . onclick = ( ) => this . panzoom . zoomOut ( ) ;
156+ zoomOutBtn . onclick = ( ) => this . zoomFromCenterByStep ( - 1 ) ;
157157 const resetZoomBtn = document . createElement ( "button" ) ;
158158 resetZoomBtn . appendChild ( this . createIcon ( "reset" , "Reset Zoom" ) ) ;
159159 resetZoomBtn . title = "Reset Zoom" ;
@@ -251,6 +251,36 @@ export class UIManager {
251251 this . toolbar . appendChild ( palettePanelBtn ) ;
252252 }
253253
254+ private getCanvasCenterFocal ( ) : { x : number ; y : number } {
255+ const rect = this . canvas . getBoundingClientRect ( ) ;
256+ return {
257+ x : rect . left + rect . width / 2 ,
258+ y : rect . top + rect . height / 2 ,
259+ } ;
260+ }
261+
262+ /**
263+ * Use zoomToPoint to zoom from the container center by one wheel step.
264+ * direction: +1 for zoom in, -1 for zoom out
265+ */
266+ private zoomFromCenterByStep ( direction : 1 | - 1 ) {
267+ const options = this . panzoom . getOptions ( ) ;
268+ const step = Number ( options . step ?? 0.3 ) ;
269+ const minScale = Number ( options . minScale ?? 0.1 ) ;
270+ const maxScale = Number ( options . maxScale ?? this . maxScale ) ;
271+ const currentScale = this . panzoom . getScale ( ) ;
272+ const wheelLikeStep = Math . exp ( direction * step ) ;
273+ const targetScale = Math . min (
274+ maxScale ,
275+ Math . max ( minScale , currentScale * wheelLikeStep ) ,
276+ ) ;
277+ const focal = this . getCanvasCenterFocal ( ) ;
278+ this . panzoom . zoomToPoint ( targetScale , {
279+ clientX : focal . x ,
280+ clientY : focal . y ,
281+ } ) ;
282+ }
283+
254284 private createPageSelector ( ) {
255285 let currentIndex = this . currentPageIndex ;
256286 const select = document . createElement ( "select" ) ;
0 commit comments