title: Aframe texture control over individual entities
body: <p>I was wondering how to set a texture on an entity but only that entity and then be able to place more by selecting texture buttons I can't get my code to work properly but I wanted to make it function a little more like minecraft than the original minecraft aframe demo did. If anybody can get my code to work it would be a real help. All the script that is commented out was because I wanted to find a better way to do whatever I was trying. Essentially I want to pick a texture in the menu at the bottom and then use that texture on my entities.</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
    &lt;head&gt;
      &lt;script src="https://aframe.io/releases/0.9.0/aframe.min.js"&gt;&lt;/script&gt;
      &lt;script src="https://unpkg.com/aframe-controller-cursor-component@0.2.x/dist/aframe-controller-cursor-component.min.js"&gt;&lt;/script&gt;
  &lt;script&gt;
      /**
   * Snap entity to the closest interval specified by `snap`.
   * Offset entity by `offset`.
   */
  AFRAME.registerComponent('snap', {
    dependencies: ['position'],
  
    schema: {
      offset: {type: 'vec3'},
      snap: {type: 'vec3'}
    },
  
    init: function () {
      this.originalPos = this.el.getAttribute('position');
    },
  
    update: function () {
      const data = this.data;
  
      const pos = AFRAME.utils.clone(this.originalPos);
      pos.x = Math.floor(pos.x / data.snap.x) * data.snap.x + data.offset.x;
      pos.y = Math.floor(pos.y / data.snap.y) * data.snap.y + data.offset.y;
      pos.z = Math.floor(pos.z / data.snap.z) * data.snap.z + data.offset.z;
  
      this.el.setAttribute('position', pos);
    }
  });
      &lt;/script&gt;
  &lt;script&gt;/**
   * Spawn entity at the intersection point on click, given the properties passed.
   *
   * `&lt;a-entity intersection-spawn="mixin: box; material.color: red"&gt;` will spawn
   * `&lt;a-entity mixin="box" material="color: red"&gt;` at intersection point.
   */
  AFRAME.registerComponent('intersection-spawn', {
    schema: {
      default: '',
      parse: AFRAME.utils.styleParser.parse
    },
  
    init: function () {
      const data = this.data;
      const el = this.el;
  
      el.addEventListener(data.event, evt =&gt; {
        // Create element. (element create     below v
        const spawnEl = document.createElement('a-entity');
  
        // Snap intersection point to grid and offset from center. (position)
        spawnEl.setAttribute('position', evt.detail.intersection.point);
  
        // Set components and properties.
        Object.keys(data).forEach(name =&gt; {
          if (name === 'event') { return; }
          AFRAME.utils.entity.setComponentProperty(spawnEl, name, data[name]);
        });
  
        // Append to scene.
        el.sceneEl.appendChild(spawnEl);
      });
    }
  });&lt;/script&gt;
      &lt;script&gt;
       function startTimer(duration, display) {
      var timer = duration, minutes, seconds;
      setInterval(function () {
          minutes = parseInt(timer / 60, 10)
          seconds = parseInt(timer % 60, 10);
  
          minutes = minutes &lt; 10 ? "0" + minutes : minutes;
          seconds = seconds &lt; 10 ? "0" + seconds : seconds;
  
          display.textContent = minutes + ":" + seconds;
  
          if (--timer &lt; 0) {
              timer = duration;
          }
      }, 1000);
  }
  
  window.onload = function () {
      var fiveMinutes = 60 * 10,
          display = document.querySelector('#time');
      startTimer(fiveMinutes, display);
  };
      &lt;/script&gt;
      &lt;style&gt;
        .transparentBox {
          width: 200px;
          background-color: #6969697a;
          margin-right: 600px;
          border-radius: 10px;
          border: 2px solid black;
        }
        
        html {
         width: 800px;
         height: 600px;
         cursor: crosshair;
        }
        
        a-scene {
          cursor: crosshair;
          width: 800px;
          height: 600px;
        }
       
        body {
          cursor: crosshair;
          width: 800px;
          height: 600px;
        }
   
        .Container {
          margin-right: 8px;
        }
      &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
      
      
      &lt;!-- aframe overlay --&gt;
      
      &lt;div class="Container" style="position:relative;"&gt;
     &lt;!-- &lt;a-scene id="updateMe" inspector="https://cdn.jsdelivr.net/gh/aframevr/aframe-inspector@master/dist/aframe-inspector.min.js"&gt; --&gt;
        &lt;a-scene embedded&gt;
        &lt;a-assets&gt;
        &lt;img id="groundTexture" src="floor.jpg"&gt;
        &lt;img id="skyTexture" src="https://cdn.aframe.io/a-painter/images/sky.jpg"&gt;
        
          &lt;a-mixin id="voxel1"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Box.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          &lt;a-mixin id="voxel2"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Brick.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          &lt;a-mixin id="voxel3"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Steel.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          &lt;a-mixin id="voxel4"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Pcb.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          &lt;a-mixin id="voxel5"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Grass.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          &lt;a-mixin id="voxel6"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Ice.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          &lt;a-mixin id="voxel7"
           geometry="primitive: box; height: 0.6; width: 0.6; depth: 0.6"
           material="id: theImage; src: Fabric.jpg; color: #696969; roughness: 1; metalness: 0"     
           snap="offset: 0.4 0.4 0.4; snap: 0.6 0.6 0.6"
        &gt;&lt;/a-mixin&gt;
          
      &lt;/a-assets&gt;
     &lt;a-obj-model rotation="-90 45 0" position="0 2 0" src="tinker.obj" mtl="obj.mtl"&gt;&lt;/a-obj-model&gt;
      &lt;a-cylinder id="ground" src="#groundTexture" radius="30" height="0.1"&gt;&lt;/a-cylinder&gt;
  
      &lt;a-sky id="background" src="#skyTexture" theta-length="90" radius="30"&gt;&lt;/a-sky&gt;
  
      &lt;!-- Camera. --&gt;
      &lt;a-camera fly="true" position="0 0.75 15" wasd-controls="acceleration: 20" wasd-controls-enabled="true" fov="90" reverse-mouse-drag="false"&gt;
        &lt;a-cursor id="Save1" intersection-spawn="event: click; mixin: voxel1"&gt;&lt;/a-cursor&gt;
        &lt;a-cursor id="Save2" intersection-spawn="event: click; mixin: voxel2"&gt;&lt;/a-cursor&gt;
        &lt;a-cursor id="Save3" intersection-spawn="event: click; mixin: voxel3"&gt;&lt;/a-cursor&gt;
        &lt;a-cursor id="Save4" intersection-spawn="event: click; mixin: voxel4"&gt;&lt;/a-cursor&gt;
        &lt;a-cursor id="Save5" intersection-spawn="event: click; mixin: voxel5"&gt;&lt;/a-cursor&gt;
        &lt;a-cursor id="Save6" intersection-spawn="event: click; mixin: voxel6"&gt;&lt;/a-cursor&gt;
        &lt;a-cursor id="Save7" intersection-spawn="event: click; mixin: voxel7"&gt;&lt;/a-cursor&gt;
      &lt;/a-camera&gt;
        &lt;/a-scene&gt;
        &lt;!-- /aframe overlay --&gt;
        &lt;center&gt;
        &lt;div style="position:absolute; margin-right:8px; top:0px; width:205px; height:180px; left:0px; z-index:1000;"&gt;
          &lt;div class="transparentBox"&gt;
          &lt;b&gt;&lt;h1 color="#FFFFFF" id="time"&gt;10:00&lt;/h1&gt;&lt;/b&gt;
            &lt;p style="font-size:20px;font-family:monospace;margin-top:-20px;"&gt;Camera Height:&lt;/p&gt;
            &lt;h1&gt;&lt;b&gt;&lt;a&gt;&amp;uarr;&lt;/a&gt;~~&lt;a&gt;&amp;darr;&lt;/a&gt;&lt;/b&gt;&lt;/h1&gt;
            &lt;iframe src="250-milliseconds-of-silence.mp3" allow="autoplay" id="audio" style="display:none"&gt;&lt;/iframe&gt;
            &lt;audio autoplay loop id="track"&gt;
    &lt;source src="Magic_Scout_-_Cottages.mp3" type="audio/mpeg"&gt;
  Your browser does not support the audio element.
  &lt;/audio&gt;&lt;center&gt;
            &lt;button class="button" id="myBtn"&gt;Menu&lt;/button&gt;
            &lt;/center&gt;
          &lt;/div&gt;
          &lt;div id="myModal" class="modal"&gt;
          &lt;center&gt;
    &lt;!-- Modal content --&gt;
    &lt;div class="modal-content"&gt;
      &lt;span id="clickMe" type="button" value="clickme" onclick="startTimer()" class="close"&gt;&amp;times;&lt;/span&gt;
      &lt;center&gt;
        &lt;p class="beginMenuText"&gt;&lt;b&gt;Welcome to SandBox!&lt;/b&gt;&lt;/p&gt;
        &lt;p class="Text"&gt;WASD to move, Space place blocks.&lt;/p&gt;
        &lt;p class="Text2"&gt;You have 10 min. before the game restarts and all is lost.&lt;/p&gt;
        &lt;p class="Text2point5"&gt;Have fun...&lt;/p&gt;
      &lt;/center&gt;
      &lt;p class="Text3"&gt;&lt;b&gt;&lt;u&gt;Credits:&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
      &lt;p class="Text4"&gt;All music by &lt;b&gt;Kevin MacLeod&lt;/b&gt;&lt;/p&gt;
      &lt;p class="Text5"&gt;&lt;b&gt;Aframe&lt;/b&gt; by the Aframe authors.&lt;/p&gt;
      &lt;p class="Text6"&gt;(Licenced under the &lt;b&gt;MIT Licence&lt;/b&gt;)&lt;/p&gt;
      &lt;p class="Text7"&gt;Inspiration from other &lt;b&gt;WebVR Projects.&lt;/b&gt;&lt;/p&gt;
      &lt;p class="Text8"&gt;Voxel textures can be changed using the menu at the &lt;b&gt;bottom&lt;/b&gt;.&lt;/p&gt;
      &lt;p class="Text9"&gt;&lt;b&gt;Enjoy!&lt;/b&gt;&lt;/p&gt;
      &lt;div class="unmute" onclick="document.getElementById('track').muted = !document.getElementById('track').muted;$(this).toggleClass('mute')"&gt;&lt;/div&gt;
    &lt;/div&gt;
            &lt;/center&gt;
          &lt;/div&gt;
            &lt;div class="textureMenu"&gt;
              &lt;div class="textureBox" id="Kill1" &gt;&lt;img src="Box.jpg" height="45" width="45"&gt;&lt;/div&gt;
               &lt;p class="spacer"&gt;~&lt;/p&gt;
              &lt;div class="textureBox" id="Kill2"&gt;&lt;img src="Brick.jpg" height="45" width="45"&gt;&lt;/div&gt;
               &lt;p class="spacer"&gt;~&lt;/p&gt;
              &lt;div class="textureBox" id="Kill3"&gt;&lt;img src="Steel.jpg" height="45" width="45"&gt;&lt;/div&gt;
               &lt;p class="spacer"&gt;~&lt;/p&gt;
              &lt;div class="textureBox" id="Kill4"&gt;&lt;img src="Pcb.jpg" height="45" width="45"&gt;&lt;/div&gt;
               &lt;p class="spacer"&gt;~&lt;/p&gt;
              &lt;div class="textureBox" id="Kill5"&gt;&lt;img src="Grass.jpg" height="45" width="45"&gt;&lt;/div&gt;
               &lt;p class="spacer"&gt;~&lt;/p&gt;
              &lt;div class="textureBox" id="Kill6"&gt;&lt;img src="Ice.jpg" height="45" width="45"&gt;&lt;/div&gt;
               &lt;p class="spacer"&gt;~&lt;/p&gt;
              &lt;div class="textureBox" id="Kill7"&gt;&lt;img src="Fabric.jpg" height="45" width="45"&gt;&lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
          &lt;/center&gt;
        
      &lt;/div&gt;
      
    &lt;/body&gt;                  
    &lt;head&gt;
     &lt;!--&lt;script&gt;
  document.getElementById('Kill1').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save1');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel1');
    }
  };
  &lt;/script&gt;
      &lt;script&gt;
  document.getElementById('Kill2').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save2');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel2');
    }
  };
  &lt;/script&gt;
      &lt;script&gt;
  document.getElementById('Kill3').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save3');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel3');
    }
  };
  &lt;/script&gt;
      &lt;script&gt;
  document.getElementById('Kill4').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save4');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel4');
    }
  };
  &lt;/script&gt;
      &lt;script&gt;
  document.getElementById('Kill5').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save5');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel5');
    }
  };
  &lt;/script&gt;
      &lt;script&gt;
  document.getElementById('Kill6').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save6');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel6');
    }
  };
  &lt;/script&gt;
      &lt;script&gt;
  document.getElementById('Kill7').addEventListener('click', function () {
    var mixinEl = document.getElementById('Save7');
    if (mixinEl.getAttribute('mixin') === 'voxel') {
      mixinEl.setAttribute('mixin',: 'voxel7');
    }
  };
  &lt;/script&gt;--&gt;
  
      &lt;style&gt;
        .spacer {
          float: left;
        }
        .textureBox {
          width: 47px;
          height: 47px;
          border: 2px solid black;
          float: left;
        }
        .textureMenu {
          height: 50px;
          width: 412px;
          padding: 10px;
          background-color: #6969697a;
          border: 2px solid black;
          border-radius: 10px;
          display:inline-block;
          position: absolute;
          left: 200%;
          top: 313%;
          transform: translate(-50%, -50%);
        }
        .Text9 {
          font-size: 25px;
          font-family: monospace;
          margin-top: -13px;
          border-bottom: 2px dashed black;
        }
        .Text8 {
          font-size: 25px;
          font-family: monospace;
          margin-top: -13px;
        }
        .Text7 {
          font-size: 18px;
          font-family: monospace;
          margin-top: -13px;
          border-bottom: 2px dashed black;
          
        }
        .Text6 {
          font-size: 10px;
          font-family: monospace;
          margin-top: -20px;
          line-height: 1.3;
        }
        .Text5 {
          font-size: 15px;
          font-family: monospace;
          margin-top: -22px;
          line-height: 1.3;
        }
        .Text4 {
          font-size: 15px;
          font-family: monospace;
          margin-top: -27px;
          line-height: 1.3;
        }
        .Text3 {
          font-size: 20px;
          font-family: monospace;
          margin-top: -30px;
          line-height: 1.3;
        }
        .Text2point5 {
          font-size: 25px;
          font-family: monospace;
          margin-top: -30px;
          line-height: 1;
        }
        .Text2 {
          font-size: 25px;
          font-family: monospace;
          margin-top: -30px;
          line-height: 1;
        }
          .Text {
          font-size: 25px;
          font-family: monospace;
          margin-top: -40px;
        }
        .beginMenuText {
          font-size: 45px;
          font-family: monospace;
          margin-top: auto;
          border-bottom: 3px dashed black;
        }
        
        .unmute {
    background-image: url(http://franriavilla.in/images/unmute.png);
    background-size: cover;
    width: 35px;
    height: 30px;
    cursor: pointer;
  }
  
  .mute {
    background-image: url(http://franriavilla.in/images/mute.png);
  }
        
        /* The Modal (background) */
  .modal {
    display: initial; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 1; /* Sit on top */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 600px; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0,0,0); /* Fallback color */
    background-color: rgba(0,0,0,0.65); /* Black w/ opacity */
    width: 800px;
    margin-right: 8px;
    margin-top: 8px;
  }
  
  /* Modal Content/Box */
  .modal-content {
    background-color: #94989e;
    margin-top: 8px; /* 15% from the top and centered */
    padding: 20px;
    border: 1px solid #888;
    width: 500px; /* Could be more or less, depending on screen size */
    border-radius: 20px;
    z-index: 20000;
  }
  
  /* The Close Button */
  .close {
    color: #FFF;
    float: right;
    margin-top: -15px;
    font-size: 35px;
    font-weight: bold;
  }
  
  .close:hover,
  .close:focus {
    color: black;
    text-decoration: none;
    cursor: pointer;
  }
      &lt;/style&gt;
      &lt;script&gt;
        // Get the modal
  var modal = document.getElementById('myModal');
  
  // Get the button that opens the modal
  var btn = document.getElementById("myBtn");
  
  // Get the &lt;span&gt; element that closes the modal
  var span = document.getElementsByClassName("close")[0];
  
  // When the user clicks on the button, open the modal 
  btn.onclick = function() {
    modal.style.display = "block";
  }
  
  // When the user clicks on &lt;span&gt; (x), close the modal
  span.onclick = function() {
    modal.style.display = "none";
  }
  
  // When the user clicks anywhere outside of the modal, close it
  window.onclick = function(event) {
    if (event.target == modal) {
      modal.style.display = "none";
    }
  }
      &lt;/script&gt;
      &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
      &lt;style&gt;
        .button {
          border-radius: 25px;
          font-size: 20px;
          color: white;
          background-color: #6969697a;
          border-color: white;
        }
      &lt;/style&gt;
    &lt;/head&gt;
  &lt;/html&gt;</code></pre>
  </div>
  </div>
  </p>