Adjust distance between camera and object in Three.js drag controls

I've implemented Three.DragControls to allow for dragging an object within a scene. However, as the object is dragged, it appears to move further away from the camera.

My query is reminiscent of this unanswered post on Stack Overflow: Drag object locked at certain distance/radius from camera view

Is there a clever workaround for ensuring that _intersection.sub( _offset ) remains at a fixed distance from the camera in the center of the scene?

To address this issue, I have introduced a sphere into the scene:

    dragSphere = new THREE.Mesh(new THREE.SphereGeometry(200, 60, 40 ),new THREE.MeshBasicMaterial());
    dragSphere.name = "dragSphere";
    dragSphere.visible = false;
    dragSphere.scale.x = -1;
    scene.add(dragSphere);

The challenge lies somewhere within this code snippet:

  function onDocumentMouseMove( event ) {

    event.preventDefault();

    var offset = $("#container").offset();
    var rect = _domElement.getBoundingClientRect();
    _mouse.x = ( ( event.clientX - rect.left - (offset.left/2) ) / ( rect.width - rect.left ) ) * 2 - 1;
    _mouse.y = - ( ( event.clientY - rect.top ) / ( rect.bottom - rect.top) ) * 2 + 1;

    _raycaster.setFromCamera( _mouse, _camera );

    if ( _selected && scope.enabled ) {

        if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {

            if(_right){

                _deltaX = event.x - _startPoint.x;
                _deltaY = event.y - _startPoint.y;

                _selected.rotation.y += (_deltaX/50);
                _selected.rotation.x += (_deltaY/50);

                console.log(_selected.position);

                _startPoint.x = event.x;
                _startPoint.y = event.y;

                _lastMoveTimestamp = new Date();
            }
            else{
                _selected.position.copy( _intersection.sub( _offset ) );
                _selected.lookAt(camera.position);
            }

        }

        scope.dispatchEvent( { type: 'drag', object: _selected } );

        return;

    }

    _raycaster.setFromCamera(_mouse,_camera);

    var intersects = _raycaster.intersectObjects(_objects,true);


    if(intersects.length >0){
        var object =intersects[0].object;

        if(object.type ==="Mesh")
             if(object.parent)
                 if(object.parent.type=="Object3D")
                     object=object.parent;

         _plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), object.position );

         if(_hovered !==object){
             scope.dispatchEvent({type:'hoveron',object:object});

           DomElement.style.cursor='pointer';
             hovered=object;
          }
      }
     else{}

    if(_hovered!==null){
          scope.dispatchCvent({Type:'hoveroff'})

       DOM.element.Style.cursor ='auto';

   }
}

function onDocumentMouseDown(event){


 event.PreVENTDEFULT();


_right=event.which==3||event.button==2;


_rayCASTER.SEtfromCAMERA(_MOUSE,_caMera)



variables Intersection=_raycaster.INTERSECToBJECTS(_OBJECts,True);



If(intersection.LENGTH >                  o){
_selected=INTERSECTS[0].OBJECT;

if(_SELECTED.TYPE='mesh'&&_SeleCTEd.PAREnT.TYPE=='OBjeCtc'){
selected=_selected.paRingecj

if('R}=ACSTEk.RAYNTERsECTpLUsENp_

_intErrUtion.Sub_sELECTED.POSitio



_domElememStYLee.cuRSOR  
scopeDISpatCHEvent({Type:dRAgJoeceF:{Object Selected}}})

}
}
elsEscopReDecimalew.dISSARYSHN.(TYPE);ACY.mob\FIrextcMLEci.Gursr..AUToHovEngBLengthw.



_pSing.something drastically! ahahaha!

In this part where we're handling the drag operation:
Whendfdessedd.th.selectsion(Editor.js
Wstoth.v57),weath.Nentsecidahavso18
Ne sitkeAriLOS(atJiuATURupragden
_lt raopr).eESeloudkeshare(jndlockAbincen atmosphericende(Mneat
tr.Byaketo.pKeasthoatfthet draiconlruesohomeehapethesoonselectin gintacåtie@

Yortsotdescape.timent(pargesmeglo).

In conclusion, my objective is to ensure that when an object is dragged, its position remains aligned along the surface of the sphere, utilizing the intersection with the sphere itself for positioning.

Answer №1

This response may not cover everything, but it can definitely point you in the right direction. I encountered a similar issue when trying to make objects drag along a plane. I took matters into my own hands and created a customized version of the DragControls.js function to include support for passing a plane as a parameter (renaming it to DragControlsPlane.js), like this:

THREE.DragControlsPlane = function (_objects, _camera, _domElement, _plane)

This code snippet goes at the top of the original DragControls.js file. Then, deactivate the line that initializes the _plane variable:

//var _plane = new THREE.Plane();

Next, disable the section of code that adjusts the plane to align with the camera view (located about midway down):

//_plane.setFromNormalAndCoplanarPoint(_camera.getWorldDirection(_plane.normal), object.position);

Finally, towards the end, rename these lines to match your updated function name:

THREE.DragControlsPlane.prototype = Object.create(THREE.EventDispatcher.prototype);
THREE.DragControlsPlane.prototype.constructor = THREE.DragControlsPlane;

After completing these steps, integrate the new function into your scripts. The existing DragControls functionality should take care of the rest, although you may need to make further adjustments to accommodate a sphere. This approach is effective for working with a flat surface, though perhaps Mr. Doob will consider incorporating it as an official feature in the future. If you manage to adapt it for use with a sphere, feel free to share your experience! While this isn't a complete solution, I hope it assists someone facing a similar challenge. Your feedback is appreciated!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

experiencing challenges with jQuery event handlers in version 1.6, but not encountering the same issues in newer releases

Presently, I am using a version 1.6 of the Jquery library, which takes time to update. I am attempting to incorporate a Jquery event handler. I have a collection of divs that contain many buttons. These buttons are constantly being added dynamically, and ...

Tips for sending an email without using MAILTO in JavaScript or jQuery

Today is a great day for many, but unfortunately not for me. I've been struggling with this issue for over two weeks now and can't seem to find a solution anywhere on the internet. Stack Overflow always comes to my rescue when things get really t ...

Create a new JavaScript object by parsing JSON data

I am looking to achieve the following: var my_data = { x : 'orange', y : 2 } function object(data){ this.x = 'banana'; this.y = 3; this.z = 'default value'; } once I have executed: var new_instance = ob ...

What is the best way to include JavaScript in a web view within an Ionic Android application?

I'm in the process of incorporating a header bar into the web view for my app. Utilizing the cordova inAppBrowser plugin to achieve this, I tested using the following code: var win = window.open( URL, "_blank", 'location=yes' ); win.addEven ...

Getting the checked values from an AngularJS Material checkbox

<md-checkbox ng-repeat="program in ctrl.programs" ng-model="ctrl.programsSelected[program.id]"> {{program.name}} </md-checkbox> Checked Items: {{ctrl.programsSelected | json}} Current Output: Checked Items: [null,true,true,true,null,true, ...

When attempting to retrieve the value of my select element, I encounter difficulty due to a hidden field that only becomes visible when a certain option is selected

I have a dropdown menu with different options, including one labeled "other". When the user selects "other", a hidden text field appears for them to enter a custom value. This functionality works correctly. However, if the user selects any other option and ...

Adding a click functionality to a dynamically generated anchor tag in angular.js

Recently, I encountered a requirement that involved converting a part of plain text into a clickable link and then adding a click handler to it. The goal was to display some details in a popup when the link is clicked. In order to convert the normal strin ...

Modifying the input value after using the append() function

I have developed a custom HTML block template that allows me to duplicate the block upon clicking the Add button. This functionality is achieved through the use of append(). Is there a way to modify the value of the name='category[]' input field ...

Having trouble with the Mongoose FindOne function?

I'm encountering an issue with Mongoose FindOne returning a null response when I pass a dateString argument as a parameter. My setup involves using nodejs and mongoose. Below is the snippet of my code: var Service = app.models.service; controller.ne ...

There are various IDs in the output and I only require one specific ID

I have a JSON fetcher that is functioning properly. However, whenever I request an ID, it returns all the IDs present in the JSON data. Is there a way to retrieve only the latest ID? This is my first time working with JSON so I am still learning. $(docu ...

Updating divs automatically using Ajax without refreshing the page is not functioning as intended

I'm having trouble understanding why this isn't functioning properly. My goal is to have the data from load.php displayed in the div sample. However, if the code is updated (for example, when pulling information from a database), I want only the ...

Creating a dropdown navigation menu using jQuery

I have been experimenting with creating a customized Drop Down menu using ul li and Jquery, following this helpful Tutorial. Here is the sample HTML Code for testing: <div id="dd" class="wrapper-dropdown-3" tabindex="1"> <span>OS</span> ...

Restrictions on the number of characters based on the size of fonts in an html list sc

Recently, I attempted to implement a ticker message on my website using li scroller. However, it appears that there is a limitation on the number of characters that can be displayed in the ticker message when different font sizes are used. With a smaller ...

AngularJS long polling implementation for a mailbox application

Creating a mailbox using AngularJS involves setting up a service and controller to manage the mails. Service app.service('mails',['$http','$interval','$rootScope',function($http,$interval,$rootScope){ var upd ...

What is the process for accessing a particular field in the data returned by the collection.find method in Expressjs and mongodb

I've been attempting to access a specific field returned from the mongodb collection.find method without success. The console.log is not displaying anything. router.get('/buildings', function(req, res, next) { var db = req.db; var collectio ...

Saving an HTML5 canvas image to an MSSQL varbinary(max) field: A step-by-step guide

SAVING CANVAS IMAGE AS BASE64 STRING TO HIDDEN FIELD This script binds the base64 string to a hidden field on click event. save.addEventListener('click', function (event) { var dataUrl = canvas.toDataURL(); $('txtbx').val(dataUrl) ...

The debate between CSS Generic loading and Page Specific loading has been a

Seeking advice on optimizing CSS placements to improve website load times. I've learned about the concept of 'critical CSS' in the head section and other styles in the body using link tags. Is it advisable to load shared 'Generic' ...

PHP is not receiving any data from the Ajax request

I'm currently attempting to set up my first Ajax example on my MAMP server. Here's how my ajax.html file looks: <html> <head> <script src='ajax.js'></script> </head> <body onload = 'ajax()'> ...

Moving from the center to the bottom-right with a CSS transition

I have a specific requirement where I need the container to cover the entire page and shrink when clicked, with an animation. Currently, I am using CSS transition to animate the container shrinking towards the top: The container shrinks slowly to the sp ...

Prevent duplicate submissions by disabling the ASP.NET Forms button after it has been clicked

How can I disable an ASP.NET button after it's clicked to prevent double-clicking, and then enable it again after the submission is complete? I need some assistance with this. ...