{"id":12446,"library":"vue-cropper","title":"Vue Cropper","description":"Vue Cropper is a lightweight and easy-to-integrate image cropping component designed for Vue.js applications. The current stable version, `1.1.1`, offers comprehensive support for both Vue 2 and Vue 3, allowing developers to implement image clipping functionalities across different project generations. It is primarily distributed via npm and follows an active, though somewhat irregular, release cadence, with updates primarily focusing on compatibility and bug fixes. Key differentiators include its straightforward API for image selection, scaling, rotation, and data extraction (base64 or blob), making it a popular choice for user profile picture uploads, content creation tools, and other scenarios requiring precise image manipulation directly within the browser. Its minimalist design aims to provide essential cropping features without excessive overhead, integrating seamlessly into existing Vue ecosystems.","status":"active","version":"0.6.5","language":"javascript","source_language":"en","source_url":"https://github.com/xyxiao001/vue-cropper","tags":["javascript","vue","cropper","vue-cropper","vue-component","vue-cropper-component"],"install":[{"cmd":"npm install vue-cropper","lang":"bash","label":"npm"},{"cmd":"yarn add vue-cropper","lang":"bash","label":"yarn"},{"cmd":"pnpm add vue-cropper","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for runtime Vue integration.","package":"vue","optional":false}],"imports":[{"note":"Standard ESM default import for the Vue component. Used for global registration (`Vue.use(VueCropper)` or `app.use(VueCropper)`) and local component registration.","wrong":"const VueCropper = require('vue-cropper');","symbol":"VueCropper","correct":"import VueCropper from 'vue-cropper';"},{"note":"ESM named import for the component. This syntax also works due to dual exports (`default` and named `VueCropper`) provided by the library, offering an alternative to the default import style.","wrong":"import Cropper from 'vue-cropper';","symbol":"VueCropper (named)","correct":"import { VueCropper } from 'vue-cropper';"},{"note":"While `vue-cropper` itself does not export specific types for its instance, developers commonly use `InstanceType<typeof VueCropper>` from Vue's core for robust TypeScript typing of component refs, allowing access to methods like `getCropData`.","wrong":"import type { InstanceType } from 'vue-cropper';","symbol":"InstanceType (for refs)","correct":"import type { InstanceType } from 'vue';"}],"quickstart":{"code":"<template>\n  <div class=\"cropper-container\">\n    <input type=\"file\" accept=\"image/*\" @change=\"handleFileChange\" />\n    <div class=\"cropper-wrapper\" v-if=\"imgSrc\">\n      <VueCropper\n        ref=\"cropperRef\"\n        :img=\"imgSrc\"\n        :output-size=\"outputSize\"\n        :output-type=\"outputType\"\n        :info=\"true\"\n        :full=\"true\"\n        :fixed-box=\"false\"\n        :can-move=\"true\"\n        :can-move-box=\"true\"\n        :original=\"false\"\n        :auto-crop=\"true\"\n        :auto-crop-width=\"200\"\n        :auto-crop-height=\"150\"\n        @realTime=\"realTimePreview\"\n      ></VueCropper>\n    </div>\n    <button @click=\"cropImage\" v-if=\"imgSrc\">Crop Image</button>\n    <div class=\"preview\" v-if=\"previewImg\">\n      <h3>Preview:</h3>\n      <img :src=\"previewImg\" alt=\"Cropped Image Preview\" />\n    </div>\n  </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue';\nimport VueCropper from 'vue-cropper';\nimport 'vue-cropper/dist/index.css'; // Don't forget to import the CSS\n\n// Define the type for the VueCropper instance\ninterface VueCropperInstance {\n  getCropData: (callback: (data: string) => void) => void;\n  getCropBlob: (callback: (blob: Blob) => void) => void;\n  // Add other methods if you plan to use them, e.g., setCropBoxData, zoom\n}\n\nconst cropperRef = ref<VueCropperInstance | null>(null);\nconst imgSrc = ref<string | null>(null);\nconst previewImg = ref<string | null>(null);\nconst outputSize = ref(1); // Output image quality (0 to 1)\nconst outputType = ref('jpeg'); // Output image format (jpeg, png, webp)\n\nconst handleFileChange = (e: Event) => {\n  const file = (e.target as HTMLInputElement).files?.[0];\n  if (file) {\n    const reader = new FileReader();\n    reader.onload = (event) => {\n      imgSrc.value = event.target?.result as string;\n    };\n    reader.readAsDataURL(file);\n  }\n};\n\nconst cropImage = () => {\n  if (cropperRef.value) {\n    cropperRef.value.getCropData((data: string) => {\n      previewImg.value = data;\n      console.log('Cropped Base64:', data.substring(0, 50) + '...');\n      // For uploading blob:\n      // cropperRef.value?.getCropBlob((blob: Blob) => {\n      //   console.log('Cropped Blob:', blob);\n      //   // You can upload the blob to your server here\n      // });\n    });\n  }\n};\n\nconst realTimePreview = (data: { img: string }) => {\n  // Optional: Update a smaller preview in real-time as the user crops\n  // For this quickstart, we'll just show the final crop on button click.\n  // If you want a live preview, you can set previewImg.value = data.img here.\n};\n\n// Watch for changes in imgSrc to reset preview when a new image is selected\nwatch(imgSrc, () => {\n  previewImg.value = null;\n});\n</script>\n\n<style scoped>\n.cropper-container {\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  gap: 20px;\n  padding: 20px;\n  border: 1px solid #eee;\n  border-radius: 8px;\n  max-width: 600px;\n  margin: 20px auto;\n  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);\n}\n.cropper-wrapper {\n  width: 100%;\n  max-width: 500px;\n  height: 300px;\n  background-color: #f8f8f8;\n  border: 1px dashed #ccc;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n}\n.preview {\n  margin-top: 20px;\n  text-align: center;\n}\n.preview img {\n  max-width: 100%;\n  height: auto;\n  border: 1px solid #ddd;\n  border-radius: 4px;\n}\ninput[type=\"file\"] {\n  padding: 10px;\n  border: 1px solid #ccc;\n  border-radius: 4px;\n  cursor: pointer;\n}\nbutton {\n  background-color: #42b983;\n  color: white;\n  border: none;\n  padding: 10px 20px;\n  border-radius: 4px;\n  cursor: pointer;\n  font-size: 16px;\n  transition: background-color 0.2s ease;\n}\nbutton:hover {\n  background-color: #368a6f;\n}\n</style>\n","lang":"typescript","description":"Demonstrates basic image loading, displaying the cropper, allowing the user to select a crop area, and extracting the cropped image as a Base64 string for preview or upload, using Vue 3 Composition API with TypeScript. It also includes the necessary CSS import."},"warnings":[{"fix":"Refer to the official GitHub repository's `README` for `1.x` usage examples. For Vue 3, prefer `app.use(VueCropper)` for global registration or local component import. Ensure you are using the correct build for your Vue version if manual configuration is needed.","message":"The `vue-cropper` package underwent significant changes between `0.x` and `1.x` to introduce native support for Vue 3. While `0.x` was primarily for Vue 2, `1.x` is compatible with both Vue 2 and Vue 3. Migration from `0.x` to `1.x` may involve adjusting component registration methods and prop names, although the core API remains similar.","severity":"breaking","affected_versions":"<1.0.0"},{"fix":"Ensure the image server sends appropriate `Access-Control-Allow-Origin` headers (e.g., `Access-Control-Allow-Origin: *` or specific origin). Alternatively, proxy the images through your own backend or consider server-side cropping.","message":"When attempting to crop images loaded from a different origin (domain, port, or protocol), browsers enforce Cross-Origin Resource Sharing (CORS) policies. This can prevent the `vue-cropper` component from accessing image data on the canvas, leading to errors like 'Tainted canvases cannot be exported' or 'Image load failed'.","severity":"gotcha","affected_versions":">=0.6.5"},{"fix":"Always include `import 'vue-cropper/dist/index.css';` in your main application entry file or directly within the component where `VueCropper` is used.","message":"Forgetting to import the component's CSS styles (`import 'vue-cropper/dist/index.css';`) is a common mistake, leading to a non-functional or unstyled cropper component.","severity":"gotcha","affected_versions":">=0.6.5"},{"fix":"Pre-process large images on the server-side to a reasonable resolution before sending them to the client. Implement client-side image resizing before passing them to the cropper if server-side processing is not an option. Optimize `output-size` and `output-type` props for performance.","message":"Handling large images, especially on less powerful devices or older browsers, can lead to performance issues, browser crashes, or slow responsiveness during cropping operations. The underlying `cropperjs` library may struggle with extremely high-resolution images.","severity":"gotcha","affected_versions":">=0.6.5"},{"fix":"Adopt Vue 3's Composition API for component communication (e.g., `emit`, `provide`/`inject`, event bus libraries) and leverage component references (refs) for direct interaction where appropriate. Use standard JavaScript string manipulation instead of Vue filters.","message":"Older global API methods like `$on`, `$off`, `$once`, `$children`, and `filters` were removed in Vue 3. Applications migrating from Vue 2 to Vue 3 that heavily relied on these global methods for event communication or direct child component access will need refactoring.","severity":"deprecated","affected_versions":"<3.0.0 (Vue core), `vue-cropper` versions primarily for Vue 2"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"For Vue 3, use `app.use(VueCropper)` where `app` is your Vue application instance (e.g., `const app = createApp(App); app.use(VueCropper); app.mount('#app');`). For Vue 2, ensure `import Vue from 'vue';` and then `Vue.use(VueCropper);`.","cause":"Attempting to globally register the VueCropper plugin in a Vue 3 application using the Vue 2 `Vue.use()` syntax, or `Vue` is not correctly imported/defined.","error":"Cannot read properties of undefined (reading 'use')"},{"fix":"Configure the server hosting the image to send `Access-Control-Allow-Origin` headers. For development, you might use a browser extension to disable CORS, but this is not a production solution. Alternatively, load images via a proxy on the same origin as your application.","cause":"This error occurs when `vue-cropper` tries to extract image data (e.g., `getCropData`, `getCropBlob`) from a canvas that contains content loaded from a different origin without proper CORS headers.","error":"Tainted canvases cannot be exported"},{"fix":"Ensure the ref is correctly typed as the `VueCropper` component instance. For example, `const cropperRef = ref<InstanceType<typeof VueCropper> | null>(null);` or define an interface for the component's methods as shown in the quickstart. Also, ensure the component is mounted before trying to access its methods.","cause":"This TypeScript error typically arises when using `ref` to reference the `VueCropper` component in a Vue 3 `<script setup>` block, but the ref's type is not correctly specified, or the component instance isn't available yet.","error":"Property 'getCropData' does not exist on type 'Vue | Element | ...'"}],"ecosystem":"npm"}