3

I upload image from nodejs to vue And put the image in v-card

But the image is cut off

how to resize the image by not cutting?

sh_J
  • 78
  • 1
  • 1
  • 5

2 Answers2

15

Use 'contain' attribute in v-img

<v-img src="/picture.png" alt=""
    contain    <!-- causes picture not to be cropped -->
    height="100px"
    width="150px">
</v-img>

check https://vuetifyjs.com/en/components/images#api for more information

johnonthetrail
  • 151
  • 1
  • 3
6

I understand this question has been answered long back but adding my answer to help the community.

The code below is not specific just for vuetify.js but this can also be used in any vue.js projects - just change the markups. And if you modify a bit then this can also be used in React, Angular or any JS frameworks.

// If you like you can this part/section into separate file 
// ------- Move from here -------
const dataURItoBlob = (dataURI) => {
  const bytes = dataURI.split(',')[0].indexOf('base64') >= 0
    ? atob(dataURI.split(',')[1])
    : unescape(dataURI.split(',')[1]);
  const mime = dataURI.split(',')[0].split(':')[1].split(';')[0];
  const max = bytes.length;
  const ia = new Uint8Array(max);
  for (let i = 0; i < max; i += 1) ia[i] = bytes.charCodeAt(i);
  return new Blob([ia], { type: mime });
};

const resizeImage = ({ file, maxSize }) => {
  const reader = new FileReader();
  const image = new Image();
  const canvas = document.createElement('canvas');

  const resize = () => {
    let { width, height } = image;

    if (width > height) {
      if (width > maxSize) {
        height *= maxSize / width;
        width = maxSize;
      }
    } else if (height > maxSize) {
      width *= maxSize / height;
      height = maxSize;
    }

    canvas.width = width;
    canvas.height = height;
    canvas.getContext('2d').drawImage(image, 0, 0, width, height);

    const dataUrl = canvas.toDataURL('image/jpeg');

    return dataURItoBlob(dataUrl);
  };

  return new Promise((ok, no) => {
    if (!file.type.match(/image.*/)) {
      no(new Error('Not an image'));
      return;
    }

    reader.onload = (readerEvent) => {
      image.onload = () => ok(resize());
      image.src = readerEvent.target.result;
    };

    reader.readAsDataURL(file);
  });
};

// export default resizeImage; // uncomment once moved to resizeImage.js
// ------- till here - into ./src/plugins/image-resize.js -------

// And then import in whichever component you like in this way:
// import resizeImage from '@/plugins/image-resize.js';

new Vue({
  el: '#app',
  vuetify: new Vuetify(),
  data() {
    return {
      originalImg: '',
      resizedImg: '',
    };
  },
  methods: {
    readURL(file) {
      // START: preview original
      // you can remove this section if you don't like to preview original image
      if (!file.type.match(/image.*/)) {
        no(new Error('Not an image'));
        return;
      }

      const reader = new FileReader();
      reader.onload = (e) => this.originalImg = e.target.result;
      reader.readAsDataURL(file); // convert to base64 string
      // END: preview original

      // START: preview resized
      resizeImage({ file: file, maxSize: 150 }).then((resizedImage) => {
        this.resizedImg = URL.createObjectURL(resizedImage);
      }).catch((err) => {
        console.error(err);
      });
      // END: preview resized
    },
  },
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.min.css" rel="stylesheet">

<script src="https://cdn.jsdelivr.net/npm/vue@2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify@2.x/dist/vuetify.js"></script>

<div id="app">
  <v-app>
    <v-content>
      <v-container>
        <v-file-input
          accept="image/png, image/jpeg, image/bmp"
          placeholder="Pick an Image"
          prepend-icon="mdi-camera"
          label="Avatar"
          @change="readURL"
        ></v-file-input>
      </v-container>

      <v-container v-if="originalImg">
        <v-row justify="space-around">
          <v-col cols="5">
            <div class="subheading">Original Image</div>
            <img :src="originalImg"/>
          </v-col>
          <v-col cols="5">
            <div class="subheading">Resized Image</div>
            <img :src="resizedImg"/>
          </v-col>
        </v-row>
      </v-container>
    </v-content>
  </v-app>
</div>

Answers that helped me to complete this answer:

  1. Preview an image before it is uploaded
  2. Use HTML5 to resize an image before upload
Syed
  • 11,612
  • 10
  • 82
  • 122