Search code examples
javascriptaframe

How to return to previous value with Aframe component?


I wrote a component for Aframe to change the src and the scale of an image when the cursor is hover it. Then, when it exit, I want to return to default value.

So, I store the default src and the default scale values, then update it with setAttribute When the cursor go out, it return to default src, but not to default scale.

How to do that properly?

Here is my component :

AFRAME.registerComponent('change-hotspots-on-hover', {
    schema: {
        src: {default: '#hotspots'},
        scale: {type: 'vec3', default: {x: 1, y: 1, z: 1}},
    },

    init: function () {
        var data = this.data;
        var el = this.el;
        var defaultSrc = el.getAttribute('src');
        var defaultScale = el.getAttribute('scale');

        console.log("Init");

        el.addEventListener('mouseenter', function (){
            console.log("Enter");

            el.setAttribute('src', data.src);
            setTimeout(() => { 
                el.setAttribute('scale', data.scale);
            }, 1);
        });

        el.addEventListener('mouseleave', function (){
            console.log("Exit");

            el.setAttribute('src', defaultSrc);
            el.setAttribute('scale', defaultScale);
        });
    }
});

And my image:

<a-image position="-10 4 -10" scale="1 1 1" material="" src="#hotspot" 
change-hotspots-on-hover="src: #hotspot_hover; scale: 7 3 2;"></a-image>

Solution

  • Looks like getAttribute('scale') returns the scale reference, not a copy - meaning if you change the scale later on (hovering) - the object that defaultScale refers to is actually the one being changed.

    You can check that with a log in your mouseover listener:

    console.log(defaultScale) // here are the default scale values
    el.setAttribute('scale', data.scale);
    console.log(defaultScale) // here are the data.scale values
    

    You can work it around with, for example, stringifying the default scale, thus turning it into a simple "1 1 1"(provided its the default):

    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
      <script>
        AFRAME.registerComponent('change-hotspots-on-hover', {
          schema: {
            src: {default: '#source'},
            scale: {type: 'vec3', default: "1 1 1"},
          },
          init: function() {
            var data = this.data;
            var el = this.el;
              var defaultSrc = el.getAttribute('src');
              var defaultScale = AFRAME.utils.coordinates.stringify(el.getAttribute('scale'));
              el.addEventListener('mouseenter', e => {
                el.setAttribute('src', data.src);
                setTimeout(() => {
                  el.setAttribute('scale', data.scale);
                }, 1);
              });
    
              el.addEventListener('mouseleave', e => {
                el.setAttribute('src', defaultSrc);
                el.setAttribute('scale', defaultScale);
              });
          }
        });
      </script>
      <a-scene cursor="rayOrigin: mouse">
        <a-assets>
          <img id="image" src="https://i.imgur.com/wjobVTN.jpeg">
        </a-assets>
        <a-box position="0 0.5 -3" rotation="0 45 0" color="#4CC3D9" change-hotspots-on-hover="src: #image; scale: 2 2 2"></a-box>
      </a-scene>