Search code examples
aframe

Resizing aframe object in the browser


I am adding some shapes (circular or rectangular) in a 360 video using A-Frame, I can drag the shape to change its position in the video frame, but I need also to be able to resize this shapes to cover a precise object in the video, let's say I want to cover a painting in a video frame with a rectangle, so I want to be able to resize the shape to cover the painting correctly while I am in the web browser mode. I found this post that is asking about rotating the object, and he is saying that he succeeded to do the resize without explaining how exactly he did it. Anyone knows how to do it ?


Solution

  • You can rescale elements either with the a-frame API:

    element.setAttribute("scale", "1 1 1") // replace 1 1 1 with new values
    

    or by accessing the underlying THREE.js API:

    element.object3D.scale.multiplyScalar(scaleFactor);
    

    You can easily create a component, which would rescale a "selected" element. Run the snipper, press the mouse over an element and use the scrollwheel:

    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script>
      // register component
      AFRAME.registerComponent("foo", {
        // init callback
        init: function() {
          // react to press / release events to know if the element is selected
          this.el.addEventListener("mousedown", e => {
            this.selected = true;
          })
          this.el.addEventListener("mouseup", e => {
            this.selected = false;
          })
          // if this is selected, scale up/down when the mouse is scrolled
          this.el.sceneEl.addEventListener("mousewheel", evt => {
            if (!this.selected) return; // ignore when not selected
            const scale_factor = evt.deltaY < 0 ? 1.1 : 0.9 // scale up or down depending on the scroll direction
            this.el.object3D.scale.multiplyScalar(scale_factor);
            evt.preventDefault();
          })
        }
      })
    
    </script>
    <a-scene cursor="rayOrigin: mouse" raycaster="objects: .interactable">
      <a-box class="interactable" position="-1 0.5 -3" rotation="0 45 0" color="#4CC3D9" foo></a-box>
      <a-sphere class="interactable" position="0 1.25 -5" radius="1.25" color="#EF2D5E" foo></a-sphere>
      <a-cylinder class="interactable" position="1 0.75 -3" radius="0.5" height="1.5" color="#FFC65D" foo></a-cylinder>
      <a-plane position="0 0 -4" rotation="-90 0 0" width="4" height="4" color="#7BC8A4"></a-plane>
    </a-scene>

    If you're looking for a ready solution, I'd recommend checking out the transform controls


    If you want to resize the plane by moving the vertices to make a custom polygon, You can directly change the planes vertices position:

    <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
    <script>
      AFRAME.registerComponent("foo", {
        init: function() {
          // grab the threejs mesh
          const mesh = this.el.getObject3D("mesh");
          // grab the vertices array
          // the array is looking like this: x1, y1, z1, x2, y2, z2, ... xn, yn, zn
          const vertices = mesh.geometry.attributes.position.array;
                
          // manipulate the vertices in fixed intervals 
          setInterval(evt => {
            vertices[0] = vertices[0] === -0.5 ? -1 : -0.5; // primitive x1 toggle
            mesh.geometry.attributes.position.needsUpdate = true; // toggle update flag
          }, 500);
          setInterval(evt => {
            vertices[1] = vertices[1] === 0.5 ? 1 : 0.5; // primitive y1 toggle
            mesh.geometry.attributes.position.needsUpdate = true; // toggle update flag
          }, 250);
        }
      })
    </script>
    <a-scene>
      <a-plane position="0 1.6 -2" color="green" foo></a-plane>
    </a-scene>

    Here is an example of moving the vertex around