# Button struggles

**URL:** https://forum.8thwall.com/t/button-struggles/942
**Category:** Technical Support
**Created:** [April 2, 2024, 1:47pm UTC](https://forum.8thwall.com/t/button-struggles/942 "2024-04-02T13:47:28Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Richard\_de\_Mowbray](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/richard_de_mowbray/32/193_2.png) [@Richard\_de\_Mowbray](https://forum.8thwall.com/u/Richard_de_Mowbray)
#### Post date: [April 2, 2024, 1:47pm UTC](https://forum.8thwall.com/t/button-struggles/942/1 "2024-04-02T13:47:28Z")

</div>

Hi all,  
I am trying to set up two UI buttons to call an animation on a .glb and to go to a website. I’ve looked through the simple button project and the tutorials but struggling to make progress. Not least because I can’t see the buttons to test them. It seems like 8th wall suggests ‘establishing’ the buttons outside of the a-scene. But I saw advice that says to include them after camera. Any thoughts?

```auto
head.html

<meta name="8thwall:renderer" content="aframe:1.3.0" />
<meta name="8thwall:package" content="@8thwall.xrextras" />
<meta name="8thwall:package" content="@8thwall.landing-page" />

<!-- Other external scripts and meta tags can also be added. -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<script src="//cdn.8thwall.com/web/aframe/aframe-extras-6.1.1.min.js"></script>

app.js

// Import necessary styles
import './main.css'

// AFRAME component to open a link, using 'lbutton' as the component name
AFRAME.registerComponent('lbutton', {
  init() {
    const btn = document.getElementById('link-button')
    if (btn) {
      btn.addEventListener('click', () => {
        window.open('https://www.bbc.co.uk/', '_blank')
      })
    } else {
      console.error('Link button not found')
    }
  },
})

// AFRAME component to play animation, renamed to 'abutton'
AFRAME.registerComponent('abutton', {
  init() {
    const btn = document.getElementById('animation-button')
    if (btn) {
      btn.addEventListener('click', () => {
        const thing = document.getElementById('windmill')
        if (thing) {
          // Assuming A-Frame and the animation-mixer component
          // Swap '*' with 'Cylinder.003Action' to target a specific animation
          thing.setAttribute('animation-mixer', {clip: 'Cylinder.003Action', loop: 'once'})
        } else {
          console.error('windmill model not found')
        }
      })
    } else {
      console.error('Animation button not found')
    }
  },
})

body.html

<!-- Copyright (c) 2022 8th Wall, Inc. -->
<!-- body.html is optional; elements will be added to your html body after app.js is loaded. -->
<button id="link-button">Open Link</button>
<button id="animation-button">Play Animation</button>
<a-scene
  xrextras-gesture-detector
  landing-page
  xrextras-loading
  xrextras-runtime-error
  renderer="colorManagement:true; webgl2: true;"
  xrweb="disableWorldTracking: true">
  <a-assets>
    <a-asset-item id="jelly-glb" src="assets/jellyfish-model.glb"></a-asset-item>
    <a-asset-item id="ooh-glb" src="assets/OA3DlogoAniV31.glb"></a-asset-item>
    <a-asset-item id="windmill" src="assets/windmill.glb"></a-asset-item>
    <img id="jelly-thumb" src="assets/video-thumbnail.jpg" />
    <video
      id="jelly-video"
      autoplay
      muted
      crossorigin="anonymous"
      loop="true"
      src="assets/jellyfish-video.mp4"></video>
  </a-assets>

  <a-camera position="0 4 10" raycaster="objects: .cantap" cursor="fuse: false; rayOrigin: mouse;">
  </a-camera>

  <a-light type="directional" intensity="0.5" position="1 1 1"></a-light>

  <a-light type="ambient" intensity="0.7"></a-light>

  <!-- Note: "name:" must be set to the name of the image target uploaded to the 8th Wall Console -->
  <xrextras-named-image-target name="video-target">
    <a-entity
      gltf-model="#ooh-glb"
      animation-mixer
      animation="Clip:Scene"
      rotation="90 0 0"
      scale="3 3 3"
      position="-0.35 -0.35 0"></a-entity>
    <a-plane
      position="0 0 0.5"
      rotation="0 0 90"
      scale="0.5 0.5 0.5"
      width="1"
      height="1"
      color="#eeeae2"
      material="opacity: 0.2; side: double;">
    </a-plane>
    <a-entity
      gltf-model="#windmill"
      rotation="90 0 0"
      scale="0.1 0.1 0.1"
      position="-1 1 0"></a-entity>
  </xrextras-named-image-target>

  <!-- Note: "name:" must be set to the name of the image target uploaded to the 8th Wall Console -->
  <xrextras-named-image-target name="model-target">
    <!-- Add a child entity that can be rotated independently of the image target. -->
    <a-entity
      gltf-model="#ooh-glb"
      animation-mixer
      animation="Clip:Scene"
      rotation="90 0 0"
      scale="3 3 3"
      position="-0.35 -0.35 0"></a-entity>
    <button id="startAnimationButton" position="0 0 0.5">Lift the stone</button>
    <a-plane
      position="0 0 0.5"
      rotation="0 0 90"
      scale="0.5 0.5 0.5"
      width="1"
      height="1"
      color="#eeeae2"
      material="opacity: 0.2; side: double;">
    </a-plane>
  </xrextras-named-image-target>
</a-scene>

main.css

#link-button {
    /* Example styling */
    padding: 10px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 5px;
    font-size: 16px;
    cursor: pointer;
}

#animation-button {
    /* Example styling */
    padding: 10px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 5px;
    font-size: 16px;
    cursor: pointer;
}

```

---

<div class="post-metadata">

### Author: ![TonyT](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/tonyt/32/88_2.png) [@TonyT](https://forum.8thwall.com/u/TonyT)
#### Post date: [April 2, 2024, 3:16pm UTC](https://forum.8thwall.com/t/button-struggles/942/2 "2024-04-02T15:16:30Z")

</div>

Hi @Richard_de_Mowbray,

Personally I always define my UI elements above/outside of the a-scene, so your approach there is just fine.

At first glance I think your AFrame components look great, however, and while you have **defined** them, you’ll need to actually add them to a component in your scene for them to be activated.

For example, you can add them to your a-scene:

```auto
<a-scene
  lbutton
  abutton
  xrextras-gesture-detector
  landing-page
  xrextras-loading
  xrextras-runtime-error
  renderer="colorManagement:true; webgl2: true;"
  xrweb="disableWorldTracking: true">

```

You might also need to adjust the z-index, and perhaps set `position: absolute` so these buttons appear on top of your scene and in the right position, example:

> **[A-Frame: Animation Mixer | 8th Wall | 8th Wall](https://www.8thwall.com/8thwall/animation-mixer-aframe/code/body.html#L4)**
>
> This example allows the user to position, scale, rotate, and change between animations embedded in a 3D model.

> **[A-Frame: Animation Mixer | 8th Wall | 8th Wall](https://www.8thwall.com/8thwall/animation-mixer-aframe/code/index.css#L1)**
>
> This example allows the user to position, scale, rotate, and change between animations embedded in a 3D model.

You can pull up the Safari or Chrome debugger to inspect elements on your page to understand further why they aren’t visible.

I wsuggest using this sample project as a reference - it contains a button and when you click it sets animation-mixer attributes:

> **[A-Frame: Animation Mixer | 8th Wall | 8th Wall](https://www.8thwall.com/8thwall/animation-mixer-aframe)**
>
> This example allows the user to position, scale, rotate, and change between animations embedded in a 3D model.

Hope this helps!

---

<div class="post-metadata">

### Author: ![Richard\_de\_Mowbray](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/richard_de_mowbray/32/193_2.png) [@Richard\_de\_Mowbray](https://forum.8thwall.com/u/Richard_de_Mowbray)
#### Post date: [April 2, 2024, 4:15pm UTC](https://forum.8thwall.com/t/button-struggles/942/3 "2024-04-02T16:15:13Z")

</div>

Really helpful, thanks Tony. So add the position info in the .css like this  
`#link-button {  
padding: 10px;  
background-color: #007bff;  
color: white;  
border: none;  
border-radius: 5px;  
font-size: 16px;  
cursor: pointer;  
position: absolute;  
top: 20px;  
left: 20px;  
z-index: 10;  
}

#animation-button {  
position: absolute;  
top: 100px;  
left: 20px;  
padding: 10px;  
background-color: #007bff;  
color: white;  
border: none;  
border-radius: 5px;  
font-size: 16px;  
cursor: pointer;  
position: absolute;  
top: 20px;  
left: 20px;  
z-index: 10;  
}

` or in the body.html like in the animation-mixer session? I see my animation button now, but there’s no functionality atm. Still…progress made! 💪

---

<div class="post-metadata">

### Author: ![Ian](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/ian/32/430_2.png) [@Ian](https://forum.8thwall.com/u/Ian)
#### Post date: [April 2, 2024, 9:00pm UTC](https://forum.8thwall.com/t/button-struggles/942/4 "2024-04-02T21:00:34Z")

</div>

are you getting a console.log when the button is clicked? please verify this first.

Secondly, can you verify your animation name? or see if any animations play with \*

`thing.setAttribute('animation-mixer', {clip: '*', loop: 'repeat'})`

---

<div class="post-metadata">

### Author: ![Richard\_de\_Mowbray](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/richard_de_mowbray/32/193_2.png) [@Richard\_de\_Mowbray](https://forum.8thwall.com/u/Richard_de_Mowbray)
#### Post date: [April 2, 2024, 10:37pm UTC](https://forum.8thwall.com/t/button-struggles/942/5 "2024-04-02T22:37:04Z")

</div>

Thanks for your help Ian. It doesn’t make any difference when I call all animations (\*). I didn’t see a console.log when the button is clicked. But when I added a console.log below in my code I did. code…`AFRAME.registerComponent('abutton', { init() { const btn = document.getElementById('animation-button') if (btn) { btn.addEventListener('click', () => { console.log('Animation button clicked!') const thing = document.getElementById('windmill') if (thing) { // Assuming A-Frame and the animation-mixer component // Swap '*' with 'Cylinder.003Action' to target a specific animation thing.setAttribute('animation-mixer', {clip: '*', loop: 'once'}) } else { console.error('Owindmill model not found') } }) } else { console.error('Animation button not found') } }, }) `

---

<div class="post-metadata">

### Author: ![Ian](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/ian/32/430_2.png) [@Ian](https://forum.8thwall.com/u/Ian)
#### Post date: [April 3, 2024, 2:08am UTC](https://forum.8thwall.com/t/button-struggles/942/6 "2024-04-03T02:08:38Z")

</div>

After reviewing your code it looks like you are grabing a model in your `<a-assets>` with the id of windmill

This isn’t the entity you want to grab as this is what is being loaded into your scene. You need to grab the entity of the gltf model wihtin your actual scene.

So, where you load the windmill model like so

```auto
  <a-entity
      gltf-model="#windmill"
      rotation="90 0 0"
      scale="0.1 0.1 0.1"
      position="-1 1 0"></a-entity>

```

you need to give that entity an ID. Something like this

```auto
  <a-entity
      id="#windmill-model"
      gltf-model="#windmill"
      rotation="90 0 0"
      scale="0.1 0.1 0.1"
      position="-1 1 0"></a-entity>

```

Then get the entity 3D model by id

`const thing = document.getElementById('windmill-model')`

And this should work correctly. So you were essentially just grabbing the model and not the one that you actually were placing into your A-frame scene.

You can see this on line 53 in the sample proeject here:

> **[A-Frame: Animation Mixer | 8th Wall | 8th Wall](https://www.8thwall.com/8thwall/animation-mixer-aframe/code/body.html#L52)**
>
> This example allows the user to position, scale, rotate, and change between animations embedded in a 3D model.

---

<div class="post-metadata">

### Author: ![Richard\_de\_Mowbray](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/richard_de_mowbray/32/193_2.png) [@Richard\_de\_Mowbray](https://forum.8thwall.com/u/Richard_de_Mowbray)
#### Post date: [April 3, 2024, 7:06am UTC](https://forum.8thwall.com/t/button-struggles/942/7 "2024-04-03T07:06:47Z")

</div>

Thanks so much Ian, really appreciate your and the teams patience with my ‘greenness’. I just had to add a # to the id and it worked perfectly.

```auto
const thing = document.getElementById('#windmill-model')

```

---

<div class="post-metadata">

### Author: ![Richard\_de\_Mowbray](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/richard_de_mowbray/32/193_2.png) [@Richard\_de\_Mowbray](https://forum.8thwall.com/u/Richard_de_Mowbray)
#### Post date: [April 5, 2024, 1:16pm UTC](https://forum.8thwall.com/t/button-struggles/942/8 "2024-04-05T13:16:18Z")

</div>

Hi, I’ve been trying to get my UI buttons to appear once the image target is located. Are there any sample projects for that? I currently have this code in app.js

```auto
window.addEventListener('load', () => {
  const videoTarget = document.querySelector('xrextras-named-image-target[name="video-target"]')
  const animationButton = document.getElementById('animation-button')
  const linkButton = document.getElementById('link-button')

  // Listen for the image target being found
  videoTarget.addEventListener('xrimagefound', () => {
    console.log('Video target found')
    animationButton.classList.add('block')
    linkButton.classList.add('block')
    console.log('Video target found - buttons shown')
  })

  // Optional: Listen for the image target being lost
  videoTarget.addEventListener('xrimagelost', () => {
    animationButton.classList.add('hidden')
    linkButton.classList.add('hidden')
    console.log('Video target lost - buttons hidden')
  })
})

```

---

<div class="post-metadata">

### Author: ![Ian](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/ian/32/430_2.png) [@Ian](https://forum.8thwall.com/u/Ian)
#### Post date: [April 5, 2024, 7:40pm UTC](https://forum.8thwall.com/t/button-struggles/942/9 "2024-04-05T19:40:46Z")

</div>

Are your cosnole logs registering? You want to write your logic into a custom component then add it to your image target.

Something like this

```auto
const customImageTargetComponent = () => ({
  schema: {
    name: {type: 'string'},
  },
  init() {
    const {object3D} = this.el
    const {name} = this.data
    object3D.visible = false

    const imageFound = ({detail}) => {
      if (name !== detail.name) {
        return
      }

      object3D.position.copy(detail.position)
      object3D.quaternion.copy(detail.rotation)
      object3D.scale.set(detail.scale, detail.scale, detail.scale)

      object3D.visible = true
    }

    const imageUpdate = ({detail}) => {
      if (name !== detail.name) {
        return
      }
      object3D.position.copy(detail.position)
      object3D.quaternion.copy(detail.rotation)
      object3D.scale.set(detail.scale, detail.scale, detail.scale)
    }

    const imageLost = (e) => {
      object3D.visible = false
    }

    this.el.sceneEl.addEventListener('xrimagefound', imageFound)
    this.el.sceneEl.addEventListener('xrimageupdated', imageUpdate)
    this.el.sceneEl.addEventListener('xrimagelost', imageLost)
  },
})

export {customImageTargetComponent}

```

This tutorial may be helpful which explains the image target events

[![](https://us1.discourse-cdn.com/flex019/uploads/x8thwall/original/1X/c93155a0799fe6455d17eb831e7abfe2b9bf0dfd.jpeg "Implementing Image Targets With Advanced Techniques (Live Learning: Session 10)") ](https://www.youtube.com/watch?v=VwQk4msRPs4&t=363s)

You want to essentially show the button UI on xrimagefound and hide it on xrimagelost

---

<div class="post-metadata">

### Author: ![Ian](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/ian/32/430_2.png) [@Ian](https://forum.8thwall.com/u/Ian)
#### Post date: [April 5, 2024, 7:42pm UTC](https://forum.8thwall.com/t/button-struggles/942/10 "2024-04-05T19:42:42Z")

</div>

you can reference this sample project (for the custom image target component part)

> **[Image Target Portal with Navigation Mesh | 8th Wall Playground | 8th Wall](https://www.8thwall.com/playground/image-target-portal-nav-mesh/code/components/image-target-portal.js)**
>
> This example showcases how to create a WebAR project with an image target and character navigation mesh.

Then register the component in app.js (line 8)

> **[Image Target Portal with Navigation Mesh | 8th Wall Playground | 8th Wall](https://www.8thwall.com/playground/image-target-portal-nav-mesh/code/app.js#L8)**
>
> This example showcases how to create a WebAR project with an image target and character navigation mesh.

Then finally add it into your a-scene (line 32)

> **[Image Target Portal with Navigation Mesh | 8th Wall Playground | 8th Wall](https://www.8thwall.com/playground/image-target-portal-nav-mesh/code/body.html#L32)**
>
> This example showcases how to create a WebAR project with an image target and character navigation mesh.
