Skip to content

How to Upload and Convert Images To SVG in Nuxt.js

SVG is the world’s most popular vector image format used by designers, developers, and content creators. It is incredibly lightweight and scalable. It is also editable as code, allowing for customizations that improve SEO, design, and accessibility.

Creating an SVG from scratch can be tricky, but in this tutorial, you will learn how to generate SVG images and code from any image.

You will implement Cloudinary’s vectorize effect to create the SVG image and take advantage of Nuxt’s APIs to upload, get, and convert your SVG images to code.

View the complete demo for this tutorial on CodeSandbox:

The source code is also available on GitHub.

To understand the concepts in this tutorial, you should have the following:

  • Basic knowledge of Git, JavaScript, and Vue
  • A GitHub account (create an account here)
  • A Cloudinary account for uploading and converting your images (create an account here)
  • Node.js, Yarn, and Git installed on your PC

First, open this starter template URL in your browser to generate a GitHub repo for this project based on a starter template:

Here, you set nuxt-imgtosvg-demo as the name of your repo.

On your PC, open a terminal window and navigate to your preferred folder, then clone your newly created repo with the command below:

git clone <your-github-repo>
Code language: HTML, XML (xml)

After it has successfully cloned to your PC, navigate into its folder and install its dependencies with yarn:

cd nuxt-imgtosvg-demo
yarn

Or using npm:

cd nuxt-imgtosvg-demo
npm install

After successfully installing its dependencies, open the project in your preferred code editor and run the code below in your terminal to start a development server:

yarn dev

Or using npm:

npm run dev

This command will serve the project with a hot reload on localhost:3000, which you can view in your browser:

Get Cloudinary Cloud Name

In a new browser tab open your Cloudinary dashboard and copy your “Cloud Name”:

In the root directory of your project, create a .env file and update it with the code below:

CLOUDINARY_CLOUDNAME=your-cloudinary-cloud-name

Enable Client-side Uploads

To enable client-side uploads on Cloudinary, you will need an “unsigned upload preset”. In your browser, navigate to Cloudinary’s settings and click on the “Upload” tab, then scroll down to “Upload Presets”:

Click on “Add upload preset”, specify the name of your new preset, and change “Signing Mode” to “Unsigned”, then save the preset:

Take note of your upload preset name.

Install Cloudinary Package for Nuxt.js

In your project’s terminal, run the code below to install the Cloudinary package for Nuxt.js:

yarn add @nuxtjs/cloudinary
Code language: CSS (css)

Or using npm:

npm install @nuxtjs/cloudinary
Code language: CSS (css)

Configure Cloudinary in Nuxt.js

After its successful installation, open your nuxt.config.js file and update it with the code below:

export default {
  // do not remove pre-existing code
  modules: ['@nuxtjs/axios', '@nuxtjs/cloudinary'],

  cloudinary: {
    cloudName: process.env.CLOUDINARY_CLOUDNAME,
  },
  // do not remove pre-existing code
};
Code language: JavaScript (javascript)

In the code above, you did the following:

  • Added @nuxtjs/cloudinary to your Nuxt.js modules array
  • Specified your Cloudinary cloudName in a Cloudinary object

Select an Image from your Device

In your code editor, open pages/index.vue and observe the code on lines 16 to 26:

<input
  type="file"
  accept="image/*"
  name="fileInput"
  class="hidden"
  @change="handleChange"
  ref="fileInput"
/>
<!-- ...template code -->
<button :onClick="handleRef" purple="true">Choose Image</button>
Code language: HTML, XML (xml)

In the code above:

  • The <input /> accepts image files and triggers the handleChange method
  • The class="hidden" hides <input> from the viewer, and ref="fileInput" lets another element reference <input>
  • The <Button> element is a custom component with an onClick prop that triggers the handleRef method

Update the handleRef method Scroll down to your <script> tag and update the handleRef() method with the code below:

<script>
  // do not remove pre-existing code
  export default {
    methods: {
      handleRef() {
        this.$refs.fileInput.click();
      },
    },
  };
</script>
Code language: HTML, XML (xml)

In the code above, you did the following:

  • Checked for a fileInput ref in your project’s list of $refs
  • Listened for the click() method triggered by fileInput

When a user clicks on the <Button> component containing this handleRef() method, it triggers a click() method on the <input /> and allows the user to select an image from their device.

Update the handleChange method In your <script> tag, update the handleChange() method with the code below:

<script>
  // do not remove pre-existing code
  export default {
    methods: {
      handleChange(e) {
        // console.log(e)
        const reader = new FileReader();

        reader.readAsDataURL(e.target.files[0]);

        reader.onload = (onloadEvent) => {
          this.setImage = onloadEvent.target.result;
        };
      },
    },
  };
</script>
Code language: HTML, XML (xml)

In this code, you did the following:

  • Created a reader variable that contains an instance of JavaScript’s FileReader() API
  • The reader reads the image file and returns its data as a base64 encoded string, which is passed to setImage

Due to :src="setImage" in line 11 of your pages/index.vue file, <img> will display the selected image on the browser, ready for upload:

In the <script> tag of your pages/index.vue, update the handleUpload() method with the code below:

<script>
  // do not remove pre-existing code
  export default {
    methods: {
      async handleUpload() {
        this.setUploadStatus = true;

        if (this.setImage !== '') {
          // Upload image to Cloudinary
          const uploadImage = await this.$cloudinary
            .upload(this.setImage, {
              upload_preset: 'imgtosvg',
            })
            .then((res) => res.public_id);
        } else {
          alert('Choose image first!');
        }
      },
    },
  };
</script>
Code language: HTML, XML (xml)

In the code above, you did the following:

  • Set the setUploadStatus state to true, which triggers the loading state of the <Button> component on lines 28 to 34. Note that this <Button> contains an onClick prop to trigger the handleUpload() method
  • Checked if the user selected an image
  • Created a uploadImage variable that uploads your selected image to Cloudinary, with upload_preset as its parameter. Replace the value of upload_preset with yours from Cloudinary
  • The upload method returns an Asset object containing the details of the image you just uploaded. You then returned its public_id, setting it as the value for uploadImage

Generate SVG URL with public_id

Update the handleUpload() method with the code below:

<script>
  // do not remove pre-existing code
  export default {
    methods: {
      async handleUpload() {
        this.setUploadStatus = true

        if (this.setImage !== '') {
          // Upload image to Cloudinary
          const uploadImage = await this.$cloudinary
            .upload(this.setImage, {
              upload_preset: 'your_cloudinary_unsigned_upload_preset_name'
            })
            .then((res) => res.public_id)

          // Convert to SVG
          const url = await this.$cloudinary.image.url(uploadImage, {
            format: 'svg',
            effect: 'vectorize',
          })

          this.setImage = url
      },
    }
  }
</script>
Code language: HTML, XML (xml)

In the code above, you did the following:

  • Generated an image URL from Cloudinary and set its format to svg and its effect to vectorize
  • Updated the value of setImage to url, which will display your converted image in your browser

Extract SVG code from URL

In your terminal, run the command below to install html-formatter:

yarn add html-formatter

Or using npm:

npm install html-formatter

This package lets you display auto-formatted HTML code, making it more readable. In your pages/index.vue, import html-formatter and update the handleUpload() method with the code below:

<script>
  import formatter from 'html-formatter';

  export default {
    methods: {
      async handleUpload() {
        this.setUploadStatus = true;

        if (this.setImage !== '') {
          // Upload image to Cloudinary
          const uploadImage = await this.$cloudinary
            .upload(this.setImage, {
              upload_preset: 'your_cloudinary_unsigned_upload_preset_name',
            })
            .then((res) => res.public_id);

          // Convert to SVG
          const url = await this.$cloudinary.image.url(uploadImage, {
            format: 'svg',
            effect: 'vectorize',
          });

          this.setImage = url;

          // Extract SVG code
          await this.$axios
            .$get(url)
            .then((data) => (this.svgDisplay = formatter.render(data)));
        } else {
          alert('Choose image first!');
        }

        this.setUploadStatus = false;
      },
    },
  };
</script>
Code language: HTML, XML (xml)

In the code above, you did the following:

  • Imported html-formatter as formatter
  • Fetched the SVG image from its URL with $axios, which returns the SVG code as data
  • Updated the value of svgDisplay to the formatted data, displaying it on the browser
  • Disabled the loading state by changing setUploadStatus to false

Here is the result of your code:

Copy SVG code to Clipboard

In your terminal, run the command below to install copy-to-clipboard:

yarn add copy-to-clipboard

Or using npm:

npm install copy-to-clipboard

This package lets you save content to your browser’s clipboard.

In the <script> tag of your pages/index.vue, import copy-to-clipboard and update the copySvg() method with the code below:

<script>
  // do not remove pre-existing code
  import copy from 'copy-to-clipboard';

  export default {
    methods: {
      copySvg() {
        copy(this.svgDisplay);
        this.clipboardStatus = 'Copied!';
        setTimeout(() => {
          this.clipboardStatus = 'Copy to Clipboard';
        }, 2000);
      },
    },
  };
</script>
Code language: HTML, XML (xml)

In the code above, you did the following:

  • Imported the copy-to-clipboard package as copy
  • Saved the current value of svgDisplay to your browser’s clipboard with copy()
  • Changed the text of the clipboard button in line 45 to 'Copied!', and back to 'Copy to Clipboard' two seconds later

In this article, you learned how to convert an image to SVG using Cloudinary, extract its SVG code and display it in a Nuxt.js project using the <pre /> tag. Check out these resources below for a deeper understanding of how Nuxt.js or Cloudinary works.

Back to top

Featured Post