504 lines
14 KiB
Vue
504 lines
14 KiB
Vue
<template>
|
|
<a-modal
|
|
class="clearSlogan_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="clearSlogan_center">
|
|
<div class="modal_title_text">
|
|
<div>{{ $t('createSlogan.title') }}</div>
|
|
<div class="modal_title_text_intro"></div>
|
|
</div>
|
|
<div class="exportCanvasBox_center">
|
|
<div v-show="textBtnShow" class="clearSlogan_center_item clearSlogan_center_btn_move">
|
|
<div class="clearSlogan_center_btn_item">
|
|
<div>{{ $t('createSlogan.Color') }}</div>
|
|
<input type="color" v-model="fill">
|
|
</div>
|
|
<!-- <div class="clearSlogan_center_btn_item">
|
|
<div>font Size</div>
|
|
<input type="Number" v-model="fontSize">
|
|
</div> -->
|
|
<div class="clearSlogan_center_btn_item">
|
|
<div>{{ $t('createSlogan.FontAlign') }}</div>
|
|
<ul>
|
|
<i class="fi fi-br-align-left" @click="setTextData('textAlign','left')" :class="{active:textAlign === 'left'}"></i>
|
|
<i class="fi fi-br-align-center" @click="setTextData('textAlign','center')" :class="{active:textAlign === 'center'}"></i>
|
|
<i class="fi fi-br-symbol" @click="setTextData('textAlign','right')" :class="{active:textAlign === 'right'}"></i>
|
|
</ul>
|
|
</div>
|
|
<div class="clearSlogan_center_btn_item">
|
|
<div>{{ $t('createSlogan.FontStyle') }}</div>
|
|
<ul>
|
|
<i class="fi fi-br-border-top" @click="setTextData('overline','')" :class="{active:overline}"></i>
|
|
<i class="fi fi-br-border-center-h" @click="setTextData('linethrough','')" :class="{active:linethrough}"></i>
|
|
<i class="fi fi-br-border-bottom" @click="setTextData('underline','')" :class="{active:underline}"></i>
|
|
</ul>
|
|
|
|
</div>
|
|
<div class="clearSlogan_center_btn_item">
|
|
<div>{{ $t('createSlogan.FontFamily') }}</div>
|
|
<select v-model="fontFamily" :style="{'font-family':fontFamily}">
|
|
<option v-for="item in textFontFamilyList" :style="{'font-family':item.value}" :value="item.value">{{item.name}}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="clearSlogan_center_btn clearSlogan_center_item">
|
|
<div @click="setTextFun('')" class="clearSlogan_center_btn_item">
|
|
<div>{{ $t('createSlogan.add') }}</div>
|
|
</div>
|
|
<div @click="removeTextFun()" class="clearSlogan_center_btn_item">
|
|
<div>{{ $t('createSlogan.delete') }}</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="exportCanvasBox_submit" @click="setSubmit">
|
|
<div class="started_btn">
|
|
{{ $t('createSlogan.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 { JSSetRemoveImage } 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 textBtnShow = ref(false)
|
|
let { t } = useI18n();
|
|
let canvas = reactive({});
|
|
let scale = 2;
|
|
let exportWH = 512
|
|
let canvasWH = ref(0);
|
|
let isDeleteSlogan = ref(false)
|
|
let textData = reactive({
|
|
fill:'#000000',
|
|
fontSize:'51',
|
|
fontFamily:'Arial',
|
|
textAlign:'left',
|
|
overline: false,
|
|
linethrough: false,
|
|
underline: false,
|
|
})
|
|
onMounted(()=>{
|
|
let arr = [
|
|
{ value: 'Arial', name: 'select font' },
|
|
{ value: 'EN_slogan_art1', name: 'select font' },
|
|
{ value: 'EN_slogan_art2', name: 'select font' },
|
|
{ value: 'EN_slogan_art3', name: 'select font' },
|
|
{ value: 'EN_slogan_art4', name: 'select font' },
|
|
{ value: 'EN_slogan_art5', name: 'select font' },
|
|
{ value: 'EN_slogan_art6', name: 'select font' },
|
|
{ value: 'EN_slogan_art7', name: 'select font' },
|
|
{ value: '微软雅黑', name: '请选择字体' },
|
|
{ value: 'CN_slogan_art1', name: '请选择字体' },
|
|
{ value: 'CN_slogan_art2', name: '请选择字体' },
|
|
{ value: 'CN_slogan_art3', name: '请选择字体' },
|
|
{ value: 'CN_slogan_art4', name: '请选择字体' },
|
|
{ value: '华文行楷', name: '请选择字体' },
|
|
{ value: '隶书', name: '请选择字体' },
|
|
]
|
|
textDataList.textFontFamilyList = arr
|
|
textData.fontFamily = arr[0].value
|
|
})
|
|
let textDataList = reactive({
|
|
textFontFamilyList: [],
|
|
})
|
|
|
|
let init = ()=>{
|
|
showPayOrder.value = true;
|
|
nextTick(()=>{
|
|
let canvasBox = document.querySelector(".clearSlogan_modal .exportCanvasBox_center");
|
|
let height = canvasBox.offsetHeight;
|
|
textData.fontSize = (height/10*1.9).toFixed(0)
|
|
canvasBox.style.width = height+'px'
|
|
canvasWH.value = height
|
|
scale = exportWH/canvasWH.value
|
|
let oldCanvasDom = canvasBox.querySelector('.canvas-container')
|
|
let oldCanvasDom1 = canvasBox.querySelector('canvas')
|
|
if(isDeleteSlogan.value && oldCanvasDom){
|
|
oldCanvasDom.remove()
|
|
canvas.remove(textbox);
|
|
canvas.dispose();
|
|
oldCanvasDom = null
|
|
isDeleteSlogan.value = false
|
|
}
|
|
if(oldCanvasDom1){
|
|
oldCanvasDom1.remove()
|
|
}
|
|
// if(oldCanvasDom)oldCanvasDom.remove()
|
|
if(!oldCanvasDom){
|
|
var canvasDom = document.createElement("canvas");
|
|
canvasBox.appendChild(canvasDom);
|
|
canvas = new fabric.Canvas(canvasDom, {
|
|
backgroundColor: "#e6e6e6",
|
|
width: canvasWH.value,
|
|
height: canvasWH.value,
|
|
isDrawingMode: false, // 开启绘图模式
|
|
});
|
|
canvas.on('object:moving',canvasMoving)
|
|
setTextFun('请输入\n一段话吧~')
|
|
}
|
|
|
|
if(!fabric.Object.prototype.controls.deleteControl){
|
|
JSSetRemoveImage(deleteObj)
|
|
}else{
|
|
fabric.Object.prototype.controls.deleteControl.mouseUpHandler = deleteObj
|
|
}
|
|
// setRemoveImage()
|
|
fabric.Object.prototype.cornerSize = 10
|
|
fabric.Object.prototype.transparentCorners = false
|
|
canvas.on('mouse:down',setTextBtn)
|
|
})
|
|
}
|
|
let selectTextbox = ref(null)
|
|
let oldClickedObject = null
|
|
let clickObjChanged = (options)=>{
|
|
// var changedObject = options.target;
|
|
setBtnPosition(oldClickedObject)
|
|
|
|
}
|
|
let clickedObject
|
|
let setTextBtn = (e) =>{//点击判断是否点击到文字
|
|
clickedObject = e.target;
|
|
if (clickedObject instanceof fabric.IText){
|
|
if(oldClickedObject)oldClickedObject.off('changed',clickObjChanged);
|
|
selectTextbox.value = clickedObject
|
|
textData.fill = clickedObject.fill
|
|
textData.fontSize = clickedObject.fontSize
|
|
textData.fontFamily = clickedObject.fontFamily
|
|
textData.textAlign = clickedObject.textAlign
|
|
textData.overline = clickedObject.overline
|
|
textData.linethrough = clickedObject.linethrough
|
|
textData.underline = clickedObject.underline
|
|
setBtnPosition(clickedObject)
|
|
clickedObject.on('changed',clickObjChanged);
|
|
oldClickedObject = clickedObject
|
|
}else{
|
|
selectTextbox.value = null
|
|
textBtnShow.value = false
|
|
}
|
|
}
|
|
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 messageShow = false
|
|
let canvasMoving = (options)=>{
|
|
let obj = options.target
|
|
let left,top
|
|
let canvasWidth = canvas.getWidth()
|
|
let canvasHeight = canvas.getHeight()
|
|
if(obj.left < 0){
|
|
left = obj.left<0?0:obj.left
|
|
}else{
|
|
left = obj.left + obj.width*obj.scaleX>canvasWidth?canvasWidth - obj.width*obj.scaleX:obj.left
|
|
}
|
|
if(obj.top < 0){
|
|
top = obj.top<0?0:obj.top
|
|
}else{
|
|
top = obj.top + obj.height*obj.scaleY>canvasHeight?canvasHeight - obj.height*obj.scaleY:obj.top
|
|
}
|
|
obj.set({
|
|
left,
|
|
top
|
|
})
|
|
isCanvasMoving(obj)
|
|
}
|
|
let isCanvasMoving = (obj)=>{
|
|
canvas.forEachObject(function(options) {
|
|
setBtnPosition(obj)
|
|
if(messageShow) return
|
|
if (options === obj) return
|
|
// 检查对象是否与另一个对象相交
|
|
if (obj.intersectsWithObject(options)) {
|
|
messageShow = true
|
|
message.info(t('Generate.jsContent11'),()=>{
|
|
messageShow = false
|
|
});
|
|
}
|
|
})
|
|
}
|
|
let setBtnPosition = (obj)=>{//传入文字对象,设置工具位置
|
|
let domXY = {x:0,y:0}
|
|
textBtnShow.value = true
|
|
let scaleY = obj.scaleY?obj.scaleY:1
|
|
domXY = {
|
|
y:obj.top+obj.height * scaleY,
|
|
x:obj.left,
|
|
}
|
|
let dom = document.querySelector('.clearSlogan_modal .clearSlogan_center_btn_move')
|
|
domXY.x = domXY.x<0?0:domXY.x
|
|
dom.style.left = domXY.x+'px'
|
|
dom.style.top = (domXY.y + 5)+'px'
|
|
}
|
|
let textbox
|
|
let setTextFun = (str)=>{
|
|
textbox = new fabric.IText(str, {
|
|
fontSize: 20,
|
|
textAlign:'center'
|
|
// fill:canvasPencilColor.value,
|
|
})
|
|
textbox.set(textData)
|
|
textbox.set({
|
|
left:canvasWH.value/2 - textbox.width / 2,
|
|
top:canvasWH.value/2 - textbox.height / 2,
|
|
})
|
|
setBtnPosition(textbox)
|
|
canvas.add(textbox)
|
|
isCanvasMoving(textbox)
|
|
textbox.enterEditing();
|
|
canvas.setActiveObject(textbox).renderAll();
|
|
selectTextbox.value = textbox
|
|
}
|
|
let removeTextFun = ()=>{
|
|
let selectObj = canvas.getActiveObjects();
|
|
if(selectObj){
|
|
selectObj.forEach(function(object) {
|
|
canvas.remove(object);
|
|
textBtnShow.value = false
|
|
});
|
|
}
|
|
}
|
|
let watchTime
|
|
watch(textData,(newValue,oldValue)=>{
|
|
clearTimeout(watchTime)
|
|
watchTime = setTimeout(()=>{
|
|
if(selectTextbox.value){
|
|
selectTextbox.value.set(newValue)
|
|
canvas.renderAll();
|
|
}
|
|
},500)
|
|
|
|
})
|
|
let setTextData = (name,value)=>{
|
|
textData[name] = value?value:!textData[name]
|
|
}
|
|
let setSubmit = ()=>{
|
|
var allObjects = canvas.getObjects();
|
|
if(allObjects.length == 0){
|
|
message.info(t('Generate.jsContent12'))
|
|
return
|
|
}
|
|
var canvasDom = document.createElement("canvas");
|
|
let exportCanvas = new fabric.Canvas(canvasDom, {
|
|
backgroundColor: "rgba(255, 255, 255,0)",
|
|
width: canvasWH.value*scale,
|
|
height: canvasWH.value*scale,
|
|
isDrawingMode: false, // 开启绘图模式
|
|
});
|
|
let canvasArr = canvas.getObjects()
|
|
canvasArr.forEach(item=>{
|
|
// let obj = fabric.util.object.clone(item);
|
|
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)
|
|
})
|
|
// textbox.set({
|
|
// left:canvasWH.value.width/2 - textbox.width / 2,
|
|
// top:canvasWH.value.height/2 - textbox.height / 2,
|
|
// })
|
|
let data = [{
|
|
imgUrl : exportCanvas.toDataURL('png'),
|
|
base64:true
|
|
}]
|
|
emit('setSloganData',data)
|
|
showPayOrder.value = false;
|
|
// console.log(exportCanvas.toDataURL('png') );
|
|
}
|
|
let cancelDsign = ()=>{
|
|
canvas.off('object:moving',canvasMoving)
|
|
if(oldClickedObject)oldClickedObject.off('changed',clickObjChanged);
|
|
if(clickedObject)clickedObject.off('changed',clickObjChanged);
|
|
canvas.off('mouse:down',setTextBtn)
|
|
canvas.dispose();
|
|
showPayOrder.value = false
|
|
}
|
|
return {
|
|
presentState,
|
|
showPayOrder,
|
|
loadingShow,
|
|
...toRefs(textData),
|
|
...toRefs(textDataList),
|
|
textBtnShow,
|
|
isDeleteSlogan,
|
|
t,
|
|
init,
|
|
setTextFun,
|
|
removeTextFun,
|
|
setTextData,
|
|
setSubmit,
|
|
cancelDsign,
|
|
};
|
|
},
|
|
data() {
|
|
return {
|
|
};
|
|
},
|
|
mounted() {},
|
|
methods: {
|
|
|
|
|
|
|
|
},
|
|
});
|
|
</script>
|
|
<style lang="less">
|
|
.clearSlogan_modal {
|
|
.closeIcon {
|
|
z-index: 2;
|
|
}
|
|
.clearSlogan_center{
|
|
position: relative;
|
|
// width: calc(512px / 2);
|
|
// width: 256px;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-direction: column;
|
|
// height: calc(512px / 2);
|
|
margin: 0 auto;
|
|
.modal_title_text{
|
|
padding-bottom: calc(2rem* 1.2);
|
|
background: #fff;
|
|
z-index: 4;
|
|
margin-bottom: 0;
|
|
}
|
|
.clearSlogan_center_item{
|
|
// position: relative;
|
|
background: #fff;
|
|
position: absolute;
|
|
|
|
display: flex;
|
|
border: 0.2rem solid #c4c4c4;
|
|
width: 25rem;
|
|
border-radius: 4px; /* 设置圆角半径 */
|
|
flex-wrap: wrap;
|
|
.clearSlogan_center_btn_item{
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 1rem 0;
|
|
>*{
|
|
cursor: pointer;
|
|
}
|
|
>input{
|
|
width: 4rem;
|
|
height: 2.5rem;
|
|
border-radius: 4px; /* 设置圆角半径 */
|
|
}
|
|
input::-webkit-inner-spin-button,
|
|
input::-webkit-outer-spin-button {
|
|
-webkit-appearance: none;
|
|
margin: 0;
|
|
}
|
|
div{
|
|
padding: 0 1rem;
|
|
font-weight: 600;
|
|
}
|
|
ul{
|
|
display: flex;
|
|
margin: 0;
|
|
i{
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 2.5rem;
|
|
cursor: pointer;
|
|
width: 4rem;
|
|
height: 4rem;
|
|
&.active{
|
|
border: 1px solid;
|
|
border-radius: 0.4rem;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.clearSlogan_center_btn{
|
|
top: 0px;
|
|
left: 50%;
|
|
width: auto;
|
|
transition: all 0.3s;
|
|
transform: translate(-50%,-100%);
|
|
}
|
|
.exportCanvasBox_center:hover .clearSlogan_center_btn{
|
|
transform: translate(-50%,0%);
|
|
z-index: 4;
|
|
}
|
|
.clearSlogan_center_btn_move{
|
|
position: absolute;
|
|
z-index: 2;
|
|
}
|
|
.exportCanvasBox_center{
|
|
height: 100%;
|
|
flex: 1;
|
|
position: relative;
|
|
margin: 0 auto;
|
|
// overflow: hidden;
|
|
// overflow: scroll;
|
|
.canvas-container{
|
|
margin: 0 auto;
|
|
}
|
|
}
|
|
}
|
|
.exportCanvasBox_submit{
|
|
margin-top: 2.4rem;
|
|
text-align: center;
|
|
}
|
|
}
|
|
</style> |