Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add middle-click + drag listener for ZOOM on EnvironmentControls #788

Open
jo-chemla opened this issue Oct 7, 2024 · 5 comments
Open

Add middle-click + drag listener for ZOOM on EnvironmentControls #788

jo-chemla opened this issue Oct 7, 2024 · 5 comments
Labels
enhancement New feature or request

Comments

@jo-chemla
Copy link
Contributor

jo-chemla commented Oct 7, 2024

Is your feature request related to a problem? Please describe.

The EnvironmentControls parses left and right clicks + mouse-wheel events, (Quick note, the SHIFT + LEFT_CLICK did not trigger rotate during my tests). It could be nice if these controls could also parse Middle click for zoom - the awy it is done in googleMapsAerial within OrbitControls

Describe the solution you'd like

Web/API/Pointer_events suggest adding to PointerTracker.js

isMiddleClicked() {
  return Boolean( this.buttons & 4 );
}

And then this could probably resort to something like the following addition to EnvironmentControls.js - pointerdownCallback

else if ( pointerTracker.isMiddleClicked() ) {

	// if the clicked point is coming from below the plane then don't perform the drag
	this.setState( ZOOM );
	this.zoomDirectionSet = false;
	this._updateZoomDirection();

        // The below could be shared on top if the `if (hit)` block
        this.pivotPoint.copy( hit.point );
        this.pivotMesh.position.copy( hit.point );
        this.pivotMesh.updateMatrixWorld();
        this.scene.add( this.pivotMesh );
}

Finally,

  • or replicate somehow the wheelCallback and replace how it handles event cursor e.deltaY motion with movementY, and apply to zoomDelta, but build this into pointermoveCallback:
	const pointermoveCallback = e => {
	// ...
	// Add mouse click handle in pointerMove
	if ( this.state === ZOOM ) {

		console.log( 'MOUSE MIDDLE CLICKED: ', e, e.deltaMode, e.deltaY );
		const delta = e.movementY;
		// use LOG to scale the scroll delta and hopefully normalize them across platforms
		const deltaSign = Math.sign( delta );
		const normalizedDelta = Math.log( Math.abs( delta ) + 1 );
		this.zoomDelta -= 3 * deltaSign * normalizedDelta * 1;
		// this.needsUpdate = true;

	}

Describe alternatives you've considered

Use another controls, like Pivot controls instead of EnvironmentControls to handle middle-mouse click

@jo-chemla jo-chemla added the enhancement New feature or request label Oct 7, 2024
@gkjohnson
Copy link
Contributor

I'm open to adding the feature if you like to make a PR!

@jo-chemla
Copy link
Contributor Author

Just did a try, seems like this is working!
#789

@jo-chemla
Copy link
Contributor Author

Edit: seems that terrain avoidance makes it not exactly work like mouse-wheel - where the cursor stays at the same spot on the mesh during zooming-in/out, while it slides with the middle-click zoom. Maybe an update that should be disabled or enabled that I am missing - something like zoomDirection or pivot?

@gkjohnson
Copy link
Contributor

seems that terrain avoidance makes it not exactly work like mouse-wheel - where the cursor stays at the same spot on the mesh during zooming-in/out, while it slides with the middle-click zoom. Maybe an update that should be disabled or enabled that I am missing - something like zoomDirection or pivot?

I'll have to try it when I'm on a computer with a mouse but I wouldn't expect this to keep the terrain in the same spot under the mouse since the cursor is being dragged. It should zoom into the point that was originally clicked.

@jo-chemla
Copy link
Contributor Author

Yes I agree it should zoom on the spot originally clicked, but this spot seem to slide a little because of the terrain constraint. It's not very noticeable, but still a bit weird.

It might be trying to zoom always to where the cursor is, which when middleclicking + sliding vertically, moves towards the top or bottom of the screen.
Conditioning _updatePosition and _updateRotation on controls update only to when state is ROTATE or DRAG also seem to be reducing the issue:

if ( state === ZOOM && zoomDelta !== 0 ) {
  this._updateZoom();
  this.rotationInertia.set( 0, 0 );
  this.dragInertia.set( 0, 0, 0 );
}
else if ( state === ROTATE || state === DRAG ) {
  this._updatePosition( deltaTime );
  this._updateRotation( deltaTime );
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants