Files
aida_front/src/component/Detail/editFrontBack.vue
X1627315083 f29cb498f3 fix
2024-10-14 16:08:24 +08:00

600 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="editFrontBack_center">
<div class="editFrontBack_center_btn editFrontBack_center_item" :class="{spread:spreadState}">
<!-- <div @click="setOperation('')" class="editFrontBack_center_btn_item">
<div>新增</div>
</div> -->
<i class="icon iconfont icon-chehui" @click="historyState('')"></i>
<i class="icon iconfont icon-fanchehui" @click="historyState('reverse')"></i>
<!-- <i class="icon iconfont icon-move" @click="setOperation('move')" :class="{active:canvasState == 'move'}"></i> -->
<i class="icon iconfont icon-bianji" @click="setOperation('pencil')" :class="{active:canvasState == 'pencil'}"></i>
<!-- <i class="icon iconfont icon-xiangpi_huaban1" @click="setOperation('eraser')" :class="{active:canvasState == 'eraser'}"></i> -->
<div class="editFrontBack_center_btn_colorRed" @click="setOperationColor('rgb(255,0,0)')" :class="{active:(canvasState != 'eraser' && rgba == 'rgb(255,0,0)')}" title="front">front</div>
<div class="editFrontBack_center_btn_colorGreen" @click="setOperationColor('rgb(0,255,0)')" :class="{active:(canvasState != 'eraser' && rgba == 'rgb(0,255,0)')}" title="back">back</div>
<div class="editFrontBack_center_btn_colorWhite" @click="setOperation('eraser')" :class="{active:canvasState == 'eraser'}" title="background">background</div>
<input type="range" v-show="canvasState != 'move'" @input="setPencilWidth" min="1" max="50" v-model="canvasPencilWidth[canvasState]">
<!-- <div class="icon iconfont icon-xiala" :class="{btnRotate:spreadState}" @click="()=>spreadState = !spreadState"></div> -->
</div>
<div class="exportCanvasBox_center_box">
<div class="exportCanvasBox_center">
<div class="editFrontBack_bgImg" v-show="loadingShow">
<img :src="imgData?.undividedLayer" alt="">
</div>
</div>
<div class="editFrontBack_pencilbtn" v-show="loadingShow" :style="pencilbtnStyle"></div>
</div>
</div>
</template>
<script>
import { defineComponent, ref, reactive, watch, onMounted, nextTick, toRefs } from "vue";
import { Https } from "@/tool/https";
import { formatTime,segmentImage } from "@/tool/util";
import { setCookie, getCookie } from "@/tool/cookie";
import { Modal, message } from "ant-design-vue";
import { ExclamationCircleOutlined } from "@ant-design/icons-vue";
import allOrder from "@/component/Pay/allOrder.vue";
import creditsDetail from "@/component/Pay/creditsDetail.vue";
import { exportSele,JSRectUpdata,JSchangeType,JScanvasMouseDown,JSSetRemoveImage,JScreateCheck,JSSetTexture } from "@/tool/canvasDrawing";
import { getMousePosition } from "@/tool/mdEvent";
import { useI18n } from "vue-i18n";
import canvasGeneral from "@/tool/canvasGeneral";
export default defineComponent({
components: {
creditsDetail,
allOrder,
},
// emits: ['setSloganData'],
props:['patchData','imgDomIndex'],
setup(props,{emit}) {
let presentState = ref('paypal');
let loadingShow = ref(false);
let { t } = useI18n();
let canvas = reactive({});
let ratio = [1,1]
let exportWH = 0
let imgDomIndex = 0
let imgData = ref()
let pencilbtnStyle = ref({
background:'',
width:0+'px',
height:0+'px',
display:'none',
left:0+'px',
top:0+'px',
})
// let a = computed(()=>{
// console.log(123);
// return props.patchData
// })
watch(()=>props.imgDomIndex,(newVal,oldVal)=>{
if(newVal == -1) return
imgDomIndex = newVal
props.patchData.front.imageUrl= ''
clearTimeout(setTimeSubmit)
init(props.patchData.front[newVal],'')
})
let canvasBtn = reactive({
canvasState:'move',
canvasPencilWidth:{
pencil:20,
eraser:20,
},
spreadState:false,
})
let canvasWH = ref(0);
let exportUrl = ''
let reverseCanvasState = ref([])//存放canvas操作
let normalCanvasState = ref([])//存放canvas操作
let canvasState = ref()//存放canvas操作
let keyDown = []//监听键盘的 keydown 和 keyup 事件
let init = (data,index)=>{
normalCanvasState.value = []
reverseCanvasState.value = []
ratio = [1,1]
imgData.value = data
nextTick(()=>{
let canvasBox = document.querySelector(".editFrontBack_center .exportCanvasBox_center");
let editFrontBack_bgImg = document.querySelector(".editFrontBack_center .editFrontBack_bgImg");
document.addEventListener("keydown", canvasKeyDown);
document.addEventListener("keyup", canvasKeyUp);
document.removeEventListener('mousemove', mouseMove);
document.removeEventListener('touchmove', touchmove);
let img = new Image();
img.onload = async function(){
loadingShow.value = true
let height = canvasBox.offsetHeight;
canvasWH.value = height
canvasBox.style.width = height+'px'
let wScale = 1
let hScale = 1
let styleWidth = Number(data.style.width.split('px')[0])
let styleHeight = Number(data.style.height.split('px')[0])
if(styleWidth>styleHeight){
hScale = styleHeight/styleWidth
exportWH = img.width
}else{
wScale = styleWidth/styleHeight
exportWH = img.height
}
editFrontBack_bgImg.style.width = canvasWH.value * wScale+'px'
editFrontBack_bgImg.style.height = canvasWH.value * hScale+'px'
ratio = [wScale,hScale]
canvas = canvasGeneral.canvasInit(canvasBox,{
width:canvasWH.value * wScale,
height:canvasWH.value * hScale,
})
pencilbtnStyle.value.background = rgba.value
fabric.Object.prototype.cornerSize = 10
fabric.Object.prototype.transparentCorners = false
exportUrl = data.maskUrl
// canvas.on('mouse:wheel', opt => {
// const delta = opt.e.deltaY // 滚轮,向上滚一下是 -100向下滚一下是 100
// let zoom = canvas.getZoom() // 获取画布当前缩放值
// zoom *= 0.999 ** delta
// if (zoom > 20) zoom = 20
// if (zoom < 0.01) zoom = 0.01
// // console.log(zoom);
// canvas.zoomToPoint(
// { // 关键点
// x: opt.e.offsetX,
// y: opt.e.offsetY
// },
// zoom
// )
// opt.e.preventDefault()
// opt.e.stopPropagation()
// })
await new Promise((resolve, reject) => {
fabric.Image.fromURL(data.maskUrl, function(img) {
// 设置背景图对象的宽度和高度与 canvas 相同
img.scaleToWidth(canvas.width);
img.scaleToHeight(canvas.height);;
img.set({
// width: canvas.width,
// height: canvas.height,
// scaleX:2,
// scaleY:1,
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
// 将背景图添加到 canvas 的底层
// canvas.add(img);
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));
if(!fabric.Object.prototype.controls.deleteControl){
JSSetRemoveImage(deleteObj)
}else{
fabric.Object.prototype.controls.deleteControl.mouseUpHandler = deleteObj
}
setPencilWidth()
updateCanvasState()
resolve('')
},{ crossOrigin: "Anonymous" });
})
// 鼠标抬起事件
canvas.on('mouse:up', function(event) {
if(canvasBtn.canvasState != 'move'){
updateCanvasState('mouseUp')
}
});
//画布上移动
// canvas.on("mouse:move", event =>setCanvasMove(event));
document.addEventListener('mousemove', mouseMove);
document.addEventListener('touchmove', touchmove);
setOperation('pencil')
createSetTimeSubmit()
img.remove()
}
img.src = data.maskUrl
})
}
let canvasKeyDown = (event) => {
if(keyDown.indexOf(event.key)>-1){
}else{
keyDown.push(event.code)
if(keyDown.indexOf('ControlLeft') > -1 && keyDown.indexOf('KeyZ') > -1 && keyDown.indexOf('ShiftLeft') > -1){
historyState('reverse')
}else if(keyDown.indexOf('ControlLeft') > -1 && keyDown.indexOf('KeyZ') > -1){
historyState('')
}
}
}
let canvasKeyUp = (event) =>{
keyDown = keyDown.filter(function(item) {
return event.code !== item;
})
}
let setClone = ()=>{
let canvasBox = document.querySelector(".editFrontBack_center .exportCanvasBox_center");
let oldCanvasDom = canvasBox.querySelector('.canvas-container')
let oldCanvasDom1 = canvasBox.querySelector('canvas')
if(oldCanvasDom)oldCanvasDom.remove()
if(oldCanvasDom1)oldCanvasDom1.remove()
loadingShow.value = false
}
let clearCanvas = ()=>{
document.removeEventListener("keydown", canvasKeyDown);
document.removeEventListener("keyup", canvasKeyUp);
}
let rgba = ref('rgb(255,0,0)')
let mouseMove = (event)=>{
let e = getMousePosition(event,false)
setCanvasMove(e)
}
let touchmove = (event)=>{
let e = getMousePosition(event,true)
setCanvasMove(e)
}
let setCanvasMove = (event)=>{
if(canvas.isDrawingMode){
canvas.setCursor('none');
}
let canvasCenterBox = document.querySelector(".editFrontBack_center .exportCanvasBox_center_box");
if(!canvasCenterBox)return
let parentX = event.clientX - canvasCenterBox.getBoundingClientRect().left
let parentY = event.clientY - canvasCenterBox.getBoundingClientRect().top
pencilbtnStyle.value.left = parentX + "px"
pencilbtnStyle.value.top = parentY+'px'
}
let setOperation = (str)=>{
if(!canvas)return
canvasBtn.canvasState = str
if(str == 'move'){
setMove()
pencilbtnStyle.value.display = `none`
}else if(str == 'pencil'){
setPencil()
pencilbtnStyle.value.display = `block`
}else if(str == 'eraser'){
setEraser()
// rgba.value = 'rgb(255,255,255)'
pencilbtnStyle.value.display = `block`
}
}
let setOperationColor = (color)=>{
pencilbtnStyle.value.background = color
rgba.value = color
canvas.freeDrawingBrush.color = color
setOperation('pencil')
}
let setMove = ()=>{
canvas.isDrawingMode = false
canvas.forEachObject((obj) =>obj.selectable = true);
}
let setPencil = ()=>{
canvas.isDrawingMode = true//开启绘画模式
canvas.freeDrawingBrush = new fabric.PencilBrush(canvas,{});
canvas.freeDrawingBrush.width = Number(canvasBtn.canvasPencilWidth[canvasBtn.canvasState]);
setPencilWidth()
canvas.freeDrawingBrush.color = rgba.value
pencilbtnStyle.value.background = rgba.value
canvas.freeDrawingBrush.isEraser = false
}
let setEraser = ()=>{
canvas.isDrawingMode = true
let eraser = new fabric.EraserBrush(canvas)
canvas.freeDrawingBrush = eraser
pencilbtnStyle.value.background = `rgb(255,255,255)`
canvas.requestRenderAll();
canvas.freeDrawingBrush.isEraser = true
canvas.freeDrawingBrush.width = Number(canvasBtn.canvasPencilWidth[canvasBtn.canvasState]);
setPencilWidth()
}
let deleteObj = ()=> {
// if(!canvas.getActiveObjects()){
// return
// }
let target = canvas.getActiveObjects()
target.forEach((item)=>{
canvas.fxRemove(item, {
onComplete(){
canvas.discardActiveObject(); // 丢弃当前选中的对象
canvas.renderAll(); // 重新渲染 Canvas
}
})
canvas.FX_DURATION = 300
})
}
let setTimeOutWidth
let setPencilWidth = ()=>{//切换颜色给铅笔设置颜色
clearTimeout(setTimeOutWidth)
setTimeOutWidth = setTimeout(()=>{
canvas.freeDrawingBrush.width = Number(canvasBtn.canvasPencilWidth[canvasBtn.canvasState])
pencilbtnStyle.value.height = canvasBtn.canvasPencilWidth[canvasBtn.canvasState]+'px'
pencilbtnStyle.value.width = canvasBtn.canvasPencilWidth[canvasBtn.canvasState]+'px'
},300)
}
let setTimeSubmit = null
let createSetTimeSubmit = ()=>{
setSubmit()
}
let updateCanvasState = (str) =>{
if(str != 'mouseUp'){
// editFrontBackPencilbtn.value.style.display = 'none'
}else{
clearTimeout(setTimeSubmit)
setTimeSubmit = setTimeout(()=>{
createSetTimeSubmit()
},1000)
}
const canvasAsJson = JSON.stringify(canvas.toJSON());
normalCanvasState.value.push(canvasAsJson);
}
//撤回
let historyState = (str)=> {
if(str == 'reverse' && reverseCanvasState.value.length > 0){//反撤回
let obj = reverseCanvasState.value.pop()
// canvasState.value = reverseCanvasState.value[reverseCanvasState.value.length-1]
canvasState.value = obj
normalCanvasState.value.push(obj);
}else if(str == '' && normalCanvasState.value.length > 1){
let obj = normalCanvasState.value.pop()
canvasState.value = normalCanvasState.value[normalCanvasState.value.length-1]
reverseCanvasState.value.push(obj);
}else{
return
}
canvas.loadFromJSON(canvasState.value, () => {
createSetTimeSubmit()
});
}
let setSubmit = ()=>{
var allObjects = canvas.getObjects('path');
var canvasDom = document.createElement("canvas");
let exportCanvas = new fabric.Canvas(canvasDom, {
width: exportWH * ratio[0],
height: exportWH * ratio[1],
isDrawingMode: false, // 开启绘图模式
});
canvas.backgroundImage.clone((back)=>{
back.scaleToWidth(exportCanvas.width);
back.scaleToHeight(exportCanvas.height);
back.set({
scaleX: exportCanvas.width / back.width,
scaleY: exportCanvas.height / back.height
})
let scale = exportCanvas.height/canvas.height
exportCanvas.backgroundImage = back
allObjects.forEach((item,index)=>{
// let obj = fabric.util.object.clone(item);
if(item.type == 'circle')return
let obj
item.clone((cloned)=>{
obj = cloned
})
obj.set(
{
scaleX:(item.scaleX?item.scaleX:1)*scale,
scaleY:(item.scaleY?item.scaleY:1)*scale,
left:item.left*scale,
top:item.top*scale,
}
)
exportCanvas.add(obj)
})
let data = exportCanvas.toDataURL('png')
cancelDsign()
clearCanvas()
// props.props.patchData.front[imgDomIndex].imageUrl = data
let mark = data
let full = props.patchData.front[imgDomIndex].undividedLayer
let size = {
width: Math.round(exportWH * ratio[0]),
height: Math.round(exportWH * ratio[1]),
}
segmentImage(mark,full,size).then((rv)=>{
// console.log(rv.targetFrontUrl,rv.targetBackUrl)
props.patchData.front[imgDomIndex].imageUrl = rv.targetFrontUrl
props.patchData.back[imgDomIndex].imageUrl = rv.targetBackUrl
props.patchData.front[imgDomIndex].maskUrl = data
})
return
})
}
let cancelDsign = ()=>{
document.removeEventListener('keydown',canvasKeyDown);
document.removeEventListener('keyup', canvasKeyUp);
}
return {
presentState,
loadingShow,
imgData,
pencilbtnStyle,
t,
...toRefs(canvasBtn),
rgba,
init,
setOperation,
setOperationColor,
setPencilWidth,
historyState,
setSubmit,
setClone,
cancelDsign,
};
},
data() {
return {
};
},
mounted() {},
methods: {
},
});
</script>
<style lang="less" scoped>
.editFrontBack_center{
position: relative;
// width: calc(512px / 2);
// width: 256px;
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
// height: calc(512px / 2);
margin: 0 auto;
.editFrontBack_center_item{
// position: relative;
background: #fff;
position: absolute;
display: flex;
border: 0.2rem solid #c4c4c4;
width: 35rem;
border-radius: 4px; /* 设置圆角半径 */
flex-wrap: wrap;
align-items: center;
.editFrontBack_center_btn_item{
display: flex;
align-items: center;
padding: 1rem 0;
}
}
.editFrontBack_center_btn{
z-index: 2;
left: 50%;
// transform: translate(-50%,-135%);
// transition: all .3s;
padding: 1rem 1.5rem;
transform: translate(-50%,0);
position: relative;
width: 100%;
flex-direction: row;
input{
// width: 100%;
flex: 1;
max-width: 30%;
}
.icon-xiala{
position: absolute;
width: 2rem;
bottom: 0;
transform: translate(-50%, 90%);
left: 50%;
width: 6rem;
background: #fff;
text-align: center;
cursor: pointer;
&.icon-xiala::before{
transition: all .3s;
}
&.btnRotate::before{
transform: rotate(180deg);
display: block;
}
}
.editFrontBack_center_btn_colorRed,.editFrontBack_center_btn_colorGreen,.editFrontBack_center_btn_colorWhite{
width: 9rem;
line-height: 3rem;
text-align: center;
height: 3rem;
border-radius: 4px;
margin: 0 .5rem;
cursor: pointer;
padding: .5rem 1;
border: 1px solid rgba(0,0,0,.5);
&.active{
border: 2px solid;
border-radius: .4rem;
}
}
.editFrontBack_center_btn_colorRed{
background: rgba(255,0,0);
}
.editFrontBack_center_btn_colorGreen{
background: rgba(0,255,0);
}
.editFrontBack_center_btn_colorWhite{
background: rgba(255,255,255);
}
i{
font-size: 2.5rem;
cursor: pointer;
width: 4rem;
height: 4rem;
display: flex;
align-items: center;
justify-content: center;
&.active{
border: 1px solid;
border-radius: .4rem;
}
}
&.spread{
transform: translate(-50%,0);
}
}
.exportCanvasBox_center_box{
padding: 3rem;
height: 100%;
flex: 1;
position: relative;
overflow: hidden;
width: 100%;
background: #e6e6e6;
&:hover{
cursor: none;
}
.editFrontBack_pencilbtn{
position: absolute;
z-index: 1;
border-radius: 50%;
border: 1px solid #000;
pointer-events: none;
transform: translate(-50%,-50%);
}
}
.exportCanvasBox_center{
margin: 0 auto;
overflow: hidden;
height: 100%;
position: relative;
// overflow: scroll;
:deep(.canvas-container){
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
opacity: .5;
// background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC);
}
.editFrontBack_bgImg{
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
img{
height: 100%;
width: 100%;
}
}
}
.exportCanvasBox_center:hover{
.editFrontBack_center_btn{
transform: translate(-50%,-101%);
&.spread{
transform: translate(-50%,0);
}
}
}
}
</style>