607 lines
17 KiB
Vue
607 lines
17 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" :class="{'active': currentView === 'canvasEditor'}"@click.stop>
|
|
<!-- :clothingMinIOPath="selectDetail.minIOPath" 部件选取 -->
|
|
<editCanvas v-if="canvasLoad" :config="canvasConfig"
|
|
@canvasInit="editSketchCanvasInit"
|
|
is-edit
|
|
:clothingImageUrl="selectDetail.path"
|
|
:clothingImageUrl2="selectDetail.layersObject[0].maskUrl"
|
|
showFixedLayer
|
|
:canvasJSON="canvasJSON"
|
|
@canvasLoadJsonSuccess="canvasLoadJsonSuccess"
|
|
:clothing-image-opts="{
|
|
imageMode:'contains',
|
|
}"
|
|
:hideCanvas="hideCanvas || !isEditPattern"
|
|
ref="editCanvas">
|
|
</editCanvas>
|
|
<!-- <canvasContent ref="canvasContent"></canvasContent> -->
|
|
</div>
|
|
<div class="editFrontBack" v-if="currentView === 'redGreenExample'" @click.stop>
|
|
<editCanvas v-if="canvasLoad" :config="canvasConfig"
|
|
@canvasInit="editFrontBackCanvasInit"
|
|
:enabledRedGreenMode="true"
|
|
:clothingImageUrl="selectDetail.path"
|
|
:redGreenImageUrl="frontBack.front[imgDomIndex].maskUrl"
|
|
@trigger-red-green-mouseup="frontBackChange"
|
|
is-edit
|
|
:clothing-image-opts="{
|
|
imageMode:'contains',
|
|
}"
|
|
:hideCanvas="hideCanvas || !isEditPattern"
|
|
ref="editCanvasBackFront">
|
|
</editCanvas>
|
|
</div>
|
|
<div class="editSketch" v-if="currentView === 'editSketch'" @click.stop>
|
|
<generalMiniCanvas ref="generalMiniCanvas" :btnShow="false" :imgUrl="selectDetail.sketchString || selectDetail.path"></generalMiniCanvas>
|
|
</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";
|
|
import { useRouter, useRoute } from 'vue-router'
|
|
import generalMiniCanvas from "../../modules/generalMiniCanvas.vue";
|
|
|
|
export default defineComponent({
|
|
components:{
|
|
editCanvas,generalMiniCanvas
|
|
},
|
|
props:{
|
|
isEditPattern:{
|
|
type:String,
|
|
default:''
|
|
},
|
|
updateOtherLayers:{
|
|
type:Function,
|
|
default:()=>{}
|
|
},
|
|
sketchSize:{
|
|
type:Object,
|
|
default:()=>{}
|
|
},
|
|
},
|
|
emits:['update:loadingShow'],
|
|
setup(props,{emit}) {
|
|
const store = useStore();
|
|
const {t} = useI18n();
|
|
const route = useRoute()
|
|
const detailDom = reactive({
|
|
editFrontBack:null as any,
|
|
model:null,
|
|
editCanvas:null as any,
|
|
editCanvasBackFront:null as any,
|
|
canvasContent:null as any,
|
|
generalMiniCanvas: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:'',
|
|
hideCanvas: computed(()=>(store.state.Workspace.projectPath !== route.fullPath)),
|
|
otherData:computed(()=>({
|
|
canvasId: store.state.DesignDetail.selectDetail.canvasId,
|
|
color: store.state.DesignDetail.selectDetail.color,
|
|
printObject: store.state.DesignDetail.selectDetail.printObject,
|
|
trims: store.state.DesignDetail.selectDetail.trims,
|
|
})),
|
|
changeSketchUpdateFrontBack:null as any,//切换sketch后是否需要合成图片进行风格
|
|
})
|
|
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 if(detailData.currentView === 'redGreenExample'){
|
|
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.path).then(()=>{
|
|
// detailData.canvasLoad = true
|
|
})
|
|
})
|
|
}else{
|
|
nextTick(()=>{
|
|
setCanvas(detailData.frontBack.front[detailData.imgDomIndex].maskUrl).then(()=>{
|
|
// detailData.canvasLoad = true
|
|
})
|
|
})
|
|
}
|
|
}
|
|
}
|
|
const updateOtherLayers = (obj:any)=>{
|
|
if(!detailDom.editCanvas)return
|
|
return new Promise(async (res,reject)=>{
|
|
await detailDom?.editCanvas.updateOtherLayers(obj)
|
|
res('')
|
|
})
|
|
}
|
|
const privewDetail = async (oldSelectDetail = detailData.selectDetail)=>{
|
|
// if(!detailDom.editCanvas)return
|
|
return new Promise(async (res,reject)=>{
|
|
console.log(detailDom.editCanvas)
|
|
await detailDom.editCanvas.exportImage({
|
|
isContainFixed:true,
|
|
width:props.sketchSize.width,
|
|
height:props.sketchSize.height,
|
|
}).then((rv)=>{
|
|
if(oldSelectDetail?.partialDesign)oldSelectDetail.partialDesign.partialDesignBase64 = rv
|
|
})
|
|
|
|
await setUndivideLayer()
|
|
res('')
|
|
})
|
|
}
|
|
const getCanvasElement = ()=>{
|
|
if(!detailDom?.editCanvas)return ''
|
|
return detailDom?.editCanvas.exportExtraInfo();
|
|
}
|
|
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
|
|
detailData.canvasConfig.width = img.width
|
|
detailData.canvasConfig.height = img.height
|
|
detailData.canvasConfig.initZoom = true
|
|
|
|
res('')
|
|
}
|
|
img.src = url
|
|
})
|
|
}
|
|
|
|
const resizeImageWithNativeCanvas = async (image1Url, imageBUrl)=>{
|
|
try {
|
|
// 加载第一张图片获取尺寸
|
|
const img1 = await loadImage(image1Url);
|
|
const targetWidth = img1.naturalWidth;
|
|
const targetHeight = img1.naturalHeight;
|
|
|
|
// 加载第二张图片
|
|
const imgB = await loadImage(imageBUrl);
|
|
|
|
// 创建canvas元素
|
|
const canvas = document.createElement('canvas');
|
|
canvas.width = targetWidth;
|
|
canvas.height = targetHeight;
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
// 绘制调整尺寸后的图片
|
|
ctx.drawImage(imgB, 0, 0, targetWidth, targetHeight);
|
|
|
|
// 导出base64
|
|
const base64 = canvas.toDataURL('image/png', 1);
|
|
|
|
return base64;
|
|
} catch (error) {
|
|
console.error('处理图片时出错:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// 图片加载辅助函数
|
|
const loadImage = (url)=>{
|
|
return new Promise((resolve, reject) => {
|
|
const img = new Image();
|
|
img.crossOrigin = 'anonymous';
|
|
img.onload = () => resolve(img);
|
|
img.onerror = reject;
|
|
img.src = url;
|
|
});
|
|
}
|
|
|
|
|
|
const frontBackChange = (value:any)=>{
|
|
let full = detailData.selectDetail.partialDesign.partialDesignBase64 || detailData.selectDetail.path
|
|
let size = {
|
|
...detailData.canvasConfig,
|
|
}
|
|
store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
|
segmentImage(value,full,size).then(async (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
|
|
let base64 = await resizeImageWithNativeCanvas(front.oldMaskUrl,value)
|
|
front.maskUrl = base64
|
|
back.imageUrl = rv.targetBackUrl
|
|
// store.commit('DesignDetail/updataDetailItem',{maskUrl:value})
|
|
})
|
|
|
|
}
|
|
const editSketchCanvasInit = async (value:any)=>{
|
|
detailData.canvasInstance = value
|
|
detailData.getCanvasIfEdit.fun = getCanvasLength
|
|
detailData.isShowMark = false
|
|
console.log('初始化完成')
|
|
}
|
|
const editFrontBackCanvasInit = (value:any)=>{
|
|
detailData.canvasInstance = value
|
|
detailData.getCanvasIfEdit.fun = getCanvasLength
|
|
detailData.isShowMark = false
|
|
console.log('初始化完成')
|
|
}
|
|
const getCanvasLength = ()=>{
|
|
return detailData.canvasInstance?.commandManager?.undoStack?.length
|
|
}
|
|
const getCanvasJSON = ()=>{
|
|
if(!detailDom?.editCanvas)return ''
|
|
return detailDom?.editCanvas?.getJSON()
|
|
}
|
|
const saveCanvas = async (canvasData:any)=>{
|
|
const index = detailData.designDetail.clothes.findIndex(item => item.id === canvasData.id);
|
|
await new Promise<void>((resolve, reject) => {
|
|
let canvasJSON = JSON.parse(canvasData.canvasJSON)
|
|
if(!canvasJSON)return resolve()
|
|
// canvasData.canvas.objects.forEach((objectsItem:any) => {
|
|
// if(objectsItem.type == 'image')objectsItem.minioUrl = getMinioUrl(objectsItem.src)
|
|
// });
|
|
let blob = new Blob([JSON.stringify(canvasJSON)], { 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)
|
|
// }
|
|
const canvasLoadJsonSuccess = async ()=>{
|
|
let otherData = await props.updateOtherLayers()
|
|
await updateOtherLayers(otherData)
|
|
if(detailData.changeSketchUpdateFrontBack){
|
|
await detailData.changeSketchUpdateFrontBack()
|
|
detailData.changeSketchUpdateFrontBack = null
|
|
}
|
|
setUndivideLayer()
|
|
emit('update:loadingShow',false)
|
|
}
|
|
const setUndivideLayer = async ()=>{
|
|
await new Promise<void>(async (resolve, reject) => {
|
|
// if(!detailData.selectDetail.undividedLayerColor){
|
|
await detailDom.editCanvas.exportImage({
|
|
isContainFixed:true,
|
|
isPrintTrimsRepeat:false,
|
|
isPrintTrimsNoRepeat:false,
|
|
isContainNormalLayer:false,
|
|
width:props.sketchSize.width,
|
|
height:props.sketchSize.height}).then((rv)=>{
|
|
detailData.selectDetail.undividedLayerColor = rv
|
|
})
|
|
// }
|
|
// if(!detailData.selectDetail.undividedLayer){
|
|
await detailDom.editCanvas.exportImage({
|
|
isContainFixed:true,
|
|
isPrintTrimsNoRepeat:false,
|
|
isPrintTrimsRepeat:true,
|
|
isContainNormalLayer:false,
|
|
width:props.sketchSize.width,
|
|
height:props.sketchSize.height,
|
|
}).then((rv)=>{
|
|
detailData.selectDetail.undividedLayer = rv
|
|
})
|
|
// }
|
|
resolve()
|
|
})
|
|
|
|
}
|
|
|
|
const submitBase64Data = ()=>{
|
|
return detailDom.generalMiniCanvas.submitBase64Data()
|
|
}
|
|
|
|
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
|
|
if(front?.oldMaskUrl)store.commit('DesignDetail/updataDetailItem',{maskUrl:front.maskUrl})
|
|
|
|
sessionStorage.removeItem('frontBackEdit');
|
|
sessionStorage.removeItem('sketchEdit');
|
|
detailData.canvasLoad = false
|
|
// privewDetail()
|
|
})
|
|
onMounted(()=>{
|
|
nextTick(async ()=>{
|
|
// detailData.currentView = 'canvasEditor'
|
|
const sessionCanvasList = sessionStorage.getItem('canvasList');
|
|
const canvasList = sessionCanvasList ? JSON.parse(sessionCanvasList) : []
|
|
let canvasIndex = canvasList.findIndex(item => item.id === detailData.selectDetail.id);
|
|
if(canvasIndex>-1){
|
|
detailData.canvasJSON = canvasList[canvasIndex].canvasJSON
|
|
}else{
|
|
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.path).then(()=>{
|
|
detailData.canvasLoad = true
|
|
})
|
|
})
|
|
})
|
|
return{
|
|
...toRefs(detailDom),
|
|
...toRefs(detailData),
|
|
editFront,
|
|
privewDetail,
|
|
setFrontBackColor,
|
|
frontBackChange,
|
|
editSketchCanvasInit,
|
|
editFrontBackCanvasInit,
|
|
saveCanvas,
|
|
getCanvasElement,
|
|
updateOtherLayers,
|
|
canvasLoadJsonSuccess,
|
|
submitBase64Data,
|
|
getCanvasJSON,
|
|
}
|
|
},
|
|
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{
|
|
opacity: 0;
|
|
position: absolute;
|
|
&.active{
|
|
opacity: 1;
|
|
position: relative;
|
|
}
|
|
}
|
|
.canvas,.editFrontBack,.editSketch{
|
|
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> |