@@ -11,7 +11,10 @@ import { createMeasure, createPageGroup } from './renderer.js';
1111const canvas = SVG ( ) . addTo ( CONFIG . container )
1212 . size ( CONFIG . screenWidth , CONFIG . screenHeight )
1313 . viewbox ( - CONFIG . autoMargin , - CONFIG . autoMargin , CONFIG . screenWidth , CONFIG . screenHeight ) ;
14- canvas . panZoom ( { zoomMin : 0.25 , zoomMax : 5 , zoomFactor : 0.1 } ) ;
14+ canvas . panZoom ( {
15+ wheelZoom : false , // custom logic instead
16+ panning : true
17+ } ) ;
1518
1619setupEditorUI ( ) ; // Initialize UI
1720const musicLayer = canvas . group ( ) . id ( "music-layer" ) ;
@@ -105,13 +108,65 @@ document.querySelectorAll(".icon").forEach(icon => {
105108
106109// Adding Measures
107110document . getElementById ( "add-measure-btn" ) . addEventListener ( "click" , ( ) => {
108- for ( let i = 0 ; i < 150 ; ++ i ) addMeasure ( ) ;
111+ for ( let i = 0 ; i < 400 ; ++ i ) addMeasure ( ) ;
109112 addMeasure ( ) ;
110113} ) ;
111114
112115// Zooming
113- document . getElementById ( "zoom-in" ) . addEventListener ( "click" , ( ) => canvas . zoom ( canvas . zoom ( ) * 1.2 ) ) ;
114- document . getElementById ( "zoom-out" ) . addEventListener ( "click" , ( ) => canvas . zoom ( canvas . zoom ( ) / 1.2 ) ) ;
116+ function getZoom ( zoom ) { // keep zoom within boundaries
117+ return Math . min ( Math . max ( zoom , CONFIG . zoomMin ) , CONFIG . zoomMax ) ;
118+ }
119+ document . getElementById ( "zoom-in" ) . addEventListener ( "click" , ( ) => canvas . zoom ( getZoom ( canvas . zoom ( ) * ( 1 + CONFIG . zoomFactor ) ) ) ) ;
120+ document . getElementById ( "zoom-out" ) . addEventListener ( "click" , ( ) => canvas . zoom ( getZoom ( canvas . zoom ( ) / ( 1 + CONFIG . zoomFactor ) ) ) ) ;
121+ canvas . on ( "wheel" , e => {
122+ e . preventDefault ( ) ;
123+
124+ let newY = 0 ; // default initialize to 0 (we change it later)
125+ if ( e . ctrlKey ) { // zoom
126+ const zFactor = 1 + CONFIG . zoomFactor ;
127+ let currZoom = canvas . zoom ( ) ;
128+ const newZoom = e . deltaY < 0 ? currZoom * zFactor : currZoom / zFactor ;
129+ const point = canvas . point ( e . clientX , e . clientY ) ; // centers zoom around mouse
130+ canvas . zoom ( getZoom ( newZoom ) , point ) ;
131+
132+ // check if we zoomed past any boundaries
133+ let vb = canvas . viewbox ( ) ;
134+ currZoom = canvas . zoom ( ) ; // update variables
135+ newY = vb . y ;
136+ const totalHeight = musicLayer . bbox ( ) . height ; // height of all pages
137+ const margin = CONFIG . autoMargin / currZoom ;
138+ const minY = - margin ; // highest possible height
139+ let maxY = Math . max ( minY , totalHeight + margin - vb . h ) ; // lowest possible height relative to the top of the viewbox
140+
141+ if ( vb . h >= totalHeight + ( margin * 2 ) || newY < minY ) { // zoomed out too far
142+ newY = minY ;
143+ } else if ( newY > maxY ) {
144+ newY = maxY ;
145+ }
146+ canvas . viewbox ( vb . x , newY , vb . w , vb . h ) ;
147+
148+ } else { // manual scrolling
149+ const vb = canvas . viewbox ( ) ;
150+ const zoom = canvas . zoom ( ) ; // use zoom so that you don't scroll by a ton when zoomed into a small area
151+
152+ // deltaY pos=down, negative=up
153+ const scrollAmount = e . deltaY / zoom ;
154+ let newY = vb . y + scrollAmount ;
155+
156+ // limit how far they can scroll vertically
157+ const totalHeight = musicLayer . bbox ( ) . height ; // height of all pages
158+ const margin = CONFIG . autoMargin / zoom ;
159+ const minY = - margin ; // highest possible height
160+ let maxY = Math . max ( minY , totalHeight + margin - vb . h ) ; // lowest possible height relative to the top of the viewbox
161+
162+ if ( newY < minY ) {
163+ newY = minY ;
164+ } else if ( newY > maxY ) {
165+ newY = maxY ;
166+ }
167+ canvas . viewbox ( vb . x , newY , vb . w , vb . h ) ; // min x coord, min y coord, width, height
168+ }
169+ } , { passive : false } ) ; // tells browser im preventing default behavior
115170
116171// Preview
117172document . getElementById ( "preview-btn" ) . addEventListener ( "click" , ( ) => {
0 commit comments