最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3結(jié)合vue-cropper實(shí)現(xiàn)圖片裁剪預(yù)覽功能

 更新時(shí)間:2025年05月23日 08:15:00   作者:小吳3  
??Vue-Cropper?? 是一個(gè)基于 Vue.js 的圖片裁剪組件庫(kù),專為 Web 應(yīng)用設(shè)計(jì),這篇文章主要為大家介紹了如何使用vue-cropper實(shí)現(xiàn)圖片裁剪預(yù)覽功能,需要的可以了解下

一、介紹??

Vue-Cropper?? 是一個(gè)基于 Vue.js 的圖片裁剪組件庫(kù),專為 Web 應(yīng)用設(shè)計(jì)。當(dāng)你在網(wǎng)上搜索的時(shí)候發(fā)現(xiàn)還有一個(gè)叫cropper的庫(kù),下面是他們的區(qū)別:

二、快速上手

//npm 安裝
npm install vue-cropper
//yarn 安裝
yarn add vue-cropper

對(duì)該插件進(jìn)行封裝,使用vue3 + ts

<script lang="ts" setup>
import 'vue-cropper/dist/index.css'
import { VueCropper } from 'vue-cropper'

const emit = defineEmits(['realTime'])
const props = defineProps({
    width: { type: Number, default: 640 },
    height: { type: Number, default: 740 }
})

const options = reactive({
    img: '',
    autoCrop: true,
    autoCropWidth: 640,
    autoCropHeight: 740,
    fillColor: '#fff', // 裁剪框填充顏色
    fixedBox: true //  固定裁剪框
})

const cropperInstance = ref()
const blobData = ref(new Blob())

const init = () => {
    options.img = ''
}

const selectImg = async (e: Event) => {
    const file = (e.target as HTMLInputElement).files?.[0]
    if (!file) return

    const reader = new FileReader()
    reader.onload = async e => {
        const img = new Image()
        img.onload = async () => {
            // 強(qiáng)制放大到最小尺寸
            const canvas = document.createElement('canvas')
            const ctx = canvas.getContext('2d')!

            // 設(shè)置 canvas 尺寸
            canvas.width = img.width
            canvas.height = img.height
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
            options.img = canvas.toDataURL()
            await nextTick()
            // 等待 DOM 更新后設(shè)置裁剪框
            setFixedCropBox()
        }
        img.src = e.target!.result as string
    }
    reader.readAsDataURL(file)
}

const setFixedCropBox = () => {
    if (!cropperInstance.value?.cropper) return

    // 正確訪問(wèn)cropper實(shí)例
    const cropper = cropperInstance.value.cropper

    // 獲取容器真實(shí)尺寸
    const containerWidth = cropper.containerData.width
    const containerHeight = cropper.containerData.height

    // 計(jì)算居中位置
    const left = (containerWidth - props.width) / 2
    const top = (containerHeight - props.height) / 2

    // 正確調(diào)用方法
    cropper.setCropBoxData({
        width: props.width,
        height: props.height,
        left,
        top
    })
}

// 實(shí)時(shí)預(yù)覽
const realTime = (data: any) => {
    emit('realTime', data.html)
}

// 獲取截圖的數(shù)據(jù) getCropBlob => blob數(shù)據(jù)
const tailoring = (): Promise<Blob> => {
    return new Promise((resolve, reject) => {
        if (!cropperInstance.value) {
            reject(new Error('裁剪組件未初始化'))
            return
        }

        cropperInstance.value.getCropBlob((data: Blob) => {
            if (data) {
                blobData.value = data
                resolve(data)
            } else {
                reject(new Error('裁剪失敗,未獲取到 Blob'))
            }
        })
    })
}

// 旋轉(zhuǎn)
const rotateLeft = () => {
    if (!cropperInstance.value) return
    cropperInstance.value.rotateLeft()
}

const rotateRight = () => {
    if (!cropperInstance.value) return
    cropperInstance.value.rotateRight()
}

onMounted(() => {
    if (props.width && props.height) {
        options.autoCropWidth = props.width
        options.autoCropHeight = props.height
    }
})

defineExpose({ options, selectImg, realTime, tailoring, blobData, init, rotateLeft, rotateRight })
</script>

<template>
    <vue-cropper
        ref="cropperInstance"
        :img="options.img"
        :autoCrop="options.autoCrop"
        :autoCropWidth="options.autoCropWidth"
        :autoCropHeight="options.autoCropHeight"
        :fixedBox="options.fixedBox"
        :fillColor="options.fillColor"
        @real-time="realTime"
    />
</template>

父組件進(jìn)行使用

<el-form-item>
            <div class="flex items-center gap-10px">
                <span>公告圖片</span>
                <!-- <el-button size="small" type="primary" class="mx-0" @click="openUpload">
                    <el-icon class="mr-3px"><Upload /></el-icon> 上傳</el-button
                > -->
                <el-button :type="form.backgroundImage ? 'success' : 'primary'" @click="openUpload">
                    <el-icon class="mr-3px"><Upload /></el-icon>
                    {{ form.backgroundImage ? '重新上傳' : '上傳' }}</el-button
                >
                <el-button class="mx-0" type="danger" :icon="Delete" @click="form.backgroundImage = ''"></el-button>
                <div class="text-slate text-xs">建議:寬高640*740,png或jpg/jpeg格式,小于2M</div>
            </div>
            <input type="file" name="" ref="uploadRef" class="hidden" @change="handleCaptureUpload" />
        </el-form-item>

        <!-- 圖片預(yù)覽裁剪 -->
        <el-dialog
            v-model="showCaptureVisible"
            title="圖片預(yù)覽裁剪"
            width="50%"
            @close="closeCapture"
            top="5vh"
            draggable
            destroy-on-close
        >
            <div class="w-full h-78vh mt-10px flex justify-center items-center">
                <Cropper ref="cropper" :height="740" :width="640"></Cropper>
            </div>
            <template #footer>
                <span class="dialog-footer">
                    <el-button :icon="RefreshRight" type="info" @click="handleRotateRight"></el-button>
                    <el-button :icon="RefreshLeft" type="info" @click="handleRotateLeft"></el-button>
                    <el-button type="info" @click="closeCapture">關(guān)閉</el-button>
                    <el-button type="primary" @click="tailoring" :loading="cropperLoading">確定</el-button>
                </span>
            </template>
        </el-dialog>


<script setup lang="ts">
 


const uploadRef = ref()
const showCaptureVisible = ref(false)
const cropper = ref()
// 上傳圖片loading
const { loading: cropperLoading } = useLoading()
// 裁剪圖片
const tailoring = async () => {
    //文件大小
    cropperLoading.value = true
    const blob = await cropper.value.tailoring()
    if (blob.size > 2 * 1024 * 1024) {
        cropperLoading.value = false
        warningMessage('圖片大小超出2M限制')
        return
    }

    const formData = new FormData()
    formData.append('file', blob, 'cropped.jpg')
    formData.append('accountId', regionSelect.brandId as string)
    uploadImage(formData) // 這里調(diào)用后臺(tái)api
        .then(
            async res => {
                form.value.backgroundImage = res.data
                doSuccess('上傳成功')
            },
            () => {
                ElNotification({
                    type: 'warning',
                    message: '圖片上傳失敗'
                })
            }
        )
        .finally(() => {
            formRef.value?.validate().catch(() => {})
            // 關(guān)閉裁剪
            showCaptureVisible.value = false
            cropperLoading.value = false
        })
}


// 圖片旋轉(zhuǎn)
const handleRotateLeft = () => {
    cropper.value?.rotateLeft()
}


const handleRotateRight = () => {
    cropper.value?.rotateRight()
}
// 上傳圖片
const handleCaptureUpload = (e: any) => {
    const input = e.target as HTMLInputElement
    if (!/\.(jpg|jpeg|png|JPG|PNG)$/.test(e.target.value)) {
        warningMessage('圖片類型要求:jpeg、jpg、png')
        return false
    }
    showCaptureVisible.value = true
    nextTick(() => {
        cropper.value?.selectImg(e)
        input.value = ''
    })
}
// 關(guān)閉裁剪
const closeCapture = () => {
    showCaptureVisible.value = false
}




</script>

三、實(shí)現(xiàn)效果

效果圖:

可進(jìn)行圖片旋轉(zhuǎn),裁剪 自定義裁剪的圖片大小

四、vue-cropper的全部參數(shù)

到此這篇關(guān)于Vue3結(jié)合vue-cropper實(shí)現(xiàn)圖片裁剪預(yù)覽功能的文章就介紹到這了,更多相關(guān)vue-cropper圖片裁剪預(yù)覽內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • html中引入Vue.js的cdn實(shí)現(xiàn)簡(jiǎn)單的文檔單頁(yè)

    html中引入Vue.js的cdn實(shí)現(xiàn)簡(jiǎn)單的文檔單頁(yè)

    這篇文章主要為大家介紹了html中引入Vue.js的cdn實(shí)現(xiàn)簡(jiǎn)單的文檔單頁(yè)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • vue3+vite3+typescript實(shí)現(xiàn)驗(yàn)證碼功能及表單驗(yàn)證效果

    vue3+vite3+typescript實(shí)現(xiàn)驗(yàn)證碼功能及表單驗(yàn)證效果

    這篇文章主要介紹了vue3+vite3+typescript實(shí)現(xiàn)驗(yàn)證碼功能及表單驗(yàn)證效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-04-04
  • vue.js實(shí)現(xiàn)備忘錄功能的方法

    vue.js實(shí)現(xiàn)備忘錄功能的方法

    下面小編就為大家?guī)?lái)一篇vue.js實(shí)現(xiàn)備忘錄功能的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • vue3如何加載本地圖片等靜態(tài)資源淺析

    vue3如何加載本地圖片等靜態(tài)資源淺析

    在最近新起的項(xiàng)目中,用到了較新的技術(shù)棧vue3.2+vite+ts,跟著網(wǎng)上的寫(xiě)法漸漸上手了,下面這篇文章主要給大家介紹了關(guān)于vue3如何加載本地圖片等靜態(tài)資源的相關(guān)資料,需要的朋友可以參考下
    2023-04-04
  • Vue中router-link如何添加mouseover提示

    Vue中router-link如何添加mouseover提示

    這篇文章主要介紹了Vue中router-link如何添加mouseover提示,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • el-form表單el-form-item驗(yàn)證規(guī)則里prop一次驗(yàn)證兩個(gè)或多個(gè)值問(wèn)題

    el-form表單el-form-item驗(yàn)證規(guī)則里prop一次驗(yàn)證兩個(gè)或多個(gè)值問(wèn)題

    這篇文章主要介紹了el-form表單el-form-item驗(yàn)證規(guī)則里prop一次驗(yàn)證兩個(gè)或多個(gè)值問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Vue3 + TypeScript 開(kāi)發(fā)總結(jié)

    Vue3 + TypeScript 開(kāi)發(fā)總結(jié)

    本文直接上 Vue3 + TypeScript + Element Plus 開(kāi)發(fā)的內(nèi)容,感興趣的話一起來(lái)看看吧
    2021-08-08
  • Vue Echarts實(shí)現(xiàn)可視化世界地圖代碼實(shí)例

    Vue Echarts實(shí)現(xiàn)可視化世界地圖代碼實(shí)例

    這篇文章主要介紹了Vue Echarts實(shí)現(xiàn)可視化世界地圖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Vue2.0設(shè)置全局樣式(less/sass和css)

    Vue2.0設(shè)置全局樣式(less/sass和css)

    這篇文章主要為大家詳細(xì)介紹了Vue2.0設(shè)置全局樣式(less/sass和css),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 使用Pinia Persistedstate插件實(shí)現(xiàn)狀態(tài)持久化的操作方法

    使用Pinia Persistedstate插件實(shí)現(xiàn)狀態(tài)持久化的操作方法

    Pinia 作為 Vue 的新一代狀態(tài)管理工具,以其輕量化和易用性受到開(kāi)發(fā)者的喜愛(ài),然而,Pinia 默認(rèn)使用內(nèi)存存儲(chǔ)狀態(tài),為了解決這個(gè)問(wèn)題,我們可以借助 Pinia Persistedstate 插件來(lái)實(shí)現(xiàn)狀態(tài)的持久化存儲(chǔ),本文將詳細(xì)介紹該插件的使用方法,需要的朋友可以參考下
    2024-11-11

最新評(píng)論

汉中市| 游戏| 台江县| 伊吾县| 沭阳县| 莱州市| 冕宁县| 霍林郭勒市| 舒城县| 神木县| 成安县| 东城区| 石林| 礼泉县| 永靖县| 漾濞| 中卫市| 资兴市| 鹰潭市| 九江县| 阿城市| 康平县| 博客| 沙坪坝区| 崇阳县| 胶南市| 永和县| 雅江县| 盘山县| 伊宁县| 兖州市| 枣庄市| 会泽县| 南京市| 邻水| 东山县| 广西| 都匀市| 达尔| 无棣县| 册亨县|