486 lines
14 KiB
Vue
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> |