rexrainbow / phaser3-rex-notes

Notes of phaser3 engine
MIT License
1.18k stars 259 forks source link

MouseWheelZoom: Multiply zoomStep by camera.zoom for a uniform zoom effect at all zoom levels. #453

Closed PatBG closed 1 week ago

rexrainbow commented 2 weeks ago

In official camera controller, it assigns new zoom value by cam.zoom += this._zoom (ref) For zoom-in (camera.zoom >= 1), it works as expect. The zoom in levels are 1.01, 1.02, 1.03, ... The issue might be zoom-out (camera.zoom < 1), the zoom out levels will be (assume that zoomStep is 0.01) 0.09, 0.08, 0.07, 0.06, ... What kind of zoom out levels in your requirement?

PatBG commented 1 week ago

The official Phaser camera controller is a lower level API, the caller controls the step value at every tick. It is how they use an uniform zoom effect in this official example: https://labs.phaser.io/view.html?src=src/tilemap\mouse%20wheel%20zoom.js (step is multiplied by zoom level on line 41)

The Rex Plugin is at a higher level and as far as I know the caller can't adjust the step at each tick, so implementing a uniform zoom effect internally is probably the better way. It allows to zoom from 0.2 (far) to 10 (very close) in a convenient way.

If both usages are needed, adding a boolean like "uniformStep" may solve the problem.

rexrainbow commented 1 week ago

Can you describe sequence of zoom levels ? Therefore I can get the requirement clearly.

PatBG commented 1 week ago

First you choose a step (let's take 0.1)

If Zooming in: Zoom = 1 then step = 0.1 x 1 = 0.1 Zoom = 1.1 then step = 0.1 x 1.1 = 0.11 Zoom = 1.21 then step = 0.1 x 1.21 = 0.121 :

If Zooming out: Zoom = 1 then step = 0.1 x 1 = 0.1 Zoom = 0.9 then step = 0.1 x 0.9 = 0.09 Zoom = 0.81 then step = 0.1 x 0.81 = 0.081 :

Trying both the Rex example and the Phaser example with a large range usually make sense (from zoom 0.2 to 5). The Rex example is too speed when far and too slow when close, while the Phaser example give a "natural" zoom feeling with its uniform effect.

rexrainbow commented 1 week ago

After wheeling- up 2 times, zoom value is 1.21.

Then wheeling-down 2 times, zoom value becomes 0.9801

zoom value won't back to initial value (1) in this case.

Will this cause any problem?

PatBG commented 1 week ago

Interesting remark, and the delta time is also taken in account by MouseWheelZoom.onZoomTick(time, delta), so I'm not sure if 2 ticks in, and 2 ticks out already come back to the initial value. I don't think it's a problem (based on my test with a mouse and various step values), But if you have a doubt, maybe a boolean to enable/disable the multiplication by current zoom level is the better solution. I think most end users expect a uniform zoom effect like in the Phaser example. https://labs.phaser.io/view.html?src=src/tilemap%5Cmouse%20wheel%20zoom.js

rexrainbow commented 1 week ago

Rewrite zoom updating formula. Now zoom value will update by zoomLevel parameter. Wheeling up/down will increase or decrease zoomLevel.

Please see this demo, current camera zoom will dump at console.

The zoom-level mapping are list below, with zoomStep = 0.1

PatBG commented 1 week ago

Please see this demo, current camera zoom will dump at console.

It seems perfect 👍 The Pull Request can be closed.