0

I am loading SVG images on to the mesh basic material of BoxBufferGeometry(cube) using SVGLoader. I want to trigger mouse events when user hovers/clicks on specific element of SVG which is loaded on the specific side of the cube.

I tried adding events into the .svg file before loading it but once it get loaded on the material it doesn\'t show any changes caused by the events.

Is there any other possible way to select the elements of loaded svg image and apply events on it?

For better understanding please refer http://plnkr.co/edit/YYN8aechHGTKXvPv6tOo?p=preview apart from this also tried to access the particular side using following code:

                raycaster.setFromCamera( mouse, camera );

                var intersects = raycaster.intersectObjects( scene.children );
                if ( intersects.length > 0 ) {
                    var index = Math.floor( intersects[0].faceIndex / 2 );
                    if ( INTERSECTED != intersects[ 0 ].object && (index == 4 || index == 5)) {
                        if ( INTERSECTED ) {
                            INTERSECTED.material[intersects[0].faceIndex].color.setHex( INTERSECTED.currentHex );
                        }


                        INTERSECTED = intersects[ 0 ].object;
                        INTERSECTED.currentHex = INTERSECTED.material[4].color.getHex();
                        INTERSECTED.material[index].color.setHex( 0xCACACA );
                        f = index;
                }
  • I think this link can help you https://stackoverflow.com/questions/12451855/how-to-add-event-listeners-to-objects-in-a-svg – gusaindpk Jul 07 '17 at 10:30
  • Also it is nice to add some sample code in the question. – gusaindpk Jul 07 '17 at 10:30
  • 3
    When you apply the SVG as a texture, it's no longer an SVG. If you want to intersect the SVG, you'd need to get the UV position of the click on the cube face (which maps to an x,y position on the SVG), and determine which SVG tag was clicked based on that position. – TheJim01 Jul 07 '17 at 13:39
  • @gusaindpk added sample link to the description. Hope this will make my question more clear – Mohit Patel Jul 07 '17 at 17:46
  • @MohitPatel created a plunker hope that will help. – gusaindpk Jul 09 '17 at 08:02
  • @TheJim01 Thanks for your solution. I tried implementing the solution provided by you in my example(provided in plunker link). But I am facing a problem while zooming in or zooming out the object. The UV co-ordinates of specific object(for e.g circle in my case) sales with some indefinite proportion and the mapping of co-ordinates doesn't remains the same. Is there anyway around to get this proportion of change/scale in that specific object? – Mohit Patel Jul 17 '17 at 19:35
  • Hmm, zoom shouldn't have an effect on the UV found by the ray. But that question is different from the topic of this post. I recommend creating a new post to ask your new question, and remember to include as much detail and code as you can. :) – TheJim01 Jul 17 '17 at 22:07
  • Hey @TheJim01 I have posted a new question. Can you please have a look at it. Link: https://stackoverflow.com/questions/45174879/finding-uv-coordinates-of-a-point-on-material-rendered-on-3d-cube-in-threejs . Thanks!! – Mohit Patel Jul 18 '17 at 18:53

1 Answers1

0

I have used threex.domevent.js to capture the mouseover event and created a plunker. I am finding the cube face which has the svg image. Links: detect mouse click / hover event on sides of cube in three js and https://github.com/jeromeetienne/threex.domevents.

  • Attach the dom event using *threex.domevent.js**

    domEvents = new THREEx.DomEvents(camera, renderer.domElement)

  • Listen to mouse over event and find the face you require.

            domEvents.addEventListener(mesh, 'mouseover', function(event) {
            var vector = new THREE.Vector3(
                (event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, );
            vector.unproject(camera);
            raycaster.set(camera.position, vector.sub(camera.position).normalize());
    
            var intersects = raycaster.intersectObject(mesh);
            if (intersects.length > 0) {
                var index = Math.floor(intersects[0].faceIndex / 2);
                if (index === 4) {
                    //index 4 is  cude face having the svg image,
                    //you can load a new svg or do required things here
                    console.log('##############');
                    mesh.material[4].map = new THREE.TextureLoader().load('sample2.svg');
                }
    
            }
        }, false)
    

    Plunker: http://plnkr.co/edit/QXwqN3X70ex3EZmlKhRf?p=preview Hope it helps.

gusaindpk
  • 1,243
  • 2
  • 13
  • 31
  • @MohitPatel did it help? – gusaindpk Jul 10 '17 at 10:14
  • thanks for the solution but I am already able to perform the same task using my code. I wanted to trigger events on the sub-geometries(circle, star,...) of the shape and change the color of those particular sub-geometry. – Mohit Patel Jul 10 '17 at 16:02
  • OK will look into it – gusaindpk Jul 11 '17 at 07:53
  • I think its not possible to attach events to svg itself as @TheJim01 has mentioned in comments. you also can check the link http://learningthreejs.com/blog/2013/04/30/closing-the-gap-between-html-and-webgl/.One possible way to enhance the code to find the particular circular area coordinates and check if mouse is present there and load other svg with the change sub-geometries – gusaindpk Jul 12 '17 at 13:57
  • Yeah the approach provided by @TheJim01 is the best so far I have received. Trying to implement the same in my code. – Mohit Patel Jul 12 '17 at 16:36
  • I will also have a look how to do it. – gusaindpk Jul 13 '17 at 07:42