11"use strict" ;
22
3- import { GL } from './lib/gl.js' ;
4- import { Vector } from './lib/vector.js' ;
3+ import { GL } from '.. /lib/gl.js' ;
4+ import { Vector } from '.. /lib/vector.js' ;
55
66/**
77 * Class representing the madelbrot animation.
@@ -68,21 +68,11 @@ export class Mandelbrot {
6868 event . preventDefault ( ) ;
6969 break ;
7070 case 'c' :
71- this . zoom_target = this . mouse_position ;
72- if ( this . zoom_speed > 0 ) {
73- this . zoom_speed += 1 ;
74- } else {
75- this . zoom_speed = 1 ;
76- }
71+ this . zoom ( true ) ;
7772 event . preventDefault ( ) ;
7873 break ;
7974 case 'v' :
80- this . zoom_target = this . mouse_position ;
81- if ( this . zoom_speed > 0 ) {
82- this . zoom_speed = - 1 ;
83- } else {
84- this . zoom_speed -= 1 ;
85- }
75+ this . zoom ( false ) ;
8676 event . preventDefault ( ) ;
8777 break ;
8878 default :
@@ -127,8 +117,17 @@ export class Mandelbrot {
127117 ) ;
128118
129119 // Don't move outside the quad.
130- if ( position . x < - 2 || position . x > 1 || position . y < - 1 || position . y > 1 ) {
131- return ;
120+ if ( position . x < - 2 ) {
121+ position . x = - 2 ;
122+ }
123+ if ( position . x > 1 ) {
124+ position . x = 1 ;
125+ }
126+ if ( position . y < - 1 ) {
127+ position . y = - 1 ;
128+ }
129+ if ( position . y > 1 ) {
130+ position . y = 1 ;
132131 }
133132
134133 this . gl . set_camera_position (
@@ -140,63 +139,93 @@ export class Mandelbrot {
140139
141140 // Add mouse wheel listener
142141 this . canvas . addEventListener ( 'wheel' , ( event ) => {
143- // No zooming while dragging.
144- if ( this . drag_active ) {
145- return ;
146- }
147-
148142 // Unproject mouse coords into scene coords.
149143 this . mouse_position = this . gl . unproject ( event . layerX , this . canvas . clientHeight - event . layerY , 0.5 ) ;
150-
151- this . zoom_target = this . gl . view_matrix . inverse ( ) . multiply_vector ( this . mouse_position ) ;
152-
153- // Don't move outside the quad.
154- if ( this . zoom_target . x < - 2 ) {
155- this . zoom_target . x = - 2 ;
156- }
157- if ( this . zoom_target . x > 1 ) {
158- this . zoom_target . x = 1 ;
159- }
160- if ( this . zoom_target . y < - 1 ) {
161- this . zoom_target . y = - 1 ;
162- }
163- if ( this . zoom_target . y > 1 ) {
164- this . zoom_target . y = 1 ;
165- }
166-
167- if ( event . deltaY > 0 ) {
168- if ( this . zoom_speed > 0 ) {
169- this . zoom_speed += 1 ;
170- } else {
171- this . zoom_speed = 1 ;
172- }
173- } else {
174- if ( this . zoom_speed > 0 ) {
175- this . zoom_speed = - 1 ;
176- } else {
177- this . zoom_speed -= 1 ;
178- }
179- }
144+ this . zoom ( event . deltaY > 0 ) ;
180145 } ) ;
181146
182- this . gl . add_render_hook ( ( frame_delta ) => this . zoom ( frame_delta ) ) ;
183- this . gl . add_render_hook ( ( frame_delta ) => this . cycle ( frame_delta ) ) ;
184- this . gl . add_render_hook ( ( ) => this . switch ( ) ) ;
147+ this . gl . add_render_hook ( ( frame_delta ) => this . zoom_hook ( frame_delta ) ) ;
148+ this . gl . add_render_hook ( ( frame_delta ) => this . cycle_hook ( frame_delta ) ) ;
149+ this . gl . add_render_hook ( ( ) => this . switch_hook ( ) ) ;
185150 this . gl . add_render_hook ( ( ) => this . drag_active ) ;
186151
187152 this . gl . event_loop ( ) ;
188153 }
189154
155+ /**
156+ * Handle a zoom event.
157+ *
158+ * @param {float } x
159+ * @param {float } y
160+ * @param {boolean } out True if zooming out.
161+ */
162+ zoom ( out ) {
163+ // No zooming while dragging.
164+ if ( this . drag_active ) {
165+ return ;
166+ }
167+
168+ this . zoom_target = this . gl . view_matrix . inverse ( ) . multiply_vector ( this . mouse_position ) ;
169+
170+ // Don't move outside the quad.
171+ if ( this . zoom_target . x < - 2 ) {
172+ this . zoom_target . x = - 2 ;
173+ }
174+ if ( this . zoom_target . x > 1 ) {
175+ this . zoom_target . x = 1 ;
176+ }
177+ if ( this . zoom_target . y < - 1 ) {
178+ this . zoom_target . y = - 1 ;
179+ }
180+ if ( this . zoom_target . y > 1 ) {
181+ this . zoom_target . y = 1 ;
182+ }
183+
184+ if ( out ) {
185+ if ( this . zoom_speed > 0 ) {
186+ this . zoom_speed += 1 ;
187+ } else {
188+ this . zoom_speed = 1 ;
189+ }
190+ } else {
191+ if ( this . zoom_speed > 0 ) {
192+ this . zoom_speed = - 1 ;
193+ } else {
194+ this . zoom_speed -= 1 ;
195+ }
196+ }
197+ }
198+
190199 /**
191200 * Perform zoom calculations.
192201 *
193202 * @param {integer } frame_delta
194203 */
195- zoom ( frame_delta ) {
204+ zoom_hook ( frame_delta ) {
196205 if ( this . zoom_speed === 0 ) {
197206 return false ;
198207 }
199208
209+ // Scale the projection matrix for the zoom effect.
210+ if ( ( this . zoom_level < 30000 && this . zoom_speed < 0 ) || ( this . zoom_level > 1 && this . zoom_speed > 0 ) ) {
211+ const scale_factor = 1 - ( frame_delta * this . zoom_speed / 1000 ) ;
212+ this . gl . projection_matrix = this . gl . projection_matrix . scale (
213+ scale_factor ,
214+ scale_factor ,
215+ 1
216+ ) ;
217+
218+ this . zoom_level *= scale_factor ;
219+
220+ // Reduce the zoom speed over time.
221+ this . zoom_speed *= 1 - ( frame_delta / 1000 ) ;
222+ if ( Math . abs ( this . zoom_speed ) < 0.005 ) {
223+ this . zoom_speed = 0 ;
224+ }
225+ } else {
226+ this . zoom_speed = 0 ;
227+ }
228+
200229 // Find the vector from the current camera position to the zoom target.
201230 // Scale by the frame_delta so that the movement would occur in 1 / zoom_speed seconds.
202231 const movement_vector = new Vector (
@@ -207,29 +236,18 @@ export class Mandelbrot {
207236 ) . multiply ( frame_delta * Math . abs ( this . zoom_speed ) / 1000 ) ;
208237
209238 // Update the camera position along the movement vector.
210- this . gl . translate_camera_position (
211- movement_vector . x ,
212- movement_vector . y ,
213- 0 ,
214- ) ;
215-
216- // Scale the projection matrix for the zoom effect.
217- if ( ( this . zoom_level < 30000 && this . zoom_speed < 0 )
218- || ( this . zoom_level > 1 && this . zoom_speed > 0 ) ) {
219- const scale_factor = 1 + ( frame_delta * - this . zoom_speed / 1000 ) ;
220- this . gl . projection_matrix = this . gl . projection_matrix . scale (
221- scale_factor ,
222- scale_factor ,
223- 1
239+ if ( this . zoom_speed < 0 ) {
240+ this . gl . translate_camera_position (
241+ movement_vector . x ,
242+ movement_vector . y ,
243+ 0
244+ ) ;
245+ } else {
246+ this . gl . translate_camera_position (
247+ - movement_vector . x ,
248+ - movement_vector . y ,
249+ 0
224250 ) ;
225-
226- this . zoom_level *= scale_factor ;
227- }
228-
229- // Reduce the zoom speed over time.
230- this . zoom_speed *= 1 - ( frame_delta / 1000 ) ;
231- if ( Math . abs ( this . zoom_speed ) < 0.005 ) {
232- this . zoom_speed = 0 ;
233251 }
234252
235253 return true ;
@@ -240,7 +258,7 @@ export class Mandelbrot {
240258 *
241259 * @param {integer } frame_delta
242260 */
243- cycle ( frame_delta ) {
261+ cycle_hook ( frame_delta ) {
244262 let speed = 200 ;
245263 if ( this . extreme_mode ) {
246264 speed = 10 ;
@@ -258,7 +276,7 @@ export class Mandelbrot {
258276 /**
259277 * Switch the rendered set.
260278 */
261- switch ( ) {
279+ switch_hook ( ) {
262280 if ( this . current_julia === this . desired_julia ) {
263281 return false ;
264282 }
0 commit comments