Compare commits
2 Commits
8a9b217314
...
ec632554e2
| Author | SHA1 | Date | |
|---|---|---|---|
| ec632554e2 | |||
| 429c7db195 |
@@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<a-modal
|
||||
class="image-clip-dialog generalModel"
|
||||
:class="{ 'is-product': data.isProduct }"
|
||||
v-model:visible="show"
|
||||
:footer="null"
|
||||
width="70%"
|
||||
@@ -25,10 +26,20 @@
|
||||
ref="imageClipRef"
|
||||
v-bind="$attrs"
|
||||
:ratio="data.ratio"
|
||||
:fixedBox="type !== 'apparel'"
|
||||
:url="data.url"
|
||||
:type="type"
|
||||
@change="(v) => (data.preview_url = v)"
|
||||
/>
|
||||
<div class="preview" v-if="data.isPreview">
|
||||
<div
|
||||
class="preview"
|
||||
:class="{
|
||||
'is-product': data.isProduct,
|
||||
'is-apparel': type === 'apparel',
|
||||
'is-cover': type === 'cover'
|
||||
}"
|
||||
v-if="data.isPreview"
|
||||
>
|
||||
<div class="title">
|
||||
<span class="icon"><svg-icon name="seller-preview" size="24" /></span>
|
||||
<span class="label">Crop Preview</span>
|
||||
@@ -44,124 +55,161 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue"
|
||||
import ImageClip from "./image-clip.vue"
|
||||
const data = reactive({
|
||||
url: "",
|
||||
title: "Crop Image",
|
||||
preview_url: "",
|
||||
ratio: [1, 1],
|
||||
isPreview: true,
|
||||
callback: null
|
||||
})
|
||||
const show = ref(false)
|
||||
const open = (url, callback, options) => {
|
||||
if (!url || !callback) return
|
||||
data.url = url
|
||||
data.callback = callback
|
||||
data.ratio = [1, 1]
|
||||
data.isPreview = true
|
||||
data.preview_url = ""
|
||||
data.title = "Crop Image"
|
||||
if (options) {
|
||||
if (options.hasOwnProperty("isPreview")) data.isPreview = options.isPreview
|
||||
if (options.hasOwnProperty("ratio")) data.ratio = options.ratio
|
||||
if (options.hasOwnProperty("title")) data.title = options.title
|
||||
}
|
||||
show.value = true
|
||||
}
|
||||
const onCancel = () => {
|
||||
show.value = false
|
||||
}
|
||||
const imageClipRef = ref(null)
|
||||
const onSubmit = () => {
|
||||
imageClipRef.value.getCropBlob().then((blob) => {
|
||||
if (data.callback) data.callback(blobToFile(blob, "image.png"))
|
||||
onCancel()
|
||||
})
|
||||
}
|
||||
// 将blob转换为file对象
|
||||
const blobToFile = (blob, fileName) => {
|
||||
return new File([blob], fileName, { type: blob.type })
|
||||
}
|
||||
defineExpose({
|
||||
open
|
||||
import { ref } from "vue"
|
||||
import ImageClip from "./image-clip.vue"
|
||||
|
||||
defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: () => false
|
||||
}
|
||||
})
|
||||
|
||||
const data = reactive({
|
||||
url: "",
|
||||
title: "Crop Image",
|
||||
preview_url: "",
|
||||
ratio: [1, 1],
|
||||
isPreview: true,
|
||||
callback: null,
|
||||
isProduct: false // 是否商品编辑
|
||||
})
|
||||
const show = ref(false)
|
||||
const open = (url, callback, options) => {
|
||||
if (!url || !callback) return
|
||||
data.url = url
|
||||
data.callback = callback
|
||||
data.ratio = options.ratio || [1, 1]
|
||||
data.isPreview = true
|
||||
data.preview_url = ""
|
||||
data.title = options.title || "Crop Image"
|
||||
if (options) {
|
||||
if (options.hasOwnProperty("isPreview")) data.isPreview = options.isPreview
|
||||
data.isProduct = options.isProduct
|
||||
}
|
||||
show.value = true
|
||||
}
|
||||
const onCancel = () => {
|
||||
show.value = false
|
||||
}
|
||||
const imageClipRef = ref(null)
|
||||
const onSubmit = () => {
|
||||
imageClipRef.value.getCropBlob().then((blob) => {
|
||||
if (data.callback) data.callback(blobToFile(blob, "image.png"))
|
||||
onCancel()
|
||||
})
|
||||
}
|
||||
// 将blob转换为file对象
|
||||
const blobToFile = (blob, fileName) => {
|
||||
return new File([blob], fileName, { type: blob.type })
|
||||
}
|
||||
defineExpose({
|
||||
open
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.image-clip-dialog-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
.image-clip-dialog-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.submit {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
border-radius: 50%;
|
||||
background: #262626;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
> .header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.submit {
|
||||
width: 4rem;
|
||||
height: 4rem;
|
||||
border-radius: 50%;
|
||||
background: #262626;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 5rem;
|
||||
> .title {
|
||||
font-family: pingfang_heavy;
|
||||
font-size: 2.4rem;
|
||||
color: #595959;
|
||||
}
|
||||
> .header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 5rem;
|
||||
> .title {
|
||||
font-family: pingfang_heavy;
|
||||
font-size: 2.4rem;
|
||||
color: #595959;
|
||||
}
|
||||
> .right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 2rem;
|
||||
> button {
|
||||
width: 10rem;
|
||||
height: 4.8rem;
|
||||
border-radius: 4rem;
|
||||
border: none;
|
||||
background: #e4e5eb;
|
||||
font-family: pingfang_heavy;
|
||||
font-size: 1.6rem;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
> .content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
> .right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> .image-clip {
|
||||
flex: 1;
|
||||
gap: 2rem;
|
||||
> button {
|
||||
width: 10rem;
|
||||
height: 4.8rem;
|
||||
border-radius: 4rem;
|
||||
border: none;
|
||||
background: #e4e5eb;
|
||||
font-family: pingfang_heavy;
|
||||
font-size: 1.6rem;
|
||||
color: #000;
|
||||
}
|
||||
> .preview {
|
||||
margin-left: 6rem;
|
||||
width: 28rem;
|
||||
}
|
||||
}
|
||||
> .content {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
> .image-clip {
|
||||
flex: 1;
|
||||
&.is-product {
|
||||
width: initial;
|
||||
flex: none;
|
||||
}
|
||||
}
|
||||
> .preview {
|
||||
margin-left: 6rem;
|
||||
width: 28rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 2.4rem;
|
||||
|
||||
> .title {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 2.4rem;
|
||||
> .title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.2rem;
|
||||
> .label {
|
||||
font-family: pingfang_heavy;
|
||||
font-size: 1.6rem;
|
||||
justify-content: center;
|
||||
gap: 1.2rem;
|
||||
> .label {
|
||||
font-family: pingfang_heavy;
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
> img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
&.is-product {
|
||||
margin-left: 0;
|
||||
height: 100%;
|
||||
|
||||
justify-content: flex-start;
|
||||
img {
|
||||
width: 20.8rem;
|
||||
height: 36.7rem;
|
||||
margin-bottom: 0;
|
||||
box-shadow: 4px 4px 16px 0px #0000000f;
|
||||
border: 1px solid #ededed;
|
||||
}
|
||||
&.is-cover {
|
||||
img {
|
||||
// width: 29.7rem;
|
||||
height: 37.5rem;
|
||||
}
|
||||
}
|
||||
> img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 3rem;
|
||||
&.is-apparel {
|
||||
img {
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
<template>
|
||||
<div class="image-clip" :class="{ 'is-product': isProduct }">
|
||||
<div class="image-clip-body" ref="imageClipBody">
|
||||
<div class="image-clip" :class="{ 'is-product': isProduct }" :data-crop-type="type || ''">
|
||||
<div class="image-clip-body" :class="{ 'is-cover': type === 'cover' }" ref="imageClipBody">
|
||||
<VueCropper
|
||||
ref="cropper"
|
||||
:img="url"
|
||||
crossOrigin="Anonymous"
|
||||
:autoCrop="true"
|
||||
:fixedNumber="ratio"
|
||||
fixed
|
||||
:fixed="type !== 'apparel'"
|
||||
movable
|
||||
centerBox
|
||||
:fixedBox="fixedBox"
|
||||
@realTime="onChange"
|
||||
v-bind="$attrs"
|
||||
outputType="png"
|
||||
:autoCropWidth="type === 'cover' ? 297 : 242"
|
||||
:autoCropHeight="autoCropHeight"
|
||||
></VueCropper>
|
||||
</div>
|
||||
<div class="clip_opterate">
|
||||
@@ -35,7 +38,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, useAttrs, onMounted, onBeforeUnmount } from "vue"
|
||||
import { ref, useAttrs, onMounted, onBeforeUnmount, computed, nextTick, watch } from "vue"
|
||||
import "vue-cropper/dist/index.css"
|
||||
import { VueCropper } from "vue-cropper"
|
||||
const props = defineProps({
|
||||
@@ -50,10 +53,25 @@ const props = defineProps({
|
||||
isProduct: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fixedBox: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: () => ""
|
||||
}
|
||||
})
|
||||
const attrs = useAttrs()
|
||||
|
||||
const autoCropHeight = computed(() => {
|
||||
let height = 426
|
||||
if (props.type === "cover") height = 375
|
||||
else if (props.type === "apparel") height = 320
|
||||
return height
|
||||
})
|
||||
|
||||
const onChange = (data) => {
|
||||
if (attrs.onChange) {
|
||||
getCropUrl().then((url) => attrs.onChange(url))
|
||||
@@ -61,15 +79,77 @@ const onChange = (data) => {
|
||||
}
|
||||
const cropper = ref(null)
|
||||
const imageClipBody = ref(null)
|
||||
let injectLabelFrame = 0
|
||||
const observer = new ResizeObserver((entries) => {
|
||||
refreshCrop()
|
||||
})
|
||||
|
||||
const clearCropLabels = (cropperBox) => {
|
||||
if (!cropperBox) return
|
||||
cropperBox.querySelectorAll(".cropper-line-label").forEach((node) => node.remove())
|
||||
}
|
||||
|
||||
const createCropLabel = ({ text, top, className }) => {
|
||||
const label = document.createElement("div")
|
||||
label.className = `cropper-line-label ${className}`
|
||||
label.textContent = text
|
||||
label.style.top = top
|
||||
label.style.left = className === "label-v" ? "50%" : "0"
|
||||
label.style.transform =
|
||||
className === "label-v" ? "translate(-50%, -50%)" : "translateY(-50%)"
|
||||
return label
|
||||
}
|
||||
|
||||
const cropLabelMap = {
|
||||
cover: [
|
||||
{ text: "crown", top: "2.67%", className: "label-h" },
|
||||
{ text: "hip line", top: "63.47%", className: "label-h" },
|
||||
{ text: "mid-thigh", top: "92.8%", className: "label-h" },
|
||||
{ text: "center", top: "0", className: "label-v" }
|
||||
],
|
||||
mainProductImage: [
|
||||
{ text: "crown", top: "2.67%", className: "label-h" },
|
||||
{ text: "footbase", top: "97.6%", className: "label-h" },
|
||||
{ text: "center", top: "0", className: "label-v" }
|
||||
],
|
||||
sketch: [
|
||||
{ text: "crown", top: "2.67%", className: "label-h" },
|
||||
{ text: "footbase", top: "97.6%", className: "label-h" },
|
||||
{ text: "center", top: "0", className: "label-v" }
|
||||
],
|
||||
apparel: [{ text: "center", top: "0", className: "label-v" }]
|
||||
}
|
||||
|
||||
const injectCropLabel = () => {
|
||||
const cropperBox = imageClipBody.value?.querySelector(".cropper-view-box")
|
||||
|
||||
if (!cropperBox) return false
|
||||
|
||||
clearCropLabels(cropperBox)
|
||||
|
||||
;(cropLabelMap[props.type] || []).forEach((config) => {
|
||||
cropperBox.appendChild(createCropLabel(config))
|
||||
})
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
const scheduleInjectCropLabel = (retry = 0) => {
|
||||
cancelAnimationFrame(injectLabelFrame)
|
||||
injectLabelFrame = requestAnimationFrame(() => {
|
||||
if (!injectCropLabel() && retry < 10) {
|
||||
scheduleInjectCropLabel(retry + 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
observer.observe(imageClipBody.value)
|
||||
injectCropLabel()
|
||||
scheduleInjectCropLabel()
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
observer.disconnect()
|
||||
cancelAnimationFrame(injectLabelFrame)
|
||||
})
|
||||
const rotateLeft = () => {
|
||||
cropper.value.rotateLeft()
|
||||
@@ -94,47 +174,14 @@ const getCropBlob = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const injectCropLabel = () => {
|
||||
const cropperBox = imageClipBody.value.querySelector(".cropper-view-box")
|
||||
|
||||
if (cropperBox) {
|
||||
// Add crown label
|
||||
const crownLabel = document.createElement("div")
|
||||
crownLabel.className = "cropper-line-label label-h"
|
||||
crownLabel.textContent = "crown"
|
||||
crownLabel.style.top = "2.67%"
|
||||
crownLabel.style.left = "0"
|
||||
crownLabel.style.transform = "translateY(-50%)"
|
||||
cropperBox.appendChild(crownLabel)
|
||||
|
||||
// Add hip line label
|
||||
const hipLabel = document.createElement("div")
|
||||
hipLabel.className = "cropper-line-label label-h"
|
||||
hipLabel.textContent = "hip line"
|
||||
hipLabel.style.top = "63.47%"
|
||||
hipLabel.style.left = "0"
|
||||
hipLabel.style.transform = "translateY(-50%)"
|
||||
cropperBox.appendChild(hipLabel)
|
||||
|
||||
// Add mid-thigh label
|
||||
const thighLabel = document.createElement("div")
|
||||
thighLabel.className = "cropper-line-label label-h"
|
||||
thighLabel.textContent = "mid-thigh"
|
||||
thighLabel.style.top = "92.8%"
|
||||
thighLabel.style.left = "0"
|
||||
thighLabel.style.transform = "translateY(-50%)"
|
||||
cropperBox.appendChild(thighLabel)
|
||||
|
||||
// Add center label
|
||||
const centerLabel = document.createElement("div")
|
||||
centerLabel.className = "cropper-line-label label-v"
|
||||
centerLabel.textContent = "center"
|
||||
centerLabel.style.top = "0"
|
||||
centerLabel.style.left = "50%"
|
||||
centerLabel.style.transform = "translate(-50%, -50%)"
|
||||
cropperBox.appendChild(centerLabel)
|
||||
}
|
||||
}
|
||||
watch(
|
||||
[() => props.type, () => props.url],
|
||||
async () => {
|
||||
await nextTick()
|
||||
scheduleInjectCropLabel()
|
||||
},
|
||||
{ flush: "post" }
|
||||
)
|
||||
|
||||
defineExpose({
|
||||
getCropUrl,
|
||||
@@ -167,6 +214,19 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
}
|
||||
&.is-cover {
|
||||
:deep(.vue-cropper) {
|
||||
overflow: hidden;
|
||||
}
|
||||
:deep(.cropper-box-canvas) {
|
||||
width: 31.1rem !important;
|
||||
left: 50% !important;
|
||||
transform: translateX(-50%) !important;
|
||||
img {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clip_opterate {
|
||||
@@ -213,52 +273,75 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
|
||||
&.is-product {
|
||||
.image-clip-body {
|
||||
width: 45.7rem;
|
||||
height: 45.7rem;
|
||||
:deep(.cropper-modal) {
|
||||
background: transparent;
|
||||
}
|
||||
:deep(.vue-cropper .cropper-view-box) {
|
||||
position: relative;
|
||||
overflow: visible !important;
|
||||
/* 原有的蓝色边框(outline)由组件控制,这里不干涉 */
|
||||
&.is-product {
|
||||
.image-clip-body {
|
||||
width: 45.7rem;
|
||||
height: 45.7rem;
|
||||
:deep(.cropper-modal) {
|
||||
background: transparent;
|
||||
}
|
||||
:deep(.vue-cropper .cropper-view-box) {
|
||||
position: relative;
|
||||
overflow: visible !important;
|
||||
/* 原有的蓝色边框(outline)由组件控制,这里不干涉 */
|
||||
}
|
||||
|
||||
:deep(.vue-cropper .cropper-view-box::after) {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 9; /* 位于图片之上,但在控制点之下 */
|
||||
background-image: none;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.vue-cropper .cropper-view-box::after) {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
pointer-events: none;
|
||||
z-index: 9; /* 位于图片之上,但在控制点之下 */
|
||||
&[data-crop-type="cover"] {
|
||||
.image-clip-body {
|
||||
:deep(.vue-cropper .cropper-view-box::after) {
|
||||
background-image:
|
||||
linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
linear-gradient(to bottom, #4ba5ff 50%, transparent 50%);
|
||||
background-repeat: repeat-x, repeat-x, repeat-x, repeat-y;
|
||||
background-size: 8px 1px, 8px 1px, 8px 1px, 1px 8px;
|
||||
background-position: 0 2.67%, 0 63.47%, 0 92.8%, 50% 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 绘制 4 条 #4BA5FF 的虚线 */
|
||||
background-image:
|
||||
linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
/* Crown */ linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
/* Hip line */ linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
/* Mid-thigh */ linear-gradient(to bottom, #4ba5ff 50%, transparent 50%); /* Center */
|
||||
&[data-crop-type="mainProductImage"],
|
||||
&[data-crop-type="sketch"] {
|
||||
.image-clip-body {
|
||||
:deep(.vue-cropper .cropper-view-box::after) {
|
||||
background-image:
|
||||
linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
linear-gradient(to right, #4ba5ff 50%, transparent 50%),
|
||||
linear-gradient(to bottom, #4ba5ff 50%, transparent 50%);
|
||||
background-repeat: repeat-x, repeat-x, repeat-y;
|
||||
background-size: 8px 1px, 8px 1px, 1px 8px;
|
||||
background-position: 0 2.67%, 0 97.6%, 50% 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
background-repeat: repeat-x, repeat-x, repeat-x, repeat-y;
|
||||
background-size:
|
||||
8px 1px,
|
||||
8px 1px,
|
||||
8px 1px,
|
||||
1px 8px; /* 虚线间距 */
|
||||
|
||||
background-position:
|
||||
0 2.67%,
|
||||
0 63.47%,
|
||||
0 92.8%,
|
||||
50% 0;
|
||||
&[data-crop-type="apparel"] {
|
||||
.image-clip-body {
|
||||
:deep(.vue-cropper .cropper-view-box::after) {
|
||||
background-image: linear-gradient(to bottom, #4ba5ff 50%, transparent 50%);
|
||||
background-repeat: repeat-y;
|
||||
background-size: 1px 8px;
|
||||
background-position: 50% 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less">
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<div
|
||||
v-if="previewImageMap[type]"
|
||||
class="crop-tool flex flex-center"
|
||||
@click="handleClickCrop(previewImageMap[type])"
|
||||
@click="handleClickCrop(previewImageMap[type], type)"
|
||||
>
|
||||
<SvgIcon name="CCrop" color="#fff" size="12" />
|
||||
</div>
|
||||
@@ -128,7 +128,10 @@
|
||||
class="sketch-element flex flex-center"
|
||||
>
|
||||
<img class="img-src" :src="item.url" alt="" />
|
||||
<div class="crop-tool flex flex-center">
|
||||
<div
|
||||
class="crop-tool flex flex-center"
|
||||
@click="handleClickCrop(item.url, 'apparel')"
|
||||
>
|
||||
<SvgIcon name="CCrop" color="#fff" size="12" />
|
||||
</div>
|
||||
</div>
|
||||
@@ -221,7 +224,8 @@
|
||||
fixedBox
|
||||
isProduct
|
||||
:info="false"
|
||||
:autoCropWidth="90"
|
||||
v-bind="$attrs"
|
||||
:type="cropType"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@@ -394,14 +398,23 @@ const handleSelectProdImg = (index: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleClickCrop = (data) => {
|
||||
console.log(data)
|
||||
const cropType = ref("")
|
||||
const handleClickCrop = (data, type) => {
|
||||
console.log(data, type)
|
||||
const titleList = {
|
||||
sketch: "Crop Sketch",
|
||||
mainProductImage: "Crop Main Product Image",
|
||||
cover: "Crop Cover",
|
||||
apparel: "Crop Apparel Sketch"
|
||||
}
|
||||
const ratio = type === "apparel" ? [4, 5] : [9, 16]
|
||||
cropType.value = type
|
||||
imageClipDialogRef.value.open(
|
||||
data,
|
||||
(file) => {
|
||||
selectList.value[currentIndex.value].sketch = URL.createObjectURL(file)
|
||||
},
|
||||
{ ratio: [9, 16], isPreview: true, title: "Crop Brand Banner" }
|
||||
{ ratio, isPreview: true, title: titleList[type], isProduct: true }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user