Vue Usage Examples

Learn how to use the HTML to Image API in your Vue applications. These examples use Vue 3 with the Composition API.

Basic Component Example

Here’s a Vue component that generates images from HTML:

<template>
  <div>
    <button 
      @click="generateImage"
      :disabled="loading"
    >
      {{ loading ? 'Generating...' : 'Generate Image' }}
    </button>
    
    <div v-if="error" class="error">
      Error: {{ error }}
    </div>
    
    <div v-if="imageUrl">
      <img 
        :src="imageUrl" 
        alt="Generated content"
        class="generated-image"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue';

const imageUrl = ref(null);
const loading = ref(false);
const error = ref(null);

const generateImage = async () => {
  loading.value = true;
  error.value = null;
  
  try {
    const response = await fetch('https://app.html2img.com/api/html', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': import.meta.env.VITE_HTML2IMG_API_KEY
      },
      body: JSON.stringify({
        html: `
          <div style="padding: 20px; background: #f0f0f0;">
            <h1>Hello from Vue!</h1>
            <p>Generated at ${new Date().toLocaleString()}</p>
          </div>
        `,
        width: 800,
        height: 600
      })
    });

    if (!response.ok) {
      throw new Error('Failed to generate image');
    }

    const blob = await response.blob();
    imageUrl.value = URL.createObjectURL(blob);
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
};

// Clean up object URL when component is unmounted
onUnmounted(() => {
  if (imageUrl.value) {
    URL.revokeObjectURL(imageUrl.value);
  }
});
</script>

<style scoped>
.error {
  color: red;
  margin: 1rem 0;
}

.generated-image {
  max-width: 100%;
  margin-top: 1rem;
}
</style>

Screenshot Component

Here’s a component for taking screenshots:

<template>
  <div>
    <div class="input-group">
      <input
        v-model="url"
        type="text"
        placeholder="Enter URL"
        class="url-input"
      />
    </div>
    
    <button 
      @click="takeScreenshot"
      :disabled="loading"
      class="screenshot-button"
    >
      {{ loading ? 'Taking Screenshot...' : 'Take Screenshot' }}
    </button>
    
    <div v-if="error" class="error">
      Error: {{ error }}
    </div>
    
    <div v-if="imageUrl" class="image-container">
      <img 
        :src="imageUrl" 
        alt="Screenshot"
        class="screenshot-image"
      />
    </div>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from 'vue';

const url = ref('https://example.com');
const imageUrl = ref(null);
const loading = ref(false);
const error = ref(null);

const takeScreenshot = async () => {
  loading.value = true;
  error.value = null;
  
  try {
    const response = await fetch('https://app.html2img.com/api/screenshot', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-API-Key': import.meta.env.VITE_HTML2IMG_API_KEY
      },
      body: JSON.stringify({
        url: url.value,
        width: 1200,
        height: 800,
        dpi: 2,
        fullpage: true
      })
    });

    if (!response.ok) {
      throw new Error('Failed to take screenshot');
    }

    const blob = await response.blob();
    imageUrl.value = URL.createObjectURL(blob);
  } catch (err) {
    error.value = err.message;
  } finally {
    loading.value = false;
  }
};

onUnmounted(() => {
  if (imageUrl.value) {
    URL.revokeObjectURL(imageUrl.value);
  }
});
</script>

<style scoped>
.input-group {
  margin-bottom: 1rem;
}

.url-input {
  width: 100%;
  padding: 0.5rem;
  border: 1px solid #ccc;
  border-radius: 4px;
}

.screenshot-button {
  margin-bottom: 1rem;
}

.error {
  color: red;
  margin: 1rem 0;
}

.image-container {
  margin-top: 1rem;
}

.screenshot-image {
  max-width: 100%;
  border: 1px solid #eee;
  border-radius: 4px;
}
</style>

Composable Example

Here’s a composable function to reuse the image generation logic:

// useHtml2Img.js
import { ref } from 'vue';

export function useHtml2Img() {
  const loading = ref(false);
  const error = ref(null);

  const generateImage = async (html, options = {}) => {
    loading.value = true;
    error.value = null;
    
    try {
      const response = await fetch('https://app.html2img.com/api/html', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-API-Key': import.meta.env.VITE_HTML2IMG_API_KEY
        },
        body: JSON.stringify({
          html,
          width: options.width || 800,
          height: options.height || 600,
          ...options
        })
      });

      if (!response.ok) {
        throw new Error('Failed to generate image');
      }

      const blob = await response.blob();
      return URL.createObjectURL(blob);
    } catch (err) {
      error.value = err.message;
      throw err;
    } finally {
      loading.value = false;
    }
  };

  return {
    generateImage,
    loading,
    error
  };
}

// Usage Example
<template>
  <div>
    <button 
      @click="handleGenerate"
      :disabled="loading"
    >
      Generate Image
    </button>
    
    <div v-if="error" class="error">
      Error: {{ error }}
    </div>
    
    <div v-if="imageUrl">
      <img :src="imageUrl" alt="Generated content" />
    </div>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from 'vue';
import { useHtml2Img } from './useHtml2Img';

const { generateImage, loading, error } = useHtml2Img();
const imageUrl = ref(null);

const handleGenerate = async () => {
  try {
    imageUrl.value = await generateImage(`
      <div style="padding: 20px; background: #f0f0f0;">
        <h1>Hello from Composable!</h1>
        <p>Generated at ${new Date().toLocaleString()}</p>
      </div>
    `);
  } catch (err) {
    console.error('Failed to generate image:', err);
  }
};

onUnmounted(() => {
  if (imageUrl.value) {
    URL.revokeObjectURL(imageUrl.value);
  }
});
</script>

Environment Setup

Create a .env file in your project root:

VITE_HTML2IMG_API_KEY=your-api-key

Access the environment variable in your components:

const apiKey = import.meta.env.VITE_HTML2IMG_API_KEY;

Never expose your API key in client-side code. Use environment variables and consider proxying requests through your backend.

These examples use the Composition API with <script setup>, which is the recommended approach for Vue 3. If you’re using Vue 2, you’ll need to adapt the code to use the Options API or the Composition API with Vue 2.7+.