0

I am able to get the intersects from my click event when I use the window object to acquire height and width, but getting the intersects position on a canvas that's dynamically sized is proving much harder. I'm not certain of the formula I would need to use to calculate the vector.x and vector.y values with a div that isn't always the same size.

The canvas is the size of a div that always has a width: height ratio of 4:3 and resizes to fit in the window and is always positioned in the center of the window.

If I resize the window to be 4:3 then the following code works perfectly:

mouse.x = (ecx/div_width) *2 -1;
mouse.y= -(ecy/div_height) *2 + 1;

when I resize the window, whichever dimension is larger than the size of the canvas has the incorrect value. I've linked an image to roughly describe how the problem presents itself

Image of horizontal dimension issue

I initially thought that the matches would be as simple as dividing the difference between the the sizes of the window and the canvas by

My question is, how would I acquire the correct values to pass to the vector object for it's x and y attributes? (using Vector3 and Raycaster)

here is the function I'm using to try and get the object(s) being clicked:

    function getClicked(event){
        event.preventDefault();
        var ecx = event.clientX;
        var ecy = event.clientY;

        //elem is the div containing the canvas
        //the canvas is not the same size as the window
        var elem_w = elem.innerWidth();
        var elem_h = elem.innerHeight();

        //most examples suggest using the window height and width
        //to get the position of the mouse in the scene.
        //since the scene isn't the same size as the window, that doesn't work
        var ww = window.innerWidth;
        var wh = window.innerHeight;

        mouse.x = (ecx/ww) *2 -1;
        mouse.y= -(ecy/wh) *2 + 1;
        var objlist = []
        rc.setFromCamera(mouse, camera);
        var intersects = rc.intersectObjects(scene.children, true);
        for (var i=0;i<names_to_spin.length;i++){
            var obj = intersects[i];
            objlist.push(obj);
        }
        //ideally, this should return a list of the objects under the cursor
        return objlist;
    }
moshy
  • 33
  • 5
  • Please be more specific and show some more relevant code; What is `ecx`. Are you using mouse event listeners and how? Are you using `div.clientWidth` ? etc. How is this related to three.js other than passing in x,y values to a Vector3 ? You do not need to use raycaster to obtain x,y position of mouse in a div. Maybe div.getBoundingClientRect() and mouse event pageX/clientX can help? – George Jun 30 '19 at 16:35
  • apologies. I'll add some more detail in a moment – moshy Jun 30 '19 at 16:53
  • firstly, there is no such thing as `element.innerWidth()`. I'm assuming that `getClicked` is being called for the div element. This will give event.clientX relative to the div x position. Instead of dividing by the viewport width (`window.innerWidth`) you can divide by the div width, which you can get with `element.getBoundingClientRect().width` This will give an x coordinate between 0 and 1, where 0 is the extreme left of the div, and 1 is the extreme right. Then you can transform these to -1 and +1 for three.js with the same method on your code, `x * 2 - 1`. – George Jun 30 '19 at 17:46
  • you must be mistaken, because I'm getting a value from elem.innerWidth(). If it didn't exist, I'd be getting undefined or something. elem is the first item in the list returned by using a jquery selector. i.e $("#elementname")[0]. Nevertheless, I'll try what you suggest. – moshy Jul 01 '19 at 13:26
  • Well you could say that about anything `element.njhbgvfcvgh()` exists in my library I'm using that I didn't tell you about, so you must be mistaken. You could at least put jquery as a tag to the question. – George Jul 01 '19 at 13:53
  • @George you're correct. I didn't mention jQuery at all, so for the purposes of my question, it didn't exist. innerWidth gives the same value as getBoundingClientRect().width, and it was something I had tried before, but the click events seem to be detected as far too close to the center of the div when I use that value. – moshy Jul 01 '19 at 17:42
  • ok. could you create a code snippet (not sample) in your question (there should be a button for this where you can put html, css, javascript, and can bring in three.js) so can understand the problem better? Also could you explain what you are trying to achieve because it could be XY problem. – George Jul 01 '19 at 21:16
  • I have figured out something that achieves what I need. I was busy making the snippet when I thought to just browse through the related but not entirely identical questions to mine to see what sort of detail was required for sufficient information for an answer and came across https://stackoverflow.com/questions/7956442/detect-clicked-object-in-three-js. The answer from Evertvdw gave me what I needed. (my canvas is not the full size of the window) – moshy Jul 03 '19 at 17:55

0 Answers0