# How to position items relative to image target?

**URL:** <https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652>\
**Category:** Technical Support\
**Tags:** image-targets\
**Created:** [March 8, 2024, 10:55pm UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652 "2024-03-08T22:55:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ze\_ev\_Gilad](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/ze_ev_gilad/32/294_2.png) [@Ze\_ev\_Gilad](https://forum.8thwall.com/u/Ze_ev_Gilad)\
**Post date:** [March 8, 2024, 10:55pm UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652/1 "2024-03-08T22:55:17Z")

</div>

I have elements that need to be _precisely_ positioned relative to an image target.  
Is there any way to do this via some kind of GUI?  
Currently it’s a lot of trial and error tweaking `position` values _ad nauseum._

---

<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:** [March 9, 2024, 1:01am UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652/2 "2024-03-09T01:01:35Z")

</div>

Hi @Ze_ev_Gilad at this time the best options is to either use the jellyfish photos for reference and or bring your image target into a 3D modeling software such as Blender and position your objects according to the image target. I’ve attached a photo of how I set up my image targe in blender to better align objects. Then second photo showing some animations.

 ![Screenshot 2024-03-08 at 5.00.50 PM](https://us1.discourse-cdn.com/flex019/uploads/x8thwall/original/1X/da54a714b32d514576baa85db5b6f119598dbadf.jpeg)  
 ![Screenshot 2024-03-08 at 5.00.56 PM](https://us1.discourse-cdn.com/flex019/uploads/x8thwall/original/1X/92ee174bf293b85e6f666da1b448f262543f20ab.jpeg)

---

<div class="post-metadata">

**Author:** ![Rickard\_Elimaa](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/rickard_elimaa/32/202_2.png) [@Rickard\_Elimaa](https://forum.8thwall.com/u/Rickard_Elimaa)\
**Post date:** [March 21, 2024, 8:39pm UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652/3 "2024-03-21T20:39:14Z")

</div>

> [@Ze\_ev\_Gilad](#):
>
> I have elements that need to be _precisely_ positioned relative to an image target.

Whenever the events `xrimagefound` or `xrimageupdated ` are fired, the detail will contain `scaledWidth` and `scaledHeight`, which are scaling information so you know if it’s a landscape or a portrait image. The bigger of these two will always be 1 (meter).

However, the smaller dimension tells you how many meters it takes to fill up the fill width/height of the image target. So if you got a `scaledHeight` of 0.74 (meters), that tells you that if you set the height to 0.74, your video or image element will take up the height of the entire image target.

But the **problem** is that 8th Wall always crops the image targets while scaling down the larger dimension (width, in the example) to 1, which will scale down the entire visible element.

So the **solution** is to calculate the ratio of your image or video element after the metadata has loaded, multiply that with the minimum dimension (e.g. `scaledHeight 0.74`), and use the minimum dimension and the modified ratio to set the scale on the child element of your image target element.

NOTE: It’s really important that the image target is the _exact_ same size as your element and that you don’t adjust the cropping at all. Simply upload your image and follow all the required steps for adding a new image target.

# Example code

I’m writing this blindly so … take it for what it is.

```auto
<!-- HTML -->
 <a-entity example-named-image-target="name: video-target">
    <a-entity 
      example-play-video="video: #jelly-video; thumb: #jelly-thumb;"
      geometry="primitive: plane"
    ></a-entity>
 </a-entity>

```

[Original source](https://github.com/8thwall/web/blob/master/examples/aframe/flyer/index.html#L59): Image Targets Flyer example (copied and modified)

```auto
/ **Javascript: registering components in index.js** /

import { exampleNamedImageTarget } from './example-named-image-target.js';
import { examplePlayVideo } from './example-play-video.js';

AFRAME.registerComponent('example-named-image-target', exampleNamedImageTarget);
AFRAME.registerComponent('example-play-video', examplePlayVideo);

```

```auto
/ **Javascript component: example-named-image-target.js** /

const exampleNamedImageTarget = {
  schema: {
    name: {type: 'string'},
  },
  init() {
    const {object3D} = this.el
    const {name} = this.data

    const setupScalingFactor = ({detail}) => {
      if (name === detail.name) {
        // HERE IS WHERE THE MAGIC HAPPENS
        this.el.firstElementChild.components.minDimension = Math.min(detail.scaledHeight, detail.scaledWidth)
      }
    }

    // Basically the same as the original code
    const updateImage = ({detail}) => {
      if (name === detail.name) {
        object3D.position.copy(detail.position)
        object3D.quaternion.copy(detail.rotation)
        object3D.scale.set(detail.scale, detail.scale, detail.scale)
        object3D.visible = true
      }
    }

    const hideImage = ({detail}) => {
      if (name === detail.name) {
        object3D.visible = false
      }
    }

    this.el.sceneEl.addEventListener('xrimagefound', setupScalingFactor)
    this.el.sceneEl.addEventListener('xrimageupdated', updateImage)
    this.el.sceneEl.addEventListener('xrimagelost', hideImage)
  },
}

export { exampleNamedImageTarget }

```

[Original source](https://github.com/8thwall/web/blob/master/xrextras/src/aframe/components/target-components.ts#L316): xrextras-named-image-target (copied, simplified, and modified)

```auto
/ **Javascript component: example-play-video.js** /

const examplePlayVideo = {
  schema: {
    video: {type: 'string'},
    thumb: {type: 'string'},
  },
  init() {
    const v = document.querySelector(this.data.video)
    const p = this.data.thumb && document.querySelector(this.data.thumb)
    const {el} = this

    el.setAttribute('material', 'src', p || v)
    el.setAttribute('class', 'cantap')

    /**
    * MORE MAGIC: SETTING CORRECT SCALE
    * 'scaledWidth' and 'scaledHeight' are in meters
    */
    const setScale(scaledWidth, scaledHeight) {
      el.object3D.scale.set(
        this.el.components.minDimension * scaledWidth,
        this.el.components.minDimension * scaledHeight
      )
    }

    // THIS ASSUMES YOU PRELOADED THE ELEMENT INSIDE A-ASSET
    // Parameters are either 1 or bigger than 1.
    setScale(
      (v.videoWidth > v.videoHeight) ? v.videoWidth / v.videoHeight : 1,
      (v.videoHeight > v.videoWidth) ? v.videoHeight / v.videoWidth : 1
    )

    el.addEventListener('click', () => {
      if (!playing) {
        el.setAttribute('material', 'src', v)
        v.play()
      } else {
        el.setAttribute('material', 'src', p || v)
        v.pause()
      }
    })
  },
}

export { examplePlayVideo }

```

[Original source](https://github.com/8thwall/web/blob/master/xrextras/src/aframe/components/gestures-components.ts#L338): xrextras-play-video (copied, modified, and extended)

Note that if the thumbnail doesn’t have the same dimensions as the element itself, then you need to take that into consideration by setting the scale based on the image dimensions and then setting the scale again based on the video dimensions when the video is about to be played.

---

<div class="post-metadata">

**Author:** ![Ze\_ev\_Gilad](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/ze_ev_gilad/32/294_2.png) [@Ze\_ev\_Gilad](https://forum.8thwall.com/u/Ze_ev_Gilad)\
**Post date:** [March 21, 2024, 8:52pm UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652/4 "2024-03-21T20:52:48Z")

</div>

Thank you! Very useful info.

---

<div class="post-metadata">

**Author:** ![Rickard\_Elimaa](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/rickard_elimaa/32/202_2.png) [@Rickard\_Elimaa](https://forum.8thwall.com/u/Rickard_Elimaa)\
**Post date:** [April 2, 2024, 11:03am UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652/5 "2024-04-02T11:03:11Z")

</div>

Discovered the other week that the event `xrimagescanning` is sent out whenever image targets are set, and the detail will contain the following properties for all image targets:

![imagetTargetProps](https://us1.discourse-cdn.com/flex019/uploads/x8thwall/original/1X/73cc13b69e62bb4c77eb6fcf0ff0647b0bc59986.png)

So, it’s not necessary to wait for the metadata from the image or video to set the scale, unless you create `example-name-image-targets` dynamically (like I do). You can instead calculate the scale directly in the `example-named-image-target` component, using `originalHeight` and `originalWidth` together with `Math.min(geometry.scaledWidth, geometry.scaledHeight)`.

---

<div class="post-metadata">

**Author:** ![Kean-Chuan\_Lim](https://sea1.discourse-cdn.com/flex019/user_avatar/forum.8thwall.com/kean-chuan_lim/32/227_2.png) [@Kean-Chuan\_Lim](https://forum.8thwall.com/u/Kean-Chuan_Lim)\
**Post date:** [April 16, 2024, 12:27pm UTC](https://forum.8thwall.com/t/how-to-position-items-relative-to-image-target/652/6 "2024-04-16T12:27:09Z")

</div>

Hi Rickard ,

Did you find a way to disable the " xr image scanning " function …  
I am seeing a lot of positional jitter , else floating point errors when the marker position updates. Then we have a tall 3d object so its made worse at the extents. Ideally once the " xr image scanning " is done , we should be able to turn it off …

Thanks !
