467 lines
13 KiB
Vue
467 lines
13 KiB
Vue
<template>
|
|
<div class="canvasBox">
|
|
<!-- designDetailShow -->
|
|
<!-- :class="[driver__.driver?'hideEvents':'']" -->
|
|
<div class="canvasContent" ref="canvasContent">
|
|
<div class="content-bottom" ref="canvasContent">
|
|
<div class="contet">
|
|
<div class="canvas" v-if="currentView === 'canvasEditor'" @click.stop>
|
|
<editCanvas v-if="canvasLoad" :config="canvasConfig"
|
|
@canvasInit="canvasInit"
|
|
@changeCanvas="changeCanvas"
|
|
:clothingImageUrl="selectDetail.undividedLayer || selectDetail.path"
|
|
showFixedLayer
|
|
:canvasJSON="canvasJSON"
|
|
:clothing-image-opts="{
|
|
imageMode:'contains',
|
|
}"
|
|
ref="editCanvas">
|
|
|
|
<template #customToolsBottom="{ toolButtonProps }">
|
|
<!-- 也可以直接使用普通的按钮 -->
|
|
<div class="custom-tool-btn" :class="{active:currentView === 'redGreenExample'}" @click="editFront('redGreenExample')">
|
|
<i class="fi fi-sr-layers"></i>
|
|
<div class="tool-tooltip">{{ $t('Canvas.editFrontBack') }}</div>
|
|
</div>
|
|
<div class="custom-tool-btn" :class="{active:currentView === 'redGreenExample'}" style="margin-top: auto;" @click="editFront('redGreenExample')">
|
|
<SvgIcon name="CHelp" size="30" />
|
|
<div class="tool-tooltip">{{ $t('Canvas.help') }}</div>
|
|
</div>
|
|
</template>
|
|
</editCanvas>
|
|
<!-- <canvasContent ref="canvasContent"></canvasContent> -->
|
|
</div>
|
|
<div class="editFrontBack" v-if="currentView === 'redGreenExample'" @click.stop>
|
|
<!-- <editFrontBack
|
|
:patchData="frontBack"
|
|
:imgDomIndex="imgDomIndex"
|
|
|
|
ref="editFrontBack">
|
|
</editFrontBack> -->
|
|
<editCanvas v-if="canvasLoad" :config="canvasConfig"
|
|
:enabledRedGreenMode="true"
|
|
@canvasInit="canvasInit"
|
|
:clothingImageUrl="selectDetail.undividedLayer || selectDetail.path"
|
|
:redGreenImageUrl="frontBack.front[imgDomIndex].maskUrl"
|
|
@trigger-red-green-mouseup="frontBackChange"
|
|
:clothing-image-opts="{
|
|
imageMode:'contains',
|
|
}"
|
|
ref="editCanvasBackFront">
|
|
</editCanvas>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- <div class="Finish">
|
|
<div class="gallery_btn" @click="privewDetail">Finish</div>
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mark_loading" v-show="isShowMark">
|
|
<a-spin size="large" />
|
|
</div>
|
|
</div>
|
|
|
|
</template>
|
|
<script lang="ts">
|
|
import { defineComponent,computed,onBeforeUnmount,provide,nextTick,watch,toRefs, reactive} from 'vue'
|
|
import { Https } from "@/tool/https";
|
|
import { Modal,message } from 'ant-design-vue';
|
|
import {getUploadUrl,isMoible,setGradual} from '@/tool/util'
|
|
import { useStore } from "vuex";
|
|
import { useI18n } from 'vue-i18n'
|
|
import editCanvas from "@/component/Canvas/CanvasEditor/index.vue";
|
|
import { formatTime,segmentImage,getMinioUrl } from "@/tool/util";
|
|
|
|
export default defineComponent({
|
|
components:{
|
|
editCanvas
|
|
},
|
|
props:{
|
|
isEditPattern:{
|
|
type:String,
|
|
default:''
|
|
}
|
|
},
|
|
setup(props,{emit}) {
|
|
const store = useStore();
|
|
const {t} = useI18n();
|
|
|
|
const detailDom = reactive({
|
|
editFrontBack:null as any,
|
|
model:null,
|
|
editCanvas:null as any,
|
|
editCanvasBackFront:null as any,
|
|
canvasContent:null as any,
|
|
})
|
|
const userDetail = computed(()=>{
|
|
return store.state.UserHabit.userDetail
|
|
})
|
|
const detailData = reactive({
|
|
isShowMark:false,
|
|
liquefactionData:null as any,
|
|
liquefaction:null as any,
|
|
canvasType:'export',
|
|
imgDomIndex:-1,
|
|
selectDetail:computed(()=>store.state.DesignDetail.selectDetail),
|
|
designDetail:computed(()=>store.state.DesignDetail.designDetail),
|
|
frontBack:computed(()=>store.state.DesignDetail.frontBack),
|
|
canvasLoad:false,
|
|
canvasConfig:{
|
|
} as any,
|
|
currentView:props.isEditPattern,
|
|
getCanvasIfEdit:inject('getCanvasIfEdit')as any,
|
|
canvasInstance:null as any,
|
|
canvasJSON:'',
|
|
})
|
|
watch(()=>detailData.selectDetail,(newValue,oldValue)=>{
|
|
detailData.imgDomIndex = detailData.frontBack.front.findIndex((item:any)=>item.id == newValue.id)
|
|
// privewDetail(oldValue)
|
|
},{immediate: true})
|
|
provide('isShowMark',detailData.isShowMark)
|
|
provide('canvasType',detailData.canvasType)
|
|
|
|
const editFront = (str:any)=>{//编辑前后片
|
|
|
|
let canvasJSON = '' as any
|
|
if(detailData.currentView === 'canvasEditor'){
|
|
sessionStorage.setItem('sketchEdit',detailDom.editCanvas.getJSON())
|
|
canvasJSON = sessionStorage.getItem('frontBackEdit');
|
|
}else{
|
|
sessionStorage.setItem('frontBackEdit',detailDom.editCanvasBackFront.getJSON())
|
|
canvasJSON = sessionStorage.getItem('sketchEdit');
|
|
}
|
|
detailData.canvasLoad = false
|
|
detailData.currentView = str
|
|
if(canvasJSON){
|
|
detailData.canvasLoad = true
|
|
nextTick(()=>{
|
|
if(detailData.currentView === 'redGreenExample'){
|
|
detailDom.editCanvas.loadJSON(canvasJSON)
|
|
}else{
|
|
detailDom.editCanvasBackFront.loadJSON(canvasJSON)
|
|
}
|
|
})
|
|
}else{
|
|
if(detailData.currentView === 'redGreenExample'){
|
|
nextTick(()=>{
|
|
setCanvas(detailData.selectDetail.undividedLayer || detailData.selectDetail.path).then(()=>{
|
|
detailData.canvasLoad = true
|
|
})
|
|
})
|
|
}else{
|
|
nextTick(()=>{
|
|
setCanvas(detailData.frontBack.front[detailData.imgDomIndex].maskUrl).then(()=>{
|
|
detailData.canvasLoad = true
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{
|
|
if(!detailDom.editCanvas)return
|
|
return new Promise((res,reject)=>{
|
|
detailDom.editCanvas.exportImage({isContainBg:false,isContainFixed:false}).then((rv)=>{
|
|
if(oldSelectDetail?.partialDesign)oldSelectDetail.partialDesign.partialDesignBase64 = rv
|
|
res('')
|
|
})
|
|
})
|
|
|
|
|
|
}
|
|
const setFrontBackColor = (data:any)=>{
|
|
detailDom.editFrontBack.setBackground(data)
|
|
}
|
|
const setCanvas = (url:any)=>{
|
|
return new Promise((res,rev)=>{
|
|
let img = new Image()
|
|
img.onload = ()=>{
|
|
let wH = [1,1]
|
|
let domHeight = detailDom.canvasContent.offsetHeight - 200
|
|
let imgHeight = img.height
|
|
wH = [1,domHeight/imgHeight]
|
|
detailData.canvasConfig.width = img.width * wH[1]
|
|
detailData.canvasConfig.height = domHeight
|
|
|
|
res('')
|
|
}
|
|
img.src = url
|
|
})
|
|
}
|
|
const frontBackChange = (value:any)=>{
|
|
let full = detailData.frontBack.front[detailData.imgDomIndex].undividedLayer || detailData.selectDetail.path
|
|
let size = {
|
|
...detailData.canvasConfig,
|
|
}
|
|
segmentImage(value,full,size).then((rv)=>{
|
|
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
|
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
|
if(!front?.oldImageUrl)front.oldImageUrl = front.imageUrl
|
|
if(!front?.oldMaskUrl)front.oldMaskUrl = front.maskUrl
|
|
if(!back?.oldImageUrl)back.oldImageUrl = back.imageUrl
|
|
if(!front?.oldMaskUrl)store.commit('DesignDetail/updataDetailItem',{maskUrl:front.oldMaskUrl})
|
|
|
|
front.imageUrl = rv.targetFrontUrl
|
|
front.maskUrl = value
|
|
back.imageUrl = rv.targetBackUrl
|
|
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
|
})
|
|
|
|
}
|
|
const canvasInit = (value:any)=>{
|
|
// detailDom.editCanvas.addImageToLayer(detailData.selectDetail.undividedLayer,{layerId:value.layers.value[0].id,imageMode:'contains',undoable:false})
|
|
detailData.canvasInstance = value
|
|
detailData.getCanvasIfEdit.fun = getCanvasLength
|
|
detailData.isShowMark = false
|
|
}
|
|
const getCanvasLength = ()=>{
|
|
return detailData.canvasInstance?.commandManager?.undoStack?.length
|
|
}
|
|
const saveCanvas = async (type:string = '')=>{
|
|
if(type !== 'auto'){
|
|
detailData.isShowMark = true
|
|
}
|
|
const index = detailData.designDetail.clothes.findIndex(item => item.id === detailData.selectDetail.id);
|
|
console.log(index,detailData.selectDetail.id)
|
|
await new Promise<void>((resolve, reject) => {
|
|
if(!detailDom?.editCanvas)return resolve()
|
|
let canvasJSON = detailDom?.editCanvas?.getJSON()
|
|
let canvasData = JSON.parse(canvasJSON)
|
|
if(!canvasData)return resolve()
|
|
canvasData.canvas.objects.forEach((objectsItem:any) => {
|
|
if(objectsItem.type == 'image')objectsItem.minioUrl = getMinioUrl(objectsItem.src)
|
|
});
|
|
let blob = new Blob([JSON.stringify(canvasData)], { type: "application/json" });
|
|
let formData = new FormData();
|
|
formData.append("file", blob, "data.json");
|
|
formData.append("designItemDetailId", detailData.selectDetail.id);
|
|
formData.append("module", "designItemDetail");
|
|
let config = {
|
|
headers: { "Content-Type": "multipart/form-data", Accept: "*/*" },
|
|
};
|
|
Https.axiosPost(Https.httpUrls.exportSave, formData, config).then(
|
|
(rv) => {
|
|
if(index>-1)detailData.designDetail.clothes[index].canvasId = rv
|
|
// detailData.selectDetail.canvasId = rv
|
|
detailData.isShowMark = false
|
|
resolve()
|
|
}
|
|
).catch(()=>{
|
|
detailData.isShowMark = false
|
|
resolve()
|
|
});
|
|
})
|
|
}
|
|
let time = null as any
|
|
const changeCanvas = ()=>{
|
|
clearTimeout(time)
|
|
time = setTimeout(()=>{
|
|
saveCanvas('auto')
|
|
},3000)
|
|
}
|
|
onBeforeUnmount(()=>{
|
|
let front = detailData.frontBack.front[detailData.imgDomIndex]
|
|
let back = detailData.frontBack.back[detailData.imgDomIndex]
|
|
|
|
if(front?.oldImageUrl)front.imageUrl = front.oldImageUrl
|
|
if(front?.oldMaskUrl)front.maskUrl = front.oldMaskUrl
|
|
if(back?.oldImageUrl)back.imageUrl = back.oldImageUrl
|
|
console.log(front)
|
|
if(front?.oldMaskUrl)store.commit('DesignDetail/updataDetailItem',{maskUrl:front.oldMaskUrl})
|
|
|
|
sessionStorage.removeItem('frontBackEdit');
|
|
sessionStorage.removeItem('sketchEdit');
|
|
detailData.canvasLoad = false
|
|
privewDetail()
|
|
})
|
|
onMounted(()=>{
|
|
nextTick(async ()=>{
|
|
// detailData.currentView = 'canvasEditor'
|
|
if(detailData.selectDetail.canvasId){
|
|
detailData.isShowMark = true
|
|
await new Promise((resolve, reject) => {
|
|
let value = {
|
|
module:'designItemDetail',
|
|
id:detailData.selectDetail.canvasId,
|
|
}
|
|
Https.axiosPost(Https.httpUrls.exportSearch, value)
|
|
.then((rv) => {
|
|
detailData.canvasJSON = rv
|
|
resolve('')
|
|
})
|
|
.catch((rv) => {
|
|
resolve(null)
|
|
});
|
|
})
|
|
}
|
|
setCanvas(detailData.selectDetail.undividedLayer || detailData.selectDetail.path).then(()=>{
|
|
detailData.canvasLoad = true
|
|
})
|
|
})
|
|
})
|
|
return{
|
|
...toRefs(detailDom),
|
|
...toRefs(detailData),
|
|
editFront,
|
|
privewDetail,
|
|
setFrontBackColor,
|
|
frontBackChange,
|
|
canvasInit,
|
|
saveCanvas,
|
|
changeCanvas,
|
|
}
|
|
},
|
|
provide() {
|
|
return {
|
|
}
|
|
},
|
|
mounted(){
|
|
},
|
|
|
|
})
|
|
</script>
|
|
<style lang="less" scoped>
|
|
.canvasBox{
|
|
flex: 1;
|
|
overflow: hidden;
|
|
// top: -100%;
|
|
display: flex;
|
|
align-items: center;
|
|
.tool-box{
|
|
width: 4rem;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
.Finish{
|
|
margin-top: auto;
|
|
> .gallery_btn{
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
.content-bottom{
|
|
:deep(.tools-sidebar){
|
|
i{
|
|
font-size: 2.5rem;
|
|
cursor: pointer;
|
|
width: 3.5rem;
|
|
height: 3.5rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
flex-shrink: 0;
|
|
transition: all .3s;
|
|
margin-bottom: .5rem;
|
|
&.active{
|
|
border: 1px solid;
|
|
border-radius: .4rem;
|
|
}
|
|
&.icon-xiala{
|
|
transform: rotate(-90deg);
|
|
}
|
|
&.icon-xialaActive{
|
|
transform: rotate(90deg);
|
|
}
|
|
&.eventNone{
|
|
cursor: no-drop;
|
|
border: none;
|
|
opacity: .5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.canvasContent{
|
|
height: 100%;
|
|
// height: 70rem;
|
|
width: 100%;
|
|
border: 2px solid #000;
|
|
border-radius: 3rem;
|
|
padding: 4rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.content-bottom{
|
|
flex: 1;
|
|
overflow: hidden;
|
|
display: flex;
|
|
> .contet{
|
|
flex: 1;
|
|
overflow: hidden;
|
|
position: relative;
|
|
.canvas,.editFrontBack{
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
.editFrontBack{
|
|
z-index: 2;
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
.custom-tool-btn {
|
|
position: relative;
|
|
width: 3.6rem;
|
|
height: 3.6rem;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: none;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 1.6rem;
|
|
color: #333;
|
|
transition: all 0.2s ease;
|
|
&.active{
|
|
background-color: #e6f7ff;
|
|
color: #1890ff;
|
|
}
|
|
}
|
|
|
|
.custom-tool-btn:hover {
|
|
background-color: #f0f0f0;
|
|
&.active{
|
|
background-color: #e6f7ff;
|
|
color: #1890ff;
|
|
}
|
|
}
|
|
|
|
.custom-tool-btn:hover .tool-tooltip {
|
|
display: block;
|
|
}
|
|
|
|
.tool-tooltip {
|
|
display: none;
|
|
position: absolute;
|
|
left: 100%;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
background-color: rgba(0, 0, 0, 0.7);
|
|
color: white;
|
|
padding: .4rem .8rem;
|
|
border-radius: .4rem;
|
|
margin-left: .8rem;
|
|
white-space: nowrap;
|
|
font-size: 1.2rem;
|
|
z-index: 10;
|
|
}
|
|
|
|
.tool-tooltip:before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 50%;
|
|
right: 100%;
|
|
margin-top: -.5rem;
|
|
border-width: .5rem;
|
|
border-style: solid;
|
|
border-color: transparent rgba(0, 0, 0, 0.7) transparent transparent;
|
|
}
|
|
|
|
</style> |