对单个实体进行Aframe纹理控制

时间:2019-03-05 00:42:34

标签: javascript html three.js aframe

我想知道如何在实体上设置纹理,但仅在该实体上设置纹理,然后通过选择纹理按钮放置更多纹理,我无法使代码正常工作,但我想使其功能更像《我的世界》比原始《我的世界》框架演示更胜一筹。如果有人可以使我的代码正常工作,那将是真正的帮助。所有被注释掉的脚本是因为我想找到一种更好的方法来做我想做的事情。本质上,我想在底部的菜单中选择一个纹理,然后在我的实体上使用该纹理。

<!DOCTYPE html>
<html>
  <head>
    <script src="https://aframe.io/releases/0.9.0/aframe.min.js"></script>
    <script src="https://unpkg.com/aframe-controller-cursor-component@0.2.x/dist/aframe-controller-cursor-component.min.js"></script>
<script>
    /**
 * 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);
  }
});
    </script>
<script>/**
 * Spawn entity at the intersection point on click, given the properties passed.
 *
 * `<a-entity intersection-spawn="mixin: box; material.color: red">` will spawn
 * `<a-entity mixin="box" material="color: red">` 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 => {
      // 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 => {
        if (name === 'event') { return; }
        AFRAME.utils.entity.setComponentProperty(spawnEl, name, data[name]);
      });

      // Append to scene.
      el.sceneEl.appendChild(spawnEl);
    });
  }
});</script>
    <script>
     function startTimer(duration, display) {
    var timer = duration, minutes, seconds;
    setInterval(function () {
        minutes = parseInt(timer / 60, 10)
        seconds = parseInt(timer % 60, 10);

        minutes = minutes < 10 ? "0" + minutes : minutes;
        seconds = seconds < 10 ? "0" + seconds : seconds;

        display.textContent = minutes + ":" + seconds;

        if (--timer < 0) {
            timer = duration;
        }
    }, 1000);
}

window.onload = function () {
    var fiveMinutes = 60 * 10,
        display = document.querySelector('#time');
    startTimer(fiveMinutes, display);
};
    </script>
    <style>
      .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;
      }
    </style>
  </head>
  <body>
    
    
    <!-- aframe overlay -->
    
    <div class="Container" style="position:relative;">
   <!-- <a-scene id="updateMe" inspector="https://cdn.jsdelivr.net/gh/aframevr/aframe-inspector@master/dist/aframe-inspector.min.js"> -->
      <a-scene embedded>
      <a-assets>
      <img id="groundTexture" src="floor.jpg">
      <img id="skyTexture" src="https://cdn.aframe.io/a-painter/images/sky.jpg">
      
        <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"
      ></a-mixin>
        <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"
      ></a-mixin>
        <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"
      ></a-mixin>
        <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"
      ></a-mixin>
        <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"
      ></a-mixin>
        <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"
      ></a-mixin>
        <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"
      ></a-mixin>
        
    </a-assets>
		 <a-obj-model rotation="-90 45 0" position="0 2 0" src="tinker.obj" mtl="obj.mtl"></a-obj-model>
    <a-cylinder id="ground" src="#groundTexture" radius="30" height="0.1"></a-cylinder>

    <a-sky id="background" src="#skyTexture" theta-length="90" radius="30"></a-sky>

    <!-- Camera. -->
    <a-camera fly="true" position="0 0.75 15" wasd-controls="acceleration: 20" wasd-controls-enabled="true" fov="90" reverse-mouse-drag="false">
      <a-cursor id="Save1" intersection-spawn="event: click; mixin: voxel1"></a-cursor>
      <a-cursor id="Save2" intersection-spawn="event: click; mixin: voxel2"></a-cursor>
      <a-cursor id="Save3" intersection-spawn="event: click; mixin: voxel3"></a-cursor>
      <a-cursor id="Save4" intersection-spawn="event: click; mixin: voxel4"></a-cursor>
      <a-cursor id="Save5" intersection-spawn="event: click; mixin: voxel5"></a-cursor>
      <a-cursor id="Save6" intersection-spawn="event: click; mixin: voxel6"></a-cursor>
      <a-cursor id="Save7" intersection-spawn="event: click; mixin: voxel7"></a-cursor>
    </a-camera>
      </a-scene>
      <!-- /aframe overlay -->
      <center>
      <div style="position:absolute; margin-right:8px; top:0px; width:205px; height:180px; left:0px; z-index:1000;">
        <div class="transparentBox">
        <b><h1 color="#FFFFFF" id="time">10:00</h1></b>
          <p style="font-size:20px;font-family:monospace;margin-top:-20px;">Camera Height:</p>
          <h1><b><a>&uarr;</a>~~<a>&darr;</a></b></h1>
          <iframe src="250-milliseconds-of-silence.mp3" allow="autoplay" id="audio" style="display:none"></iframe>
          <audio autoplay loop id="track">
  <source src="Magic_Scout_-_Cottages.mp3" type="audio/mpeg">
Your browser does not support the audio element.
</audio><center>
          <button class="button" id="myBtn">Menu</button>
          </center>
        </div>
        <div id="myModal" class="modal">
        <center>
  <!-- Modal content -->
  <div class="modal-content">
    <span id="clickMe" type="button" value="clickme" onclick="startTimer()" class="close">&times;</span>
    <center>
      <p class="beginMenuText"><b>Welcome to SandBox!</b></p>
      <p class="Text">WASD to move, Space place blocks.</p>
      <p class="Text2">You have 10 min. before the game restarts and all is lost.</p>
      <p class="Text2point5">Have fun...</p>
    </center>
    <p class="Text3"><b><u>Credits:</u></b></p>
    <p class="Text4">All music by <b>Kevin MacLeod</b></p>
    <p class="Text5"><b>Aframe</b> by the Aframe authors.</p>
    <p class="Text6">(Licenced under the <b>MIT Licence</b>)</p>
    <p class="Text7">Inspiration from other <b>WebVR Projects.</b></p>
    <p class="Text8">Voxel textures can be changed using the menu at the <b>bottom</b>.</p>
    <p class="Text9"><b>Enjoy!</b></p>
    <div class="unmute" onclick="document.getElementById('track').muted = !document.getElementById('track').muted;$(this).toggleClass('mute')"></div>
  </div>
          </center>
        </div>
          <div class="textureMenu">
            <div class="textureBox" id="Kill1" ><img src="Box.jpg" height="45" width="45"></div>
             <p class="spacer">~</p>
            <div class="textureBox" id="Kill2"><img src="Brick.jpg" height="45" width="45"></div>
             <p class="spacer">~</p>
            <div class="textureBox" id="Kill3"><img src="Steel.jpg" height="45" width="45"></div>
             <p class="spacer">~</p>
            <div class="textureBox" id="Kill4"><img src="Pcb.jpg" height="45" width="45"></div>
             <p class="spacer">~</p>
            <div class="textureBox" id="Kill5"><img src="Grass.jpg" height="45" width="45"></div>
             <p class="spacer">~</p>
            <div class="textureBox" id="Kill6"><img src="Ice.jpg" height="45" width="45"></div>
             <p class="spacer">~</p>
            <div class="textureBox" id="Kill7"><img src="Fabric.jpg" height="45" width="45"></div>
        </div>
    </div>
        </center>
      
    </div>
    
  </body>                  
  <head>
   <!--<script>
document.getElementById('Kill1').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save1');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel1');
  }
};
</script>
    <script>
document.getElementById('Kill2').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save2');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel2');
  }
};
</script>
    <script>
document.getElementById('Kill3').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save3');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel3');
  }
};
</script>
    <script>
document.getElementById('Kill4').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save4');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel4');
  }
};
</script>
    <script>
document.getElementById('Kill5').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save5');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel5');
  }
};
</script>
    <script>
document.getElementById('Kill6').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save6');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel6');
  }
};
</script>
    <script>
document.getElementById('Kill7').addEventListener('click', function () {
  var mixinEl = document.getElementById('Save7');
  if (mixinEl.getAttribute('mixin') === 'voxel') {
    mixinEl.setAttribute('mixin',: 'voxel7');
  }
};
</script>-->

    <style>
      .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;
}
    </style>
    <script>
      // Get the modal
var modal = document.getElementById('myModal');

// Get the button that opens the modal
var btn = document.getElementById("myBtn");

// Get the <span> 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 <span> (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";
  }
}
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <style>
      .button {
        border-radius: 25px;
        font-size: 20px;
        color: white;
        background-color: #6969697a;
        border-color: white;
      }
    </style>
  </head>
</html>

1 个答案:

答案 0 :(得分:0)

切换纹理可以通过两种方式完成

  • aframe原语(例如<a-box><a-sphere>实体)很简单。只需更改material.src属性

    el.setAttribute('material', 'src', newTexture)
    
  • 模型可能很难处理,因为您需要切换mesh.map.texture属性(可能在所有子对象上,而不仅仅是在一个网格上)。

    var mesh = this.el.getObject3D('mesh')
    var loader = new THREE.TextureLoader();
    loader.load( url, (texture) => {
        // onLoad callback
        mesh.material.map = texture
        mesh.material.needsUpdate = true
        this.switch = !this.switch
      }
    )
    


选择可能以百万分之一的方式完成。

起初,我想存储有关纹理的信息,并在单击<a-box>时访问它,但是一种简单的方法是拥有几张图像

<img class=".images" ....>
<img class=".images" ....>

以及每个无框架原语上的一个组件,该组件将是:

检测这些图像上的点击->存储信息->单击我们时使用它:

检测图像上的点击:

var els = document.getElementsByClassName("images");
Array.from(els).forEach((el) => {
   el.addEventListener('click', (e)=>{
      this.selectedTexture = e.target.src
   })
});

点击时应用纹理:

this.el.addEventListener('click', (e) => {
  if (!this.selectedTexture) {
  return
  }
  this.el.setAttribute("material", "src", this.selectedTexture)
})

This fiddle包含以上所有内容。有两个框可以自己切换纹理,其余的将应用所选图像作为纹理。