我正在使用来自cropperjs的vue-cropper 4.1和Nuxt 2.13。当我的裁剪器加载时它显示一个占位符,在选择图像并上传后,裁剪器仍然显示选择的图像,但我想再次加载占位符。我该怎么办?我试过替换()但没有奏效。这是我的代码:
注意:我的代码中有一些this
你可能找不到参考。它们通过 mixins 全局添加到我的项目中。并且 editProduct 是我的 vuex 中的一个状态,它被全局添加,与其操作相同。
<template>
<div class="pt-6">
<v-row class="ma-0">
<v-col cols="12" sm="12" md="5" class="pa-0" >
<v-card flat class="pb-4" max-width="450px">
<client-only>
<vue-cropper
ref="cropper"
:aspect-ratio="1/1"
:src="url"
dragMode="move"
/>
</client-only>
<v-card flat class="d-flex justify-center theme__main__color my-2">
<v-btn text icon class="mx-1 text_main_color" @click.prevent="rotate(-45)">
<v-icon>mdi-rotate-left</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" ref="flipX" @click.prevent="flipX">
<v-icon>mdi-flip-horizontal</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" @click.prevent="reset">
<v-icon>mdi-border-all-variant</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" ref="flipY" @click.prevent="flipY">
<v-icon>mdi-flip-vertical</v-icon>
</v-btn>
<v-btn text icon class="mx-1 text_main_color" @click.prevent="rotate(45)">
<v-icon>mdi-rotate-right</v-icon>
</v-btn>
<a style="display:none;" ref="flipX" href="#" @click.prevent="flipX"></a>
<a style="display:none;" ref="flipY" href="#" @click.prevent="flipY"></a>
</v-card>
<v-list container inline class="transparent text-center pa-0">
<v-list-item class="px-0">
<v-list-item class="px-1">
<v-btn
width="100%"
class="theme__btn__w text_main_color"
:loading="isSelecting"
@click="onChooseClick"
>{{lang.chooseimage}}</v-btn>
</v-list-item>
<v-list-item class="px-1">
<v-btn
width="100%"
class="theme__btn__s text_main_color"
@click.prevent="uploadImage"
:disabled="isUploading || !selectedFile"
>{{lang.upload}}</v-btn>
<input
ref="uploader"
class="d-none"
type="file"
accept="image/*"
@change="onFileChanged"
>
</v-list-item>
</v-list-item>
</v-list>
</v-card>
</v-col>
<v-col cols="12" sm="12" md="7" class="pa-0" v-if="storedImg">
<v-row class="ma-0">
<!-- img 1 -->
<v-col cols="12" sm="6" md="4" class="pa-1 mb-4" v-for="(image, index) in storedImg" :key="index">
<v-card flat>
<div tile class="rounded-r felx float-right text_main_color theme__btn__p pa-1" height="100%">
<div><v-icon class="text_main_color" medium>mdi-sort-variant</v-icon></div>
<div><span class="my-1 productlist__btn__sort">Hold to order</span></div>
</div>
<v-img class="theme__main__color rounded-l" max-width="141" :src="imagePathCreator(image.url)"></v-img>
<v-btn text class="theme__cta__color text_main_color mt-2" min-width="141" @click.prevent="deleteImg(index, image.id)">{{lang.delete}}</v-btn>
</v-card>
</v-col>
</v-row>
</v-col>
<!-- btn -->
<addproductbtn :section="section" />
</v-row>
</div>
</template>
<style>
</style>
<script>
import addproductbtn from '~/components/global/cms/addproductbtn'
import {ALERT_TYPE, ALERT_METHOD} from '~/plugins/constants.js'
import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css';
export default {
components:{
VueCropper,
'addproductbtn': addproductbtn
},
props:['err'],
data(){
return{
isSelecting: false,
selectedFile: null,
url: null,
placeholder: '/images/placeholder/place-800.png',
section: 'img',
pImages: [],
pId: null,
cropData: null,
isUploading: false
}
},
computed:{
storedImg(){
return this.editProduct.images
}
},
methods:{
// ***** Cropper Methods ***** \\
flipX() {
const dom = this.$refs.flipX;
let scale = dom.getAttribute('data-scale');
scale = scale ? -scale : -1;
this.$refs.cropper.scaleX(scale);
dom.setAttribute('data-scale', scale);
},
flipY() {
const dom = this.$refs.flipY;
let scale = dom.getAttribute('data-scale');
scale = scale ? -scale : -1;
this.$refs.cropper.scaleY(scale);
dom.setAttribute('data-scale', scale);
},
reset() {
this.$refs.cropper.reset();
},
rotate(deg) {
this.$refs.cropper.rotate(deg);
},
getData(){
this.cropData = this.$refs.cropper.getData(true);
},
// ***** Component Methods ***** \\
onChooseClick(){
this.isSelecting = true
window.addEventListener('focus', () => {
this.isSelecting = false
}, { once: true })
this.$refs.uploader.click()
},
onFileChanged(e) {
// **** CROPPER CHOOSE FILE **** //
this.selectedFile = e.target.files[0];
if (this.selectedFile.type.indexOf('image/') === -1) {
this.noty(ALERT_TYPE[0],lang.errimagefile);
return;
}
if (typeof FileReader === 'function') {
const reader = new FileReader();
reader.onload = (event) => {
this.url = event.target.result;
// rebuild cropperjs with the updated source
this.$refs.cropper.replace(event.target.result);
};
reader.readAsDataURL(this.selectedFile);
} else {
this.noty(ALERT_TYPE[0],lang.something_wrong);
}
},
async uploadImage(){
this.getData()
if(this.notEmpty(this.selectedFile) && this.notEmpty(this.pId) &&
this.notEmpty(this.cropData)){
this.isUploading = true
const data = new FormData()
data.append('image', this.selectedFile)
data.append('pId', this.pId)
data.append('w', this.cropData.width)
data.append('h', this.cropData.height)
data.append('x', this.cropData.x)
data.append('y', this.cropData.y)
data.append('r', this.cropData.rotate)
data.append('sx', this.cropData.scaleX)
data.append('sy', this.cropData.scaleY)
let response = await this.axiosPost('product/createproimg', data)
if(this.resOk(response.status)){
const newImages = {"id": response.data.id,"url": response.data.url}
this.setEditProductImg(newImages)
this.selectedFile = null
}
}
this.isUploading = false
},
},
created(){
this.url = this.placeholder
}
}
</script>