How to get the naturalSize of Vuetify v-img?

Viewed 1455

So I need to get the sizes of an image shown in my page using Vuetify v-img. I tried to get the size with naturalHeight and naturalWidth by doing so:

//markup
<v-img ref="imageShow" @load="getSizes" src"/images/background.jpg"></v-img>

//method
getSizes(){
   console.log(this.$refs.imageShow.naturalHeigth)
}

but it didn't show me the size, it returns undefined.

3 Answers

VImg renders on a VResponsive, and puts the image in a div as backgroundimage.

It is not a HTMLImageElement.

But maybe you can abuse an integrated onLoad event and access its vm.image, which is a HTMLImageElement | null.

getSizes(){
   // unless loading error
   const {naturalHeight, naturalWidth} = this.$refs.imageShow.image;
   console.log(naturalHeight, naturalWidth);
}

Or you can extend this component for your needs:

let vuetifyOptions;
Vuetify.install({
  use(_, options){
     vuetifyOptions: {...options}
  }
})

const VImg = vuetifyOptions.components.VImg;


export default {
  extends: VImg,
  data(){
    return {
      naturalHeight: null,
      naturalWidth: null
    }
  }
  onLoad(){
    this.naturalHeight = this.image.naturalHeight
    this.naturalWidth = this.image.naturalWidth
    this.$emit('naturals', this.image)
    this.$emit('load', this.src)
  }
}

If you look under the hood, you find Vuetify uses the background image of a DIV element, and not an IMG element. If you then take apart the engine, you find the natural width and aspect ratio stashed in the Vue component.

I needed to extract this in a pinch, so I did the following. I'm not recommending this non-API hack, but "it is what it is".

I was not able to access the Component from my code, so needed to grab the dimensions from the element proper.

const naturalWidth = divElement.__vue__.naturalWidth
const naturalHeight = naturalWidth / divElement.__vue__.computedAspectRatio

You can also check your element is a v-img, and get the html image element from the component

if (divElement.classList.contains('v-image')) {
  const img = divElement.__vue__?.image as HTMLImageElement
  if (img?.complete) {
    process(img.naturalWidth, img.naturalHeight)
  }
}

Finally, make sure you wait for the loaded event.

Related