Files
aida_front/src/component/Detail/addDetails.vue
2024-07-12 15:54:46 +08:00

486 lines
14 KiB
Vue

<template>
<a-modal
class="addDetails_modal generalModel"
v-model:visible="showPayOrder"
:footer="null"
width="50%"
:maskClosable="false"
:centered="true"
:closable="false"
wrapClassName="#app"
:keyboard="false"
>
<div class="generalModel_btn">
<div class="generalModel_closeIcon" @click.stop="cancelDsign()">
<i class="fi fi-rr-cross-small"></i>
</div>
</div>
<div class="addDetails_center">
<div class="modal_title_text">
<div>{{ $t('addDetails.AddDetails') }}</div>
<div class="modal_title_text_intro"></div>
</div>
<div class="exportCanvasBox_center">
<div class="addDetails_center_btn addDetails_center_item" :class="{spread:spreadState}">
<!-- <div @click="setOperation('')" class="addDetails_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>
<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>
<div class="exportCanvasBox_submit" @click="setSubmit">
<div class="started_btn">
{{ $t('addDetails.submit') }}
</div>
</div>
</div>
<div></div>
</a-modal>
<div class="mark_loading" v-show="loadingShow">
<a-spin size="large" />
</div>
</template>
<script>
import { defineComponent, ref, reactive, watch, onMounted, nextTick, toRefs } from "vue";
import { Https } from "@/tool/https";
import { formatTime } 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 { useI18n } from "vue-i18n";
export default defineComponent({
components: {
creditsDetail,
allOrder,
},
emits: ['setSloganData'],
setup(props,{emit}) {
let presentState = ref('paypal');
let showPayOrder = ref(false);
let loadingShow = ref(false);
let { t } = useI18n();
let canvas = reactive({});
let scale = 2;
let ratio = [1,1]
let exportWH = 512
let canvasBtn = reactive({
canvasState:'move',
canvasPencilWidth:{
pencil:4,
eraser:4,
},
spreadState:false,
})
let canvasWH = ref(0);
onMounted(()=>{
})
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 = []
showPayOrder.value = true;
loadingShow.value = true
scale = 2;
ratio = [1,1]
exportWH = 512
nextTick(()=>{
let canvasBox = document.querySelector(".addDetails_modal .exportCanvasBox_center");
let height = canvasBox.offsetHeight;
canvasBox.style.width = height+'px'
canvasWH.value = height
var canvasDom = document.createElement("canvas");
document.addEventListener("keydown", canvasKeyDown);
document.addEventListener("keyup", canvasKeyUp);
let oldCanvasDom = canvasBox.querySelector('.canvas-container')
if(oldCanvasDom)oldCanvasDom.remove()
canvasBox.appendChild(canvasDom);
let img = new Image();
img.onload = function(){
let wScale = 1
let hScale = 1
if(img.width>img.height){
hScale = img.height/img.width
exportWH = img.width
}else{
wScale = img.width/img.height
exportWH = img.height
}
ratio = [wScale,hScale]
canvas = new fabric.Canvas(canvasDom, {
backgroundColor: "#FFF",
width: canvasWH.value * wScale,
height: canvasWH.value * hScale,
isDrawingMode: false, // 开启绘图模式
});
scale = img.height/canvas.height
JSchangeType(canvas,'init')
fabric.Object.prototype.cornerSize = 10
fabric.Object.prototype.transparentCorners = false
exportUrl = data.path
fabric.Image.fromURL(data.path, function(img) {
// 设置背景图对象的宽度和高度与 canvas 相同
img.scaleToWidth(canvas.width);
img.scaleToHeight(canvas.height);
// 将背景图添加到 canvas 的底层
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas));
if(!fabric.Object.prototype.controls.deleteControl){
JSSetRemoveImage(deleteObj)
}else{
fabric.Object.prototype.controls.deleteControl.mouseUpHandler = deleteObj
}
updateCanvasState()
},{ crossOrigin: "Anonymous" });
// 鼠标抬起事件
canvas.on('mouse:up', function(event) {
if(canvasBtn.canvasState != 'move'){
updateCanvasState('mouseUp')
}
});
//画布上移动
canvas.on("mouse:move", event =>setCanvasMove(event));
canvas.add(brushIndicator)
loadingShow.value = false
setOperation('pencil')
img.remove()
}
img.src = data.path
})
}
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 clearCanvas = ()=>{
canvasBtn.canvasState = 'move'
canvasBtn.spreadState = false
document.removeEventListener("keydown", canvasKeyDown);
document.removeEventListener("keyup", canvasKeyUp);
}
let rgba = 'rgba(0, 0, 0, 1)'
let brushIndicator = new fabric.Circle({
radius:2,
fill: 'rgba(0, 0, 0, 0)',
stroke: '#000',
strokeWidth: 1,
originX: 'center',
originY: 'center',
visible :true,
// left: -100,
// top: -100,
erasable: false,
});
let setCanvasMove = (event)=>{
var pointer = canvas.getPointer(event.e);
if(canvas.isDrawingMode){
canvas.setCursor('none');
if(!canvas.contains(brushIndicator)){
canvas.add(brushIndicator)
brushIndicator.set({// left:0,
// top:0,
radius:(canvasBtn.canvasPencilWidth[canvasBtn.canvasState])/2
})
canvas.bringToFront(brushIndicator);//设置优先级最高
}
// brushIndicator.fill = canvasPencilColor.value
brushIndicator.set({ left: pointer.x, top: pointer.y, visible: true,radius:(canvasBtn.canvasPencilWidth[canvasBtn.canvasState])/2 });
}
canvas.requestRenderAll()
}
let setOperation = (str)=>{
canvasBtn.canvasState = str
if(str == 'move'){
setMove()
if(canvas.contains(brushIndicator))canvas.remove(brushIndicator)
}else if(str == 'pencil'){
setPencil()
if(!canvas.contains(brushIndicator))canvas.add(brushIndicator)
}else if(str == 'eraser'){
setEraser()
if(!canvas.contains(brushIndicator))canvas.add(brushIndicator)
}
}
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]);
canvas.freeDrawingBrush.color = rgba
brushIndicator.set('fill',rgba)
canvas.freeDrawingBrush.isEraser = false
}
let setEraser = ()=>{
canvas.isDrawingMode = true
let eraser = new fabric.EraserBrush(canvas)
canvas.freeDrawingBrush = eraser
brushIndicator.set({fill: '#fff'});
canvas.requestRenderAll();
canvas.freeDrawingBrush.isEraser = true
canvas.freeDrawingBrush.width = Number(canvasBtn.canvasPencilWidth[canvasBtn.canvasState]);
}
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])
},300)
}
let updateCanvasState = (str) =>{
if(str != 'mouseUp'){
canvas.remove(brushIndicator)
}
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, () => {});
}
let setSubmit = ()=>{
var allObjects = canvas.getObjects('path');
if(allObjects.length == 0){
return message.info(t('addDetails.jsContent1'))
}
var canvasDom = document.createElement("canvas");
let exportCanvas = new fabric.Canvas(canvasDom, {
backgroundColor: "rgba(255, 255, 255,1)",
width: exportWH * ratio[0],
height: exportWH * ratio[1],
isDrawingMode: false, // 开启绘图模式
});
canvas.backgroundImage.clone((back)=>{
back.set({
scaleX:1,
scaleY:1,
left:back.left*scale,
top:back.top*scale ,
})
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)
if(allObjects.length-1 == index){
let data = exportCanvas.toDataURL('jpg')
cancelDsign()
clearCanvas()
emit('setSloganData',data)
}
})
})
}
let cancelDsign = ()=>{
canvas.dispose();
showPayOrder.value = false
document.removeEventListener('keydown',canvasKeyDown);
document.removeEventListener('keyup', canvasKeyUp);
}
return {
presentState,
showPayOrder,
loadingShow,
t,
...toRefs(canvasBtn),
init,
setOperation,
setPencilWidth,
historyState,
setSubmit,
cancelDsign,
};
},
data() {
return {
};
},
mounted() {},
methods: {
},
});
</script>
<style lang="less">
.addDetails_modal {
.closeIcon {
z-index: 2;
}
.addDetails_center{
position: relative;
// width: calc(512px / 2);
// width: 256px;
height: 100%;
display: flex;
flex-direction: column;
// height: calc(512px / 2);
margin: 0 auto;
.addDetails_center_item{
// position: relative;
background: #fff;
position: absolute;
display: flex;
border: 0.2rem solid #c4c4c4;
width: 25rem;
border-radius: 4px; /* 设置圆角半径 */
flex-wrap: wrap;
.addDetails_center_btn_item{
display: flex;
align-items: center;
padding: 1rem 0;
}
}
.exportCanvasBox_center{
height: 100%;
flex: 1;
position: relative;
margin: 0 auto;
overflow: hidden;
background: #e6e6e6;
// overflow: scroll;
.addDetails_center_btn{
z-index: 2;
left: 50%;
transform: translate(-50%,-135%);
transition: all .3s;
padding: 1rem 1.5rem;
// position: relative;
input{
width: 100%;
margin-top: 1rem;
}
.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;
}
}
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);
}
}
.canvas-container{
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
}
.exportCanvasBox_center:hover{
.addDetails_center_btn{
transform: translate(-50%,-101%);
&.spread{
transform: translate(-50%,0);
}
}
}
}
.exportCanvasBox_submit{
margin-top: 2.4rem;
text-align: center;
}
}
</style>