Search code examples
javascriptaframe

Aframe cycle through a-sky image source on button click


I'm trying to cycle through over panoramic images set as a-sky, using the forward and back buttons. But I'm struggling with the js logic. Any help is appreciated. The below example uses 3 images in the array, but in practice it'll have hundreds.

  function goNext() {

    var zerod = 0;
    var images = ["https://aframe.io/aframe/examples/boilerplate/panorama/puydesancy.jpg", 
                  "https://aframe.io/aframe/examples/showcase/composite/lake.jpg", 
                  "https://l13.alamy.com/360/PWNBM9/testing-new-cameralens-combination-in-my-garden-in-aarhus-denmark-PWNBM9.jpg"]

    function nextimage() {
    console.log(zerod)
      $("#sky").attr("src", images[zerod])
      zerod = (zerod < images.length + 1) ? ++zerod : 0
    }
    nextimage();
  };
  
    function goBack() {

    var zerod = 0;
    var images = ["https://aframe.io/aframe/examples/boilerplate/panorama/puydesancy.jpg", 
                  "https://aframe.io/aframe/examples/showcase/composite/lake.jpg", 
                  "https://l13.alamy.com/360/PWNBM9/testing-new-cameralens-combination-in-my-garden-in-aarhus-denmark-PWNBM9.jpg"]

    function previmage() {
    console.log(zerod)
      $("#sky").attr("src", images[zerod])
      zerod = (zerod < images.length - 1) ? ++zerod : 0
    }
    previmage();
  };
.menu {
    position: absolute;
    bottom: 15px;
    z-index: 2;
    right: 15px;
}

.menu a {
    display: block;
    background: rgba(0, 0, 0, 0.35);
    color: white;
    padding-left: 5px;
    padding-right: 5px;
    padding-bottom: 5px;
    padding-top: 5px;
    text-decoration: none;
    font-family: tahoma;
    margin: 5px;
    text-align: center;
    cursor: pointer;
}
<head>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>  
</head>
    
<body>
        <div class="menu">
        <!--<br>-->
        <a id="forward" onClick="goNext()">Forward</a>
        <!--<br>-->
        <a id="back" onClick="goBack()">Back</a>
        <!--<br>-->
        <a id="vr" onclick="document.querySelector('a-scene').enterVR()">VR</a>
        </div>

    <a-scene image-toggle vr-mode-ui="enabled: false">
           
    <a-assets>
      <img id="skybox" src="https://l13.alamy.com/360/PWNBM9/testing-new-cameralens-combination-in-my-garden-in-aarhus-denmark-PWNBM9.jpg">
    </a-assets>
        
      <a-sky id="sky" src="#skybox"></a-sky>
        <a-camera id="camera" look-controls="pointerLockEnabled: false">
        </a-camera>
    </a-scene>
</body>


Solution

  • First of all both goNext() and goBack() set zerod to 0;


    Second of all you want to change the index before setting the source. Imagine calling goNext() and goBack():

    // goNext()
    $("#sky").attr("src", images[zerod])              // zerod is 0 here
    zerod = (zerod < images.length + 1) ? ++zerod : 0 // zerod i 1 here
    
    // goBack()
    $("#sky").attr("src", images[zerod]) // zerod is 1 here! Nothing changes!
    zerod = (zerod < images.length - 1) ? ++zerod : 0
    

    goBack() does nothing in this case if you click it after goNext()


    Last but not least - the conditions:

    // goNext()
    // three images, but you check if the index is less then 4?
    zerod = (zerod < images.length + 1) ? ++zerod : 0           
    
    // goBack()
    // you increase the index? thought you should be going back
    zerod = (zerod < images.length - 1) ? ++zerod : 0
    

    Should look like this:

    // goNext()
    // switch to 0 when we're at the last image (2nd index for three images)
    zerod = (zerod < images.length - 1) ? ++zerod : 0  
        
    // goBack()
    // decrease the index. change to the last image when at the first one
    zerod = (zerod <= 0) ? --zerod : images.length - 1;
    

    Check it out with these three points applied:

    var zerod = 0;
    var images = ["https://aframe.io/aframe/examples/boilerplate/panorama/puydesancy.jpg",
      "https://aframe.io/aframe/examples/showcase/composite/lake.jpg",
      "https://l13.alamy.com/360/PWNBM9/testing-new-cameralens-combination-in-my-garden-in-aarhus-denmark-PWNBM9.jpg"
    ]
    
    function goNext() {
      zerod = (zerod < images.length - 1) ? ++zerod : 0;
      console.log(zerod)
      $("#sky").attr("src", images[zerod])
    }
    
    function goBack() {
      zerod = (zerod != 0) ? --zerod : images.length -1;
        console.log(zerod)
      $("#sky").attr("src", images[zerod])
    };
    .menu {
      position: absolute;
      bottom: 15px;
      z-index: 2;
      right: 15px;
    }
    
    .menu a {
      display: block;
      background: rgba(0, 0, 0, 0.35);
      color: white;
      padding-left: 5px;
      padding-right: 5px;
      padding-bottom: 5px;
      padding-top: 5px;
      text-decoration: none;
      font-family: tahoma;
      margin: 5px;
      text-align: center;
      cursor: pointer;
    }
    <head>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
      <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
    </head>
    
    <body>
      <div class="menu">
        <!--<br>-->
        <a id="forward" onClick="goNext()">Forward</a>
        <!--<br>-->
        <a id="back" onClick="goBack()">Back</a>
        <!--<br>-->
        <a id="vr" onclick="document.querySelector('a-scene').enterVR()">VR</a>
      </div>
    
      <a-scene image-toggle vr-mode-ui="enabled: false">
    
        <a-assets>
          <img id="skybox" src="https://aframe.io/aframe/examples/boilerplate/panorama/puydesancy.jpg">
        </a-assets>
    
        <a-sky id="sky" src="#skybox"></a-sky>
        <a-camera id="camera" look-controls="pointerLockEnabled: false">
        </a-camera>
      </a-scene>
    </body>


    Even better if you turn it into a custom component:

    .menu {
      position: absolute;
      bottom: 15px;
      z-index: 2;
      right: 15px;
    }
    
    .menu a {
      display: block;
      background: rgba(0, 0, 0, 0.35);
      color: white;
      padding-left: 5px;
      padding-right: 5px;
      padding-bottom: 5px;
      padding-top: 5px;
      text-decoration: none;
      font-family: tahoma;
      margin: 5px;
      text-align: center;
      cursor: pointer;
    }
    <script src="https://aframe.io/releases/1.3.0/aframe.min.js"></script>
    <script>
      AFRAME.registerComponent("image-changer", {
        init: function() {
          // grab the elements
          const nextbtn = document.getElementById("forward");
          const backbtn = document.getElementById("back");
          // react to the clicks
          nextbtn.addEventListener("click", () => {
            this.index = (this.index < this.images.length - 1) ? ++this.index : 0;
            this.changeImage()
          })
          backbtn.addEventListener("click", () => {
            this.index = (this.index != 0) ? --this.index : this.images.length - 1;
            this.changeImage()
          })
          // initial index and images values
          this.index = 0;
          this.images = ["https://aframe.io/aframe/examples/boilerplate/panorama/puydesancy.jpg",
            "https://aframe.io/aframe/examples/showcase/composite/lake.jpg",
            "https://l13.alamy.com/360/PWNBM9/testing-new-cameralens-combination-in-my-garden-in-aarhus-denmark-PWNBM9.jpg"
          ]
          this.changeImage();
        },
        changeImage: function() {
          this.el.setAttribute("src", this.images[this.index])
        }
      })
    </script>
    <div class="menu">
      <!--<br>-->
      <a id="forward">Forward</a>
      <!--<br>-->
      <a id="back">Back</a>
      <!--<br>-->
      <a id="vr" onclick="document.querySelector('a-scene').enterVR()">VR</a>
    </div>
    
    <a-scene image-toggle vr-mode-ui="enabled: false">
      <a-sky id="sky" image-changer></a-sky>
      <a-camera id="camera" look-controls="pointerLockEnabled: false">
      </a-camera>
    </a-scene>