国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

vue3+vant+cropper.js實(shí)現(xiàn)移動(dòng)端圖片裁剪功能

這篇具有很好參考價(jià)值的文章主要介紹了vue3+vant+cropper.js實(shí)現(xiàn)移動(dòng)端圖片裁剪功能。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

一、前言

最近做項(xiàng)目中遇到一個(gè)需求,需要對(duì)海報(bào)圖片按照一定的比例進(jìn)行裁剪并上傳到oss。一開(kāi)始這個(gè)需求思路有兩個(gè),使用canvas原生或者尋找現(xiàn)成的第三方庫(kù),對(duì)比了一番覺(jué)得canvas實(shí)現(xiàn)時(shí)間耗費(fèi)較長(zhǎng),且秉承著不重復(fù)造輪子的原則(其實(shí)是菜)。

在進(jìn)行技術(shù)調(diào)研后,決定使用vue-cropper插件來(lái)實(shí)現(xiàn),預(yù)想會(huì)順利,可結(jié)果恰恰相反!安裝vue-cropper設(shè)置參數(shù)封裝完組件后,發(fā)現(xiàn)裁剪框和裁剪的圖片在h5頁(yè)面上不能拖動(dòng),在web頁(yè)面上可以,看源碼里面也有兼容移動(dòng)端的方法代碼,在github上的issue里面也沒(méi)發(fā)現(xiàn)有人遇到相同問(wèn)題,難道就我遇到了?問(wèn)度娘發(fā)現(xiàn)大家都可以,為什么我的就不行呢?后來(lái)又使用了vue-cropper-h5,也存在各種問(wèn)題。其實(shí),vue-cropper、vue-cropper-h5、vue-cropperjs等插件都是基于cropper.js實(shí)現(xiàn)的,最終決定使用cropper.js去實(shí)現(xiàn)。官方封裝了很多參數(shù)、方法、事件,上手容易,文檔閱讀體驗(yàn)較好、而且便于擴(kuò)展。下面就來(lái)詳細(xì)介紹一個(gè)cropper.js的詳細(xì)用法吧!

cropper.js可以對(duì)指定的圖片進(jìn)行裁剪,可以自己選擇裁剪的交互方式,如大小、縱橫比等,裁剪后可以生成一個(gè)包含裁剪圖的canvas對(duì)象,借助canvas的toDataURL方法可以生成一張Base64格式的圖片,再通過(guò)toBlob轉(zhuǎn)換成blob類型文件,再通過(guò)new File(),轉(zhuǎn)換成file文件上傳,當(dāng)然也可以直接上傳裁剪后生成的base64。還有另外一種不使用canvas的方式,利用該工具豐富的api可以拿到裁剪區(qū)域相對(duì)于原圖的各項(xiàng)數(shù)據(jù),使用這些數(shù)據(jù)進(jìn)行css絕對(duì)定位即可展示裁剪后的圖,該方式可以保證圖片不失真和完整。

二、項(xiàng)目環(huán)境

1.node

v16.0.0

2.vue

"vue": "^3.2.45"

3.vant

"vant": "^4.0.2"

4.cropper.js

"cropperjs": "^1.5.13"

三、使用

1.安裝

yarn add cropperjs

2.引入,要導(dǎo)入樣式,不然不會(huì)生效

import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'

3.模板

<div class="v-simple-cropper">
    <van-uploader
      :after-read="afterRead"
    >
      <template #default>
        <img v-if="imgUrl" class="upload-img" :src="imgUrl" alt="">
        <div v-else class="upload-area" />
      </template>
    </van-uploader>
    <div v-show="showlayer" class="v-cropper-layer">
      <van-row class="layer-header" :gutter="36">
        <van-col :span="8">
          <van-button type="danger" plain block size="small" @click="cancelHandle">
            取消
          </van-button>
        </van-col>
        <van-col :span="8">
          <van-button type="success" block size="small" @click="rotateHandle">
            旋轉(zhuǎn)
          </van-button>
        </van-col>
        <van-col :span="8">
          <van-button type="primary" block size="small" @click="confirmHandle">
            裁剪并上傳
          </van-button>
        </van-col>
      </van-row>
      <img ref="cropperImg">
    </div>
  </div>
</template>

4.js

<script setup lang="ts">
import Cropper from 'cropperjs'
import 'cropperjs/dist/cropper.min.css'
import { onMounted, ref, watch } from 'vue'
import { closeToast, showFailToast, showLoadingToast, showToast } from 'vant'
import { useRequest } from 'vue-request'
import { fileUpload } from '@/api/basic/index'

const props = defineProps({
  url: {
    type: String,
    default: '',
  },
  width: {
    type: Number,
  },
  height: {
    type: Number,
  },
  scale: {
    type: Number,
    default: 0.8
  }
})
const emit = defineEmits(['update:url'])

const cropperImg = ref<any>(null)
const cropper = ref<any>(null)
const showlayer = ref(false)
const imgUrl = ref(props.url)

watch(() => props.url, (val) => {
  if (val)
    imgUrl.value = val
})

function init() {
  cropper.value = new Cropper(cropperImg.value, {
    viewMode: 1,
    // 根據(jù)所需圖片寬高,計(jì)算比例
    aspectRatio: props.width && props.height ? (Number(props.width) / Number(props.height)) : 1 / 0.618,
    dragMode: 'move',
    cropBoxResizable: false,
    autoCropArea: 1,
  })
}
// 選擇圖片
function afterRead(file) {
  // 判斷擴(kuò)展名
  const tmpCnt = file.file.name.lastIndexOf('.')
  const exName = file.file.name.substring(tmpCnt + 1)
  const names = ['jpg', 'jpeg', 'png']
  if (!names.includes(exName)) {
    showToast('不支持的格式!')
    return
  }

  const URL = window.URL || window.webkitURL
  const binaryData = []
  binaryData.push(file.file)
  cropper.value.replace(URL.createObjectURL(new Blob(binaryData)))
  showlayer.value = true
}

// 旋轉(zhuǎn)
function rotateHandle() {
  cropper.value.rotate(90)
}
function cancelHandle() {
  cropper.value.reset()
  showlayer.value = false
}
// 上傳方法
const { run: runUplaod } = useRequest(fileUpload, {
  manual: true,
  onSuccess: (res) => {
    closeToast()
    imgUrl.value = res.imgUrl
    emit('update:url', res.imgUrl)
  },
  onError: (err) => {
    closeToast()
    showFailToast(err.message)
  },
})
// 裁剪并上傳
function confirmHandle() {
  const cropBox = cropper.value.getCropBoxData();
  const scale = props.scale || 1;
  cropper.value.getCroppedCanvas({
    width: cropBox.width * scale,
    height: cropBox.height * scale,
  })
  // 把裁剪的圖片轉(zhuǎn)換成blob類型文件,在通過(guò)new File(),轉(zhuǎn)換成file文件
    .toBlob(async (blob) => {
    // 重置file的name,以時(shí)間戳作為文件名
      const timeString = new Date().getTime()
      const imgFile = new File([blob], `${timeString}.jpg`, {
        type: 'image/jepg',
      })
      showlayer.value = false
      showLoadingToast({
        message: '上傳中...',
        duration: 0,
        forbidClick: true,
      })
      runUplaod(imgFile)
    })
}

onMounted(() => {
  init()
})
</script>

5.style

<style lang="less" scoped>
.v-simple-cropper {
  text-align: center;
  padding-top: 10px;
  .upload-area {
    width: 190px;
    height: 120px;
    background: url('@/assets/bg-upload-box.png');
    background-size: 100% 100%;
  }
  .upload-img {
    width: 190px;
    height: 120px;
  }
  /deep/.van-uploader__upload {
    margin: 0 !important;
  }
  .v-cropper-layer {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: #fff;
    z-index: 200;
    .layer-header {
      position: absolute;
      bottom: 0;
      left: 0;
      z-index: 200;
      width: 100%;
      padding: 0 16px 12px;
      box-sizing: border-box;
    }
    img {
      position: inherit !important;
      border-radius: inherit !important;
      float: inherit !important;
    }
  }
}
</style>

在上面的代碼中,我們使用了cropperjs組件來(lái)實(shí)現(xiàn)圖片裁剪功能。在afterRead方法中,我們獲取用戶上傳的圖片,并將其轉(zhuǎn)換為URL對(duì)象。在confirmHandle方法中,我們使用getCroppedCanvas方法獲取裁剪后的canvas對(duì)象,并使用toBlob方法將其轉(zhuǎn)換為Blob對(duì)象,最后將其轉(zhuǎn)換為File對(duì)象并上傳oss,返回一個(gè)oss url。

四、其他

1.預(yù)覽功能

上面創(chuàng)建cropper的時(shí)候,我們可以在選項(xiàng)中添加了如下代碼實(shí)現(xiàn)預(yù)覽功能。

preview:[
   document.querySelector('.previewBox'), 
   document.querySelector('.previewBoxRound')
]

preview就是用來(lái)設(shè)置我們需要實(shí)時(shí)預(yù)覽的地方,但是設(shè)置完成之后要給上述的兩個(gè)div添加一下樣式,才可以正常顯示。

.previewBox {
    box-shadow: 0 0 5px #adadad;
    width: 100px;
    height: 100px;
    margin-top: 30px;
     /*這個(gè)超出設(shè)置為隱藏很重要,否則就會(huì)整個(gè)顯示出來(lái)了*/
    overflow: hidden;      
}

2. 官方文檔

(1)官網(wǎng)示例

https://fengyuanchen.github.io/cropper/

(2)官方github文檔

https://github.com/fengyuanchen/cropperjs

(3)npm官方網(wǎng)站

https://www.npmjs.com/package/cropper文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-789846.html

到了這里,關(guān)于vue3+vant+cropper.js實(shí)現(xiàn)移動(dòng)端圖片裁剪功能的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包