88c6ce8ccc
- 迁移为 frontend-web、frontend-electron、backend-web 与 docker 部署结构 - 网页端:订阅门禁二次弹窗、套餐/支付组件化、顶栏分组对齐 - 首页:最近文件与模板库布局优化,缩略图对齐,下载与删除操作 - 新增管理后台、支付与云端文件 API,更新 README 与项目规范 Co-authored-by: Cursor <cursoragent@cursor.com>
5781 lines
356 KiB
JavaScript
5781 lines
356 KiB
JavaScript
|
||
function desEncrypt(str, key = "df6a551ca43181fc485f3043bcdd2fbc") {
|
||
var APIFMS;
|
||
try {
|
||
var keyHex_encrypt = CryptoJS.enc.Utf8.parse(key);
|
||
var encrypted = CryptoJS.DES.encrypt(str, keyHex_encrypt, {
|
||
mode: CryptoJS.mode.ECB,
|
||
padding: CryptoJS.pad.Pkcs7
|
||
});
|
||
APIFMS = CryptoJS.enc.Base64.stringify(encrypted.ciphertext);
|
||
} catch (err) {
|
||
console.log('des 加密 -------------------------');
|
||
console.log(err);
|
||
}
|
||
return APIFMS;
|
||
}
|
||
(function (fabric) {
|
||
fabric.CurvedText = fabric.util.createClass(fabric.Object, {
|
||
type: 'curved-text',
|
||
diameter: 0,
|
||
kerning: 0,
|
||
text: '',
|
||
flipped: false,
|
||
fill: '#000',
|
||
fontFamily: 'Times New Roman',
|
||
fontSize: 24, // in px
|
||
fontWeight: 'normal',
|
||
fontStyle: '', // "normal", "italic" or "oblique".
|
||
cacheProperties: fabric.Object.prototype.cacheProperties.concat('diameter', 'textBackgroundColor', 'kerning', 'flipped', 'fill', 'fontFamily', 'fontSize', 'fontWeight', 'fontStyle', 'strokeStyle', 'strokeWidth'),
|
||
strokeStyle: null,
|
||
strokeWidth: 0,
|
||
initialize: function (text, options) {
|
||
options || (options = {});
|
||
if (typeof text === 'object' && text) {
|
||
for (let key in text) {
|
||
this[key] = text[key]
|
||
}
|
||
} else {
|
||
this.text = text;
|
||
}
|
||
this.callSuper('initialize', options);
|
||
this.set('lockUniScaling', true);
|
||
var canvas = this.getCircularText();
|
||
this.cropCanvas(canvas);
|
||
this.set('width', canvas.width);
|
||
this.set('height', canvas.height);
|
||
},
|
||
_getFontDeclaration: function () {
|
||
return [
|
||
(fabric.isLikelyNode ? this.fontWeight : this.fontStyle),
|
||
(fabric.isLikelyNode ? this.fontStyle : this.fontWeight),
|
||
this.fontSize + 'px',
|
||
(fabric.isLikelyNode ? ('"' + this.fontFamily + '"') : this.fontFamily)
|
||
].join(' ');
|
||
},
|
||
cropCanvas: function (canvas) {
|
||
var ctx = canvas.getContext('2d'),
|
||
w = canvas.width,
|
||
h = canvas.height,
|
||
pix = { x: [], y: [] }, n,
|
||
imageData = ctx.getImageData(0, 0, w, h),
|
||
fn = function (a, b) { return a - b };
|
||
for (var y = 0; y < h; y++) {
|
||
for (var x = 0; x < w; x++) {
|
||
if (imageData.data[((y * w + x) * 4) + 3] > 0) {
|
||
pix.x.push(x);
|
||
pix.y.push(y);
|
||
}
|
||
}
|
||
}
|
||
// 如果没有找到任何非透明像素,直接返回,不进行裁剪
|
||
if (pix.x.length === 0 || pix.y.length === 0) {
|
||
return;
|
||
}
|
||
pix.x.sort(fn);
|
||
pix.y.sort(fn);
|
||
n = pix.x.length - 1;
|
||
w = pix.x[n] - pix.x[0];
|
||
h = pix.y[n] - pix.y[0];
|
||
// 确保宽度和高度是有效的正数
|
||
if (w <= 0 || h <= 0 || isNaN(w) || isNaN(h)) {
|
||
return;
|
||
}
|
||
var cut = ctx.getImageData(pix.x[0], pix.y[0], w, h);
|
||
canvas.width = w;
|
||
canvas.height = h;
|
||
ctx.putImageData(cut, 0, 0);
|
||
},
|
||
getCircularText: function () {
|
||
var text = this.text,
|
||
diameter = this.diameter,
|
||
flipped = this.flipped,
|
||
kerning = this.kerning,
|
||
fill = this.fill,
|
||
inwardFacing = true,
|
||
startAngle = 0,
|
||
canvas = fabric.util.createCanvasElement(),
|
||
ctx = canvas.getContext('2d'),
|
||
cw, // character-width
|
||
x, // iterator
|
||
clockwise = -1; // draw clockwise for aligned right. Else Anticlockwise
|
||
if (flipped) {
|
||
// startAngle = 180;
|
||
inwardFacing = false;
|
||
}
|
||
startAngle *= Math.PI / 180; // convert to radians
|
||
var d = document.createElement('div');
|
||
d.style.fontFamily = this.fontFamily;
|
||
d.style.fontSize = this.fontSize + 'px';
|
||
d.style.fontWeight = this.fontWeight;
|
||
d.style.fontStyle = this.fontStyle;
|
||
d.textContent = text;
|
||
document.body.appendChild(d);
|
||
var textHeight = d.offsetHeight;
|
||
document.body.removeChild(d);
|
||
canvas.width = canvas.height = diameter;
|
||
ctx.font = this._getFontDeclaration();
|
||
if (inwardFacing) { text = text.split('').reverse().join('') };
|
||
ctx.translate(diameter / 2, diameter / 2); // Move to center
|
||
startAngle += (Math.PI * !inwardFacing); // Rotate 180 if outward
|
||
ctx.textBaseline = 'middle'; // Ensure we draw in exact center
|
||
ctx.textAlign = 'center'; // Ensure we draw in exact center
|
||
for (x = 0; x < text.length; x++) {
|
||
cw = ctx.measureText(text[x]).width;
|
||
startAngle += ((cw + (x == text.length - 1 ? 0 : kerning)) / (diameter / 2 - textHeight)) / 2 * -clockwise;
|
||
}
|
||
ctx.rotate(startAngle);
|
||
for (x = 0; x < text.length; x++) {
|
||
cw = ctx.measureText(text[x]).width; // half letter
|
||
ctx.rotate((cw / 2) / (diameter / 2 - textHeight) * clockwise);
|
||
if (this.strokeStyle && this.strokeWidth) {
|
||
ctx.strokeStyle = this.strokeStyle;
|
||
ctx.lineWidth = this.strokeWidth;
|
||
ctx.miterLimit = 2;
|
||
ctx.strokeText(text[x], 0, (inwardFacing ? 1 : -1) * (0 - diameter / 2 + textHeight / 2));
|
||
}
|
||
ctx.fillStyle = fill;
|
||
ctx.fillText(text[x], 0, (inwardFacing ? 1 : -1) * (0 - diameter / 2 + textHeight / 2));
|
||
ctx.rotate((cw / 2 + kerning) / (diameter / 2 - textHeight) * clockwise); // rotate half letter
|
||
}
|
||
return canvas;
|
||
},
|
||
_set: function (key, value) {
|
||
switch (key) {
|
||
case 'scaleX':
|
||
this.fontSize *= value;
|
||
this.diameter *= value;
|
||
this.width *= value;
|
||
this.scaleX = 1;
|
||
if (this.width < 1) { this.width = 1; }
|
||
break;
|
||
case 'scaleY':
|
||
this.height *= value;
|
||
this.scaleY = 1;
|
||
if (this.height < 1) { this.height = 1; }
|
||
break;
|
||
default:
|
||
this.callSuper('_set', key, value);
|
||
break;
|
||
}
|
||
},
|
||
_render: function (ctx) {
|
||
var canvas = this.getCircularText();
|
||
this.cropCanvas(canvas);
|
||
this.set('width', canvas.width);
|
||
this.set('height', canvas.height);
|
||
ctx.drawImage(canvas, -this.width / 2, -this.height / 2, this.width, this.height);
|
||
this.setCoords();
|
||
},
|
||
toObject: function (propertiesToInclude) {
|
||
return this.callSuper('toObject', ['text', 'diameter', 'textBackgroundColor', 'kerning', 'flipped', 'fill', 'fontFamily', 'fontSize', 'fontWeight', 'fontStyle', 'strokeStyle', 'strokeWidth'].concat(propertiesToInclude));
|
||
}
|
||
});
|
||
fabric.CurvedText.fromObject = function (object, callback, forceAsync) {
|
||
return fabric.Object._fromObject('CurvedText', object, callback, forceAsync, 'curved-text');
|
||
};
|
||
})(typeof fabric !== 'undefined' ? fabric : require('fabric').fabric);
|
||
|
||
const remote = require('@electron/remote')
|
||
var path = require('path');
|
||
// 使用用户数据目录,避免写入需要管理员权限
|
||
const exePath = remote.app.getPath('userData')
|
||
const { ipcRenderer } = require('electron')
|
||
const { dialog } = require('@electron/remote')
|
||
var jrQrcode = require('jr-qrcode');
|
||
var JsBarcode = require('jsbarcode');
|
||
ipcRenderer.send('get-sys-fonts');
|
||
ipcRenderer.send('get-scale-rate');
|
||
const { clipboard } = require('electron')
|
||
const dpi = 600
|
||
// // 内部剪贴板
|
||
// let clipboardData = {
|
||
// objects: null,
|
||
// offset: 10 // 粘贴位置偏移量
|
||
// };
|
||
|
||
layui.use(['layer', 'slider', 'form', 'colorpicker'], function () {
|
||
let myDate = new Date();
|
||
let s_lan = "";
|
||
ipcRenderer.send('get-sys-language');
|
||
/* if(myDate.getFullYear()>2021 && myDate.getMonth() >= 1 && myDate.getDate() > 15){
|
||
|
||
}*/
|
||
function GetFile() {
|
||
const params = new URLSearchParams(window.location.search);
|
||
return params
|
||
}
|
||
function langua_ge(lan = 'zh') {
|
||
$("[language='m']").each(function (i) {
|
||
$(this).html($(this).attr(lan));
|
||
})
|
||
|
||
$("[language='t']").each(function (i) {
|
||
$(this).attr("title", $(this).attr(lan));
|
||
})
|
||
}
|
||
function language_str(str) {
|
||
let t = {
|
||
"whetherSave": { zh: "是否保存当前文件?", ozh: "是否保存當前文件?", en: "Do you want to save the current file?" },
|
||
"save": { zh: "保存", ozh: "保存", en: "Save" },
|
||
"noSave": { zh: "不保存", ozh: "不保存", en: "No saving" },
|
||
"cancel": { zh: "取消", ozh: "取消", en: "Cancel" },
|
||
"saveSucc": { zh: "保存成功至", ozh: "保存成功至", en: "Save successfully to" },
|
||
"saveFile": { zh: "保存文件", ozh: "保存文件", en: "Save file" },
|
||
"display": { zh: "预览", ozh: "預覽", en: "Display" },
|
||
"output": { zh: "导出", ozh: "導出", en: "Export" },
|
||
"bg": { zh: "背景", ozh: "背景", en: "Background" },
|
||
"selectPic": { zh: "请选择图片", ozh: "請選擇圖片", en: "Please select a picture" },
|
||
"selectPic": { zh: "请选择文件", ozh: "請選擇文件", en: "Please select a file" },
|
||
"img": { zh: "圖片", ozh: "圖片", en: "Image" },
|
||
"simg": { zh: "合成圖片", ozh: "合成圖片", en: "Synthesized Image" },
|
||
"text": { zh: "文本", ozh: "文本", en: "Text" },
|
||
"ctext": { zh: "圆形文本", ozh: "圆形文本", en: "Circle Text" },
|
||
"stext": { zh: "合成文本", ozh: "合成文本", en: "Synthesized Text" },
|
||
"rect": { zh: "矩形", ozh: "矩形", en: "Rectangle" },
|
||
"circ": { zh: "圓形", ozh: "圓形", en: "Circle" },
|
||
"line": { zh: "直線", ozh: "直線", en: "Line" },
|
||
"qrc": { zh: "二維碼", ozh: "二維碼", en: "QR code" },
|
||
"barc": { zh: "條形碼", ozh: "條形碼", en: "Barcode" },
|
||
"counter": { zh: "計數器", ozh: "计数器", en: "Counter" },
|
||
"about": { zh: "关于Soon Design", ozh: "關於Soon Design", en: "About Soon Design" },
|
||
"vers": { zh: "版本", ozh: "版本", en: "Version" },
|
||
"comf": { zh: "确认", ozh: "確認", en: "Select" },
|
||
"copyright": { zh: "© 2022 cardsoon Co., Ltd. All rights reserved.", ozh: "© 2022 cardsoon Co., Ltd. All rights reserved.", en: "© 2022 cardsoon Co., Ltd. All rights reserved." }
|
||
}
|
||
return t[str][s_lan];
|
||
}
|
||
|
||
var $ = layui.$;
|
||
var layer = layui.layer
|
||
, slider = layui.slider, colorpicker = layui.colorpicker;
|
||
let addState = 0;//0是不添加
|
||
let background_image, background_image1, background_image2;
|
||
let bg_version = 1;//front_bg1.png front_bg2.png
|
||
var zoom = 1;
|
||
$(function () {
|
||
// 定义CurvedText类
|
||
|
||
|
||
$("#object_attribute").css("height", "470px");
|
||
$("#obj_list").css("height", document.body.clientHeight - 520);
|
||
$(".obj_list").css("height", $("#obj_list").height() - 32);
|
||
|
||
$(".main").show();
|
||
$(".canvas_box").css("height", document.body.clientHeight - 100);
|
||
zoom = $(".canvas_bg_img").width() / 2787
|
||
$("#canvas1").attr("width", $(".canvas_box").width() / zoom);
|
||
$("#canvas1").attr("height", $(".canvas_box").height() / zoom);
|
||
$("#canvas2").attr("width", $(".canvas_box").width() / zoom);
|
||
$("#canvas2").attr("height", $(".canvas_box").height() / zoom);
|
||
var openAs = {
|
||
_name: "",
|
||
set name(val) {
|
||
if (val == "") {
|
||
$("title").html('Soon Design');
|
||
} else {
|
||
$("title").html('Soon Design - ' + val);
|
||
}
|
||
this._name = val;
|
||
},
|
||
get name() {
|
||
return this._name
|
||
},
|
||
};//被打开的文件名
|
||
let objs1 = [];
|
||
let objs2 = [];
|
||
let step1 = { val: 0 }, step2 = { val: 0 };
|
||
let step = step1;
|
||
let objs = objs1;
|
||
let recordJson1 = [], recordJson2 = [], recordJson = recordJson1, recordObjs1 = [], recordObjs2 = [], recordObjs = recordObjs1;
|
||
let pre_objs1 = [], pre_objs2 = [], next_objs1 = [], next_objs2 = [], pre_objs = pre_objs1, next_objs = next_objs1;
|
||
let pre_json1 = [], pre_json2 = [], next_json1 = [], next_json2 = [], pre_json = pre_json1, next_json = next_json1;
|
||
var canvas1 = new fabric.Canvas('canvas1');
|
||
var canvas2 = new fabric.Canvas('canvas2');
|
||
fabric.Object.prototype.objectCaching = false;
|
||
var ctx1 = canvas1.getSelectionContext();
|
||
var ctx2 = canvas2.getSelectionContext();
|
||
let is_bgi_add = false;
|
||
canvas1.zoomToPoint(new fabric.Point(0, 0), 1);
|
||
canvas2.zoomToPoint(new fabric.Point(0, 0), 1);
|
||
|
||
// 初始化标尺
|
||
initRulers();
|
||
|
||
$("#source_front").width(zoom * $("#source_front").width());
|
||
$("#source_back").width(zoom * $("#source_back").width());
|
||
$(".canvas-container:eq(0)").css('transform', 'scale(' + zoom + ')')
|
||
$(".canvas-container:eq(1)").css('transform', 'scale(' + zoom + ')')
|
||
$(".canvas-container:eq(0)").css('width', 0)
|
||
|
||
$(".canvas-container:eq(1)").hide();
|
||
var canvas = canvas1;
|
||
fabric.Object.prototype.set({
|
||
borderColor: "#9013FE",
|
||
cornerColor: "#9013FE", //激活状态角落图标的填充颜色
|
||
cornerStrokeColor: "#9013FE", //激活状态角落图标的边框颜色
|
||
borderOpacityWhenMoving: 1,
|
||
borderScaleFactor: 6,
|
||
cornerSize: 24,
|
||
cornerStyle: "circle", //rect,circle
|
||
centeredScaling: false, //角落放大缩小是否是以图形中心为放大原点
|
||
centeredRotation: true, //旋转按钮旋转是否是左上角为圆心旋转
|
||
transparentCorners: false, //激活状态角落的图标是否透明
|
||
rotatingPointOffset: 20, //旋转距旋转体的距离
|
||
padding: 0,
|
||
});
|
||
canvas1.preserveObjectStacking = true;
|
||
canvas2.preserveObjectStacking = true;
|
||
|
||
|
||
var front_list = [];
|
||
ipcRenderer.on('font-list', (event, data) => {
|
||
const newFontList = [];
|
||
data.map(item => {
|
||
if (item.indexOf('"') === 0) {
|
||
newFontList.push(item.replace(/^"|"$/g, ''));
|
||
} else {
|
||
newFontList.push(item);
|
||
}
|
||
})
|
||
front_list = newFontList;
|
||
for (let item of front_list) {
|
||
$("#text_font_family").append("<option value='" + item + "'>" + item + "</option>");
|
||
$("#circle_text_font_family").append("<option value='" + item + "'>" + item + "</option>");
|
||
$("#out_text_font_family").append("<option value='" + item + "'>" + item + "</option>");
|
||
$("#barcode_font_family").append("<option value='" + item + "'>" + item + "</option>");
|
||
$("#count_font_family").append("<option value='" + item + "'>" + item + "</option>");
|
||
}
|
||
});
|
||
ipcRenderer.on('sys-lan', (event, data) => {
|
||
let lang = localStorage.getItem("lang");
|
||
if (lang) {
|
||
s_lan = lang;
|
||
langua_ge(lang);
|
||
$("#language_select").val(lang);
|
||
return;
|
||
}
|
||
switch (data) {
|
||
case 'zh-CN':
|
||
s_lan = "zh";
|
||
langua_ge("zh");
|
||
$("#language_select").val("zh");
|
||
localStorage.setItem("lang", "zh");
|
||
break;
|
||
case 'zh':
|
||
s_lan = "zh";
|
||
langua_ge("zh");
|
||
$("#language_select").val("zh");
|
||
localStorage.setItem("lang", "zh");
|
||
break;
|
||
case 'zh-TW':
|
||
s_lan = "ozh";
|
||
langua_ge("ozh");
|
||
$("#language_select").val("ozh");
|
||
localStorage.setItem("lang", "ozh");
|
||
break;
|
||
case 'en':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
case 'en-AU':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
case 'en-CA':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
case 'en-GB':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
case 'en-NZ':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
case 'en-US':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
case 'en-ZA':
|
||
s_lan = "en";
|
||
langua_ge("en");
|
||
$("#language_select").val("en");
|
||
localStorage.setItem("lang", "en");
|
||
break;
|
||
}
|
||
});
|
||
ipcRenderer.on('close', (event, message) => {
|
||
layer.confirm('<font style="color:black">' + language_str("whetherSave") + '</font>', {//是否保存当前文件?
|
||
btn: [language_str("save"), language_str("noSave"), language_str("cancel")] //['保存', '不保存', '取消']
|
||
, btn3: function (index, layero) {
|
||
|
||
}
|
||
}, function (index, layero) {
|
||
|
||
output(() => ipcRenderer.send('run-close'));
|
||
return;
|
||
let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let _g1 = [], _g2 = [];
|
||
let left = 0, top = 0;
|
||
for (let _o of canvas1.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g1.push(fabric.util.object.clone(_o));
|
||
}
|
||
let fp = new fabric.Group(_g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
left = 0, top = 0;
|
||
for (let _o of canvas2.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g2.push(fabric.util.object.clone(_o));
|
||
}
|
||
//let fp = new fabric.Group(_g1).toDataURL();
|
||
let bp = new fabric.Group(_g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let o = { f: j, b: {}, fo: objs1, bo: objs2, fp: fp, bp: '' };
|
||
if (openAs.name != "") {
|
||
//打开的文件
|
||
let fs = require('fs')
|
||
o.soonType = 1
|
||
fs.writeFileSync(openAs.name, JSON.stringify(o))
|
||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||
saveHistory();
|
||
|
||
ipcRenderer.send('run-close');
|
||
return;
|
||
}
|
||
dialog.showSaveDialog({
|
||
title: language_str("saveFile"),//'保存文件'
|
||
filters: [
|
||
{ name: 'Soon File Type', extensions: ['soon'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.filePath == "") { ipcRenderer.send('run-close'); return; }
|
||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
||
result.filePath += '.soon';
|
||
}
|
||
let fs = require('fs')
|
||
o.soonType = 1
|
||
fs.writeFileSync(result.filePath, JSON.stringify(o))
|
||
openAs.name = result.filePath;
|
||
layer.msg(language_str("saveSucc") + openAs.name);//保存成功至
|
||
saveHistory();
|
||
ipcRenderer.send('run-close');
|
||
}).catch(err => {
|
||
console.log()
|
||
})
|
||
layer.close(index);
|
||
}, function (index) {
|
||
ipcRenderer.send('run-close');
|
||
});
|
||
|
||
})
|
||
addBackground();//添加背景 白色卡片
|
||
|
||
initAligningGuidelines(canvas1);
|
||
initAligningGuidelines(canvas2);
|
||
//canvas.setZoom(0.5)
|
||
//recordObjs1.push(JSON.stringify(objs1));
|
||
//recordJson1.push(canvas1.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"]));
|
||
//recordObjs2.push(JSON.stringify(objs2));
|
||
//recordJson2.push(canvas2.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"]));
|
||
canvas.renderAll();//重新渲染画布
|
||
var zoomSlider = slider.render({
|
||
elem: '#zoomSlide', //绑定元素
|
||
min: 25,
|
||
max: 500,
|
||
value: 100,
|
||
change(val) {
|
||
console.log(val, zoomSlider)
|
||
canvas.zoomToPoint(
|
||
new fabric.Point(0, 0),
|
||
val / 100
|
||
);
|
||
// zoom = val / 100;
|
||
//$(".canvas-container").css("transform","scale(" + val / 100 + ")")
|
||
}
|
||
|
||
});
|
||
window.rotate = function (id) {
|
||
let angle = $(`#${id}`).attr("angle") - 0;
|
||
angle += 90;
|
||
$(`#${id}`).css("transform", `rotate(${angle}deg)`);
|
||
$(`#${id}`).attr("angle", angle);
|
||
}
|
||
$('#display').on('click', function () {
|
||
// 类型改变
|
||
fabric.Image.fromURL('./public/images/front_bg' + bg_version + '_1.png', function (i1) {
|
||
i1.left = background_image.left;
|
||
i1.top = background_image.top;
|
||
let img1 = i1;
|
||
|
||
fabric.Image.fromURL('./public/images/back_bg_1.png', function (i2) {
|
||
i2.left = background_image.left;
|
||
i2.top = background_image.top;
|
||
let img2 = i2;
|
||
fabric.Image.fromURL('./public/images/op_1.png', function (i3) {
|
||
i2.left = background_image.left;
|
||
i2.top = background_image.top;
|
||
let img3 = i3;
|
||
display_func(img1, img2, img3);
|
||
})
|
||
})
|
||
})
|
||
});
|
||
// 导出文件
|
||
async function saveImageAsPNG(buffer) {
|
||
let fs = require('fs');
|
||
// 弹出保存对话框
|
||
const { canceled, filePath } = await dialog.showSaveDialog({
|
||
title: '保存图片',
|
||
defaultPath: path.join(exePath, 'output.png'), // 默认路径
|
||
filters: [{ name: 'PNG Images', extensions: ['png'] }] // 文件过滤器
|
||
});
|
||
|
||
if (canceled) {
|
||
console.log('用户取消了保存操作');
|
||
return;
|
||
}
|
||
|
||
// 将Buffer写入PNG文件到用户选择的路径
|
||
fs.writeFile(filePath, buffer, (err) => {
|
||
if (err) {
|
||
console.error('写入文件失败:', err);
|
||
} else {
|
||
layer.msg(language_str("saveSucc") + filePath);//'保存成功至'
|
||
console.log('PNG文件已保存至:', filePath);
|
||
}
|
||
});
|
||
}
|
||
function display_func(img1, img2, img3) {
|
||
$("#base_control").hide();
|
||
$("#line_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
$("#component_type").text(language_str("bg"));//"背景"
|
||
canvas1.discardActiveObject().renderAll();
|
||
canvas2.discardActiveObject().renderAll();
|
||
let _objs1 = canvas1.getObjects();
|
||
let g1 = [];
|
||
let g3 = [];
|
||
let g5 = [];
|
||
let left = 0;//左裁剪
|
||
let top = 0;//顶裁剪
|
||
let black_left = 0;//黑色左裁剪
|
||
let black_top = 0;//黑色顶裁剪
|
||
let all_left = 0;//预览图左裁剪
|
||
let all_top = 0;//预览图顶裁剪
|
||
let list1 = [..._objs1]
|
||
for (let item of list1) {
|
||
let idx = getIndex(item, canvas1);
|
||
//console.log("------");
|
||
//console.log(item.getCoords());
|
||
//console.log(getCoordsMinX(background_image.getCoords()));
|
||
//console.log(getCoordsMinX(item.getCoords()));
|
||
//console.log(getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()));
|
||
//console.log("------");
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) {
|
||
all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) {
|
||
all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g3.push(fabric.util.object.clone(item));
|
||
if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) {
|
||
continue;//计数器 或 合成文字
|
||
}
|
||
if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) {
|
||
continue;//二维码 条形码
|
||
}
|
||
if (idx != 0 && (objs1[idx - 1].type == 2)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 &&
|
||
(
|
||
(
|
||
objs1[idx - 1].type == 3
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 11
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//圆形文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 5//矩形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 6//圆形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 7//直线
|
||
&&
|
||
(item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")
|
||
)
|
||
||
|
||
objs1[idx - 1].black == true //勾选并入黑色图层
|
||
// (
|
||
// objs1[idx-1].type == 1//固定图片
|
||
// &&
|
||
// objs1[idx-1].black == true //勾选并入黑色图层
|
||
// )
|
||
)
|
||
) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) {
|
||
black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) {
|
||
black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g1.push(fabric.util.object.clone(item));
|
||
continue;//黑色文字 黑色矩形 黑色线条 黑色圆形
|
||
} else if (idx == 0) {
|
||
g1.push(fabric.util.object.clone(item));
|
||
}
|
||
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) {
|
||
left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) {
|
||
top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g1.push(fabric.util.object.clone(item));
|
||
}
|
||
let url1 = new fabric.Group(g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
|
||
g3.push(img1);
|
||
let url3 = new fabric.Group(g3).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
let url5 = new fabric.Group(g5).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: black_top,
|
||
left: black_left
|
||
});
|
||
let _objs2 = canvas2.getObjects();
|
||
let g2 = [];
|
||
let g4 = [];
|
||
let g6 = [];
|
||
left = 0;
|
||
top = 0;
|
||
black_top = 0;
|
||
black_left = 0;
|
||
all_top = 0;
|
||
all_left = 0;
|
||
for (let item of _objs2) {
|
||
let idx = getIndex(item, canvas2);
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) {
|
||
all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) {
|
||
all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g4.push(fabric.util.object.clone(item));
|
||
if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) {
|
||
continue;//黑色字或计数器 或 合成文字
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) {
|
||
continue;//二维码 条形码
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 2)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 10)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 &&
|
||
(
|
||
(
|
||
objs2[idx - 1].type == 3
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 11
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//圆形文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 5//矩形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 6//圆形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 7//直线
|
||
&&
|
||
(item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")
|
||
)
|
||
||
|
||
objs2[idx - 1].black == true //勾选并入黑色图层
|
||
// (
|
||
// objs2[idx-1].type == 1//固定图片
|
||
// &&
|
||
// objs2[idx-1].black == true //勾选并入黑色图层
|
||
// )
|
||
)
|
||
) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) {
|
||
black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) {
|
||
black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g2.push(fabric.util.object.clone(item));
|
||
continue;//黑色文字 黑色矩形 黑色线条 黑色圆形
|
||
} else if (idx == 0) {
|
||
g2.push(fabric.util.object.clone(item));
|
||
}
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) {
|
||
left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) {
|
||
top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g2.push(fabric.util.object.clone(item));
|
||
|
||
}
|
||
let url2 = new fabric.Group(g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let white_url1 = canvas1.getObjects()[0].toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
});
|
||
g4.push(img2);
|
||
let url4 = new fabric.Group(g4).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
let url6 = new fabric.Group(g6).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: black_top,
|
||
left: black_left
|
||
});
|
||
|
||
let w = document.body.clientWidth * 0.7 + "px";
|
||
let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + "px";
|
||
let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + "px";
|
||
|
||
if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) {
|
||
//高度超出,则按高度计算
|
||
h = document.body.clientHeight * 0.8 + "px";
|
||
h1 = document.body.clientHeight * 0.8 - 150 + "px";
|
||
w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94
|
||
}
|
||
|
||
let fs = require('fs');
|
||
const Buffer = require('buffer').Buffer;
|
||
const buffer = Buffer.from(url3.replace(/^data:image\/\w+;base64,/, ""), 'base64');
|
||
const printPath = path.join(exePath, 'print.png');
|
||
fs.writeFileSync(printPath, buffer);
|
||
|
||
layer.open({
|
||
type: 1,
|
||
area: [w, h],
|
||
title: language_str("display"), //不显示标题栏"预览"
|
||
shadeClose: true, //点击遮罩关闭
|
||
content: `
|
||
<div style="padding:20px;background-color:#1E252D;height:${h1};display:flex;align-items: center;overflow:hidden;">
|
||
<div style="display: flex;justify-content: center;height: 100%;width: 100%;">
|
||
<div class="rotate-div" id="displayImg1" angle="0">
|
||
<img src="${printPath}" style="max-width:100%;max-height:100%;"/>
|
||
<div class="rotate-wrap" onclick="window.rotate('displayImg1')">
|
||
<img src="./public/images/rotate.png" style="height: 64px;width: 64px"/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>`,
|
||
btn: [language_str("output"), "打印"],//'导出'
|
||
btn1: function (index, layero) {
|
||
saveImageAsPNG(buffer)
|
||
|
||
printJS({ printable: printPath, type: 'image', style: 'img { width: 100%; height: auto; }' })
|
||
}
|
||
});
|
||
}
|
||
function output(callback = null, _save = save) {
|
||
// 类型改变
|
||
fabric.Image.fromURL('./public/images/op_1.png', function (i1) {
|
||
i1.left = background_image.left;
|
||
i1.top = background_image.top;
|
||
let img1 = i1;
|
||
fabric.Image.fromURL('./public/images/op_1.png', function (i2) {
|
||
i2.left = background_image.left;
|
||
i2.top = background_image.top;
|
||
let img2 = i2;
|
||
|
||
$("#base_control").hide();
|
||
$("#line_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
$("#component_type").text(language_str("bg"));//"背景"
|
||
canvas1.discardActiveObject().renderAll();
|
||
canvas2.discardActiveObject().renderAll();
|
||
let _objs1 = canvas1.getObjects();
|
||
let g1 = [];
|
||
let g3 = [];
|
||
let g5 = [];//黑色图层
|
||
let left = 0;//左裁剪
|
||
let top = 0;//顶裁剪
|
||
let black_left = 0;//黑色左裁剪
|
||
let black_top = 0;//黑色顶裁剪
|
||
let all_left = 0;//预览图左裁剪
|
||
let all_top = 0;//预览图顶裁剪
|
||
for (let item of _objs1) {
|
||
let idx = getIndex(item, canvas1);
|
||
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) {
|
||
all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) {
|
||
all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g3.push(fabric.util.object.clone(item));
|
||
if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) {
|
||
continue;//计数器 或 合成文字
|
||
}
|
||
if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) {
|
||
continue;//二维码 条形码
|
||
}
|
||
if (idx != 0 && (objs1[idx - 1].type == 2)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 &&
|
||
(
|
||
(
|
||
objs1[idx - 1].type == 3
|
||
&&
|
||
item.get("fill") == "#000000"
|
||
//文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 11
|
||
&&
|
||
item.get("fill") == "#000000"
|
||
//圆形文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 5//矩形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 6//圆形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 7//直线
|
||
&&
|
||
(item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")
|
||
)
|
||
||
|
||
objs1[idx - 1].black == true //勾选并入黑色图层
|
||
|
||
)
|
||
) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) {
|
||
black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) {
|
||
black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g1.push(fabric.util.object.clone(item));
|
||
continue;//黑色文字 黑色矩形 黑色线条 黑色圆形
|
||
} else if (idx == 0) {
|
||
g1.push(fabric.util.object.clone(item));
|
||
}
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) {
|
||
left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) {
|
||
top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g1.push(fabric.util.object.clone(item));
|
||
}
|
||
let url1 = new fabric.Group(g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
g3.push(img1);
|
||
let url3 = new fabric.Group(g3).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
let url5 = new fabric.Group(g5).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: black_top,
|
||
left: black_left
|
||
});
|
||
let _objs2 = canvas2.getObjects();
|
||
let g2 = [];
|
||
let g4 = [];
|
||
let g6 = [];//黑色图层
|
||
left = 0;
|
||
top = 0;
|
||
black_left = 0;//黑色左裁剪
|
||
black_top = 0;//黑色顶裁剪
|
||
all_left = 0;//黑色左裁剪
|
||
all_top = 0;//黑色顶裁剪
|
||
for (let item of _objs2) {
|
||
let idx = getIndex(item, canvas2);
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) {
|
||
all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) {
|
||
all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g4.push(fabric.util.object.clone(item));
|
||
if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) {
|
||
continue;//计数器 或 合成文字
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) {
|
||
continue;//二维码 条形码
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 2)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 &&
|
||
(
|
||
(
|
||
objs2[idx - 1].type == 3
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type ==11
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//圆形文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 5//矩形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 6//圆形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 7//直线
|
||
&&
|
||
(item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")
|
||
)
|
||
||
|
||
objs2[idx - 1].black == true //勾选并入黑色图层
|
||
// (
|
||
// objs2[idx-1].type == 1//固定图片
|
||
// &&
|
||
// objs2[idx-1].black == true //勾选并入黑色图层
|
||
// )
|
||
)
|
||
) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) {
|
||
black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) {
|
||
black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g2.push(fabric.util.object.clone(item));
|
||
continue;//黑色文字 黑色矩形 黑色线条 黑色圆形
|
||
} else if (idx == 0) {
|
||
g2.push(fabric.util.object.clone(item));
|
||
}
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) {
|
||
left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) {
|
||
top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g2.push(fabric.util.object.clone(item));
|
||
|
||
}
|
||
let url2 = new fabric.Group(g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let white_url1 = canvas1.getObjects()[0].toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
});
|
||
g4.push(img2);
|
||
let url4 = new fabric.Group(g4).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
let url6 = new fabric.Group(g6).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: black_top,
|
||
left: black_left
|
||
});
|
||
// let white_url2 = canvas2.getObjects()[0].toDataURL({
|
||
// height: 2787,
|
||
// width: 2787,
|
||
// });
|
||
//console.log(canvas.getObjects())
|
||
let w = document.body.clientWidth * 0.7 + "px";
|
||
let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + "px";
|
||
let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + "px";
|
||
|
||
if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) {
|
||
//高度超出,则按高度计算
|
||
h = document.body.clientHeight * 0.8 + "px";
|
||
h1 = document.body.clientHeight * 0.8 - 150 + "px";
|
||
w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94
|
||
}
|
||
|
||
let op = { frontColorPic: "", backColorPic: "", frontBlackPic: "", backBlackPic: "", frontData: [], backData: [], flag: 1, frontDisplayPic: url3, backDisplayPic: '' };
|
||
if (objs1.length != 0 & objs2.length == 0) {
|
||
op.flag = 2;
|
||
} else if (objs1.length == 0 & objs2.length != 0) {
|
||
op.flag = 3;
|
||
}
|
||
op.frontColorPic = desEncrypt(url1);
|
||
op.backColorPic = '';
|
||
//op.frontBlPic = url5;
|
||
//op.backBlPic = url6;
|
||
op.frontBlackPic = '';
|
||
op.backBlackPic = '';
|
||
for (let item of _objs1) {
|
||
let idx = getIndex(item, canvas1);
|
||
if (idx == 0) continue;//background-image
|
||
let type = objs1[idx - 1].type;
|
||
if (type == 2) {
|
||
//out_pic
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 1,
|
||
"name": objs1[idx - 1].name,
|
||
"FontColor": objs1[idx - 1].black ? "#000000" : "@",
|
||
"transparency": item.get("opacity"),
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 3) {
|
||
|
||
} else if (type == 11) {
|
||
|
||
op.frontData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||
"circleCenter" : objs1[idx - 1].circleCenter
|
||
});
|
||
} else if (type == 4) {
|
||
//out_text
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 3,
|
||
"name": objs1[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"DefaultText": item.get("text"),
|
||
"FontBackgroudColor": item.get("textBackgroundColor"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontColor": item.get("fill"),
|
||
"Exceed": objs1[idx - 1].exceed,
|
||
"AutoWrap": objs1[idx - 1].autoWrap,
|
||
"FixSize": objs1[idx - 1].fixSize,
|
||
"Bold": item.get("fontWeight") == "bold",
|
||
"Underline": item.get("underline"),
|
||
"Italic": item.get("fontStyle") == "italic",
|
||
"Strikeout": item.get("linethrough"),
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0)),
|
||
align: objs1[idx - 1].align
|
||
});
|
||
} else if (type == 8) {
|
||
//二维码
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 4,
|
||
"name": objs1[idx - 1].name,
|
||
"FontColor": objs1[idx - 1].color,
|
||
"DefaultText": objs1[idx - 1].val,
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 9) {
|
||
//条形码
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 5,
|
||
"name": objs1[idx - 1].name,
|
||
"FontSize": parseInt(objs1[idx - 1].fontSize),
|
||
"DefaultText": objs1[idx - 1].val,
|
||
"HideText": objs1[idx - 1].show,
|
||
"FontFamily": objs1[idx - 1].font,
|
||
"FontColor": objs1[idx - 1].color,
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 10) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 6,
|
||
"name": objs1[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontColor": item.get("fill"),
|
||
"start": objs1[idx - 1].start,
|
||
"add": parseInt(objs1[idx - 1].add),
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
}
|
||
//obj2
|
||
for (let item of _objs2) {
|
||
let idx = getIndex(item, canvas2);
|
||
if (idx == 0) continue;//background-image
|
||
let type = objs2[idx - 1].type;
|
||
if (type == 2) {
|
||
//out_pic
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 1,
|
||
"name": objs2[idx - 1].name,
|
||
"FontColor": objs2[idx - 1].black ? "#000000" : "@",
|
||
"transparency": item.get("opacity"),
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 3) {
|
||
|
||
} else if (type == 11) {
|
||
|
||
op.frontData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||
"circleCenter" : objs2[idx - 1].circleCenter
|
||
});
|
||
} else if (type == 4) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 3,
|
||
"name": objs2[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"DefaultText": item.get("text"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontBackgroudColor": item.get("textBackgroundColor"),
|
||
"FontColor": item.get("fill"),
|
||
"Exceed": objs2[idx - 1].exceed,
|
||
"AutoWrap": objs2[idx - 1].autoWrap,
|
||
"FixSize": objs2[idx - 1].fixSize,
|
||
"Bold": item.get("fontWeight") == "bold",
|
||
"Underline": item.get("underline"),
|
||
"Italic": item.get("fontStyle") == "italic",
|
||
"Strikeout": item.get("linethrough"),
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0)),
|
||
align: objs2[idx - 1].align
|
||
});
|
||
} else if (type == 8) {
|
||
//二维码
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 4,
|
||
"name": objs2[idx - 1].name,
|
||
"FontColor": objs2[idx - 1].color,
|
||
"DefaultText": objs2[idx - 1].val,
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 9) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 5,
|
||
"name": objs2[idx - 1].name,
|
||
"DefaultText": objs2[idx - 1].val,
|
||
"HideText": objs1[idx - 1].show,
|
||
"FontSize": parseInt(objs2[idx - 1].fontSize),
|
||
"FontFamily": objs2[idx - 1].font,
|
||
"FontColor": objs2[idx - 1].color,
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 10) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 6,
|
||
"name": objs2[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontColor": item.get("fill"),
|
||
"start": parseInt(objs2[idx - 1].start),
|
||
"add": parseInt(objs2[idx - 1].add),
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
}
|
||
_save(op, callback);
|
||
//return false 开启该代码可禁止点击该按钮关闭
|
||
})
|
||
})
|
||
}
|
||
$('#output').on('click', function () {
|
||
output(null, saveAs);
|
||
return;
|
||
// 类型改变
|
||
fabric.Image.fromURL('./public/images/op_1.png', function (i1) {
|
||
i1.left = background_image.left;
|
||
i1.top = background_image.top;
|
||
let img1 = i1;
|
||
fabric.Image.fromURL('./public/images/op_1.png', function (i2) {
|
||
i2.left = background_image.left;
|
||
i2.top = background_image.top;
|
||
let img2 = i2;
|
||
|
||
$("#base_control").hide();
|
||
$("#line_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
$("#component_type").text(language_str("bg"));//"背景"
|
||
canvas1.discardActiveObject().renderAll();
|
||
canvas2.discardActiveObject().renderAll();
|
||
let _objs1 = canvas1.getObjects();
|
||
let g1 = [];
|
||
let g3 = [];
|
||
let g5 = [];//黑色图层
|
||
let left = 0;//左裁剪
|
||
let top = 0;//顶裁剪
|
||
let black_left = 0;//黑色左裁剪
|
||
let black_top = 0;//黑色顶裁剪
|
||
let all_left = 0;//预览图左裁剪
|
||
let all_top = 0;//预览图顶裁剪
|
||
for (let item of _objs1) {
|
||
let idx = getIndex(item, canvas1);
|
||
|
||
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) {
|
||
all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) {
|
||
all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g3.push(fabric.util.object.clone(item));
|
||
if (idx != 0 && (objs1[idx - 1].type == 10 || objs1[idx - 1].type == 4)) {
|
||
continue;//计数器 或 合成文字
|
||
}
|
||
if (idx != 0 && (objs1[idx - 1].type == 8 || objs1[idx - 1].type == 9)) {
|
||
continue;//二维码 条形码
|
||
}
|
||
if (idx != 0 && (objs1[idx - 1].type == 2)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 &&
|
||
(
|
||
(
|
||
objs1[idx - 1].type == 3
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 11
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//圆形文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 5//矩形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 6//圆形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs1[idx - 1].type == 7//直线
|
||
&&
|
||
(item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")
|
||
)
|
||
||
|
||
objs1[idx - 1].black == true //勾选并入黑色图层
|
||
// (
|
||
// objs1[idx-1].type == 1//固定图片
|
||
// &&
|
||
// objs1[idx-1].black == true //勾选并入黑色图层
|
||
// )
|
||
)
|
||
) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) {
|
||
black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) {
|
||
black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g1.push(fabric.util.object.clone(item));
|
||
continue;//黑色文字 黑色矩形 黑色线条 黑色圆形
|
||
} else if (idx == 0) {
|
||
g1.push(fabric.util.object.clone(item));
|
||
}
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) {
|
||
left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) {
|
||
top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g1.push(fabric.util.object.clone(item));
|
||
}
|
||
let url1 = new fabric.Group(g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
g3.push(img1);
|
||
let url3 = new fabric.Group(g3).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
let url5 = new fabric.Group(g5).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: black_top,
|
||
left: black_left
|
||
});
|
||
let _objs2 = canvas2.getObjects();
|
||
let g2 = [];
|
||
let g4 = [];
|
||
let g6 = [];//黑色图层
|
||
left = 0;
|
||
top = 0;
|
||
black_left = 0;//黑色左裁剪
|
||
black_top = 0;//黑色顶裁剪
|
||
all_left = 0;//黑色左裁剪
|
||
all_top = 0;//黑色顶裁剪
|
||
for (let item of _objs2) {
|
||
let idx = getIndex(item, canvas2);
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > all_left) {
|
||
all_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > all_top) {
|
||
all_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g4.push(fabric.util.object.clone(item));
|
||
if (idx != 0 && (objs2[idx - 1].type == 10 || objs2[idx - 1].type == 4)) {
|
||
continue;//计数器 或 合成文字
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 8 || objs2[idx - 1].type == 9)) {
|
||
continue;//二维码 条形码
|
||
}
|
||
if (idx != 0 && (objs2[idx - 1].type == 2)) {
|
||
continue;//合成图片
|
||
}
|
||
if (idx != 0 &&
|
||
(
|
||
(
|
||
objs2[idx - 1].type == 3
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 11
|
||
&&
|
||
(item.get("fill") == "#000000" || (item.get("fill") == "#ffffff" && false))
|
||
//圆形文字 && 黑色
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 5//矩形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 6//圆形
|
||
&&
|
||
(
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("stroke") == "") //黑填充 透明边框
|
||
||
|
||
(item.get("fill") == "" && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //透明填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && (item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")) //黑填充 黑边框
|
||
||
|
||
((item.get("fill") == "#000000" || item.get("fill") == "#ffffff") && item.get("strokeWidth") == 0) //黑填充 0边框
|
||
)
|
||
)
|
||
||
|
||
(
|
||
objs2[idx - 1].type == 7//直线
|
||
&&
|
||
(item.get("stroke") == "#000000" || item.get("stroke") == "#ffffff")
|
||
)
|
||
||
|
||
objs2[idx - 1].black == true //勾选并入黑色图层
|
||
// (
|
||
// objs2[idx-1].type == 1//固定图片
|
||
// &&
|
||
// objs2[idx-1].black == true //勾选并入黑色图层
|
||
// )
|
||
)
|
||
) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > black_left) {
|
||
black_left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > black_top) {
|
||
black_top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g2.push(fabric.util.object.clone(item));
|
||
continue;//黑色文字 黑色矩形 黑色线条 黑色圆形
|
||
} else if (idx == 0) {
|
||
g2.push(fabric.util.object.clone(item));
|
||
}
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(item.getCoords()) > left) {
|
||
left = -(getCoordsMinX(item.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(item.getCoords()) > top) {
|
||
top = -(getCoordsMinY(item.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
g2.push(fabric.util.object.clone(item));
|
||
|
||
}
|
||
let url2 = new fabric.Group(g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let white_url1 = canvas1.getObjects()[0].toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
});
|
||
g4.push(img2);
|
||
let url4 = new fabric.Group(g4).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: all_top,
|
||
left: all_left
|
||
});
|
||
let url6 = new fabric.Group(g6).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: black_top,
|
||
left: black_left
|
||
});
|
||
// let white_url2 = canvas2.getObjects()[0].toDataURL({
|
||
// height: 2787,
|
||
// width: 2787,
|
||
// });
|
||
//console.log(canvas.getObjects())
|
||
let w = document.body.clientWidth * 0.7 + "px";
|
||
let h = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + 150 + "px";
|
||
let h1 = (document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 + "px";
|
||
|
||
if ((document.body.clientWidth * 0.7 - 40 - 0.06 * document.body.clientWidth * 0.7) * 0.62548 > document.body.clientHeight) {
|
||
//高度超出,则按高度计算
|
||
h = document.body.clientHeight * 0.8 + "px";
|
||
h1 = document.body.clientHeight * 0.8 - 150 + "px";
|
||
w = ((document.body.clientHeight * 0.8 - 150) / 0.62548 + 40) / 0.94
|
||
}
|
||
|
||
let op = { frontColorPic: "", backColorPic: "", frontBlackPic: "", backBlackPic: "", frontData: [], backData: [], flag: 1, frontDisplayPic: url3, backDisplayPic: '' };
|
||
if (objs1.length != 0 & objs2.length == 0) {
|
||
op.flag = 2;
|
||
} else if (objs1.length == 0 & objs2.length != 0) {
|
||
op.flag = 3;
|
||
}
|
||
op.frontColorPic = desEncrypt(url1);
|
||
op.backColorPic = '';
|
||
//op.frontBlPic = url5;
|
||
//op.backBlPic = url6;
|
||
op.frontBlackPic = '';
|
||
op.backBlackPic = '';
|
||
for (let item of _objs1) {
|
||
let idx = getIndex(item, canvas1);
|
||
if (idx == 0) continue;//background-image
|
||
let type = objs1[idx - 1].type;
|
||
if (type == 2) {
|
||
//out_pic
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 1,
|
||
"name": objs1[idx - 1].name,
|
||
"FontColor": objs1[idx - 1].black ? "#000000" : "@",
|
||
"transparency": item.get("opacity"),
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 3) {
|
||
//text
|
||
/*2022-07-26 黑色并入黑色图层
|
||
if(item.get("fill") == "#000000"){
|
||
//纯黑
|
||
op.frontData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
*/
|
||
} else if (type == 11) {
|
||
//circle_text
|
||
/*2022-07-26 黑色并入黑色图层
|
||
if(item.get("fill") == "#000000"){
|
||
//纯黑
|
||
op.frontData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
*/
|
||
op.frontData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||
"circleCenter" : objs1[idx - 1].circleCenter
|
||
});
|
||
} else if (type == 4) {
|
||
//out_text
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 3,
|
||
"name": objs1[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"DefaultText": item.get("text"),
|
||
"FontBackgroudColor": item.get("textBackgroundColor"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontColor": item.get("fill"),
|
||
"Exceed": objs1[idx - 1].exceed,
|
||
"AutoWrap": objs1[idx - 1].autoWrap,
|
||
"FixSize": objs1[idx - 1].fixSize,
|
||
"Bold": item.get("fontWeight") == "bold",
|
||
"Underline": item.get("underline"),
|
||
"Italic": item.get("fontStyle") == "italic",
|
||
"Strikeout": item.get("linethrough"),
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0)),
|
||
align: objs1[idx - 1].align
|
||
});
|
||
} else if (type == 8) {
|
||
//二维码
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 4,
|
||
"name": objs1[idx - 1].name,
|
||
"FontColor": objs1[idx - 1].color,
|
||
"DefaultText": objs1[idx - 1].val,
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 9) {
|
||
//条形码
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 5,
|
||
"name": objs1[idx - 1].name,
|
||
"FontSize": parseInt(objs1[idx - 1].fontSize),
|
||
"DefaultText": objs1[idx - 1].val,
|
||
"HideText": objs1[idx - 1].show,
|
||
"FontFamily": objs1[idx - 1].font,
|
||
"FontColor": objs1[idx - 1].color,
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 10) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.frontData.push({
|
||
"type": 6,
|
||
"name": objs1[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontColor": item.get("fill"),
|
||
"start": objs1[idx - 1].start,
|
||
"add": parseInt(objs1[idx - 1].add),
|
||
"x": parseInt((xy[0] - background_image1.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image1.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
}
|
||
//obj2
|
||
for (let item of _objs2) {
|
||
let idx = getIndex(item, canvas2);
|
||
if (idx == 0) continue;//background-image
|
||
let type = objs2[idx - 1].type;
|
||
if (type == 2) {
|
||
//out_pic
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 1,
|
||
"name": objs2[idx - 1].name,
|
||
"FontColor": objs2[idx - 1].black ? "#000000" : "@",
|
||
"transparency": item.get("opacity"),
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 3) {
|
||
//text
|
||
/*2022-07-26 黑色并入黑色图层
|
||
if(item.get("fill") == "#000000"){
|
||
//纯黑
|
||
op.backData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image2.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image2.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
*/
|
||
} else if (type == 11) {
|
||
//circle_text
|
||
/*2022-07-26 黑色并入黑色图层
|
||
if(item.get("fill") == "#000000"){
|
||
//纯黑
|
||
op.backData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image2.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image2.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
*/
|
||
op.frontData.push({
|
||
"type" : 2,
|
||
"Text" : item.get("text"),
|
||
"FontFamily" : item.get("fontFamily"),
|
||
"FontSize" : parseInt(item.get("fontSize")),
|
||
"FontColor" : "#000000",
|
||
"FontBackgroudColor" : item.get("textBackgroundColor"),
|
||
"Bold" : item.get("fontWeight") == "bold",
|
||
"Underline" : item.get("underline"),
|
||
"Italic" : item.get("fontStyle") == "italic",
|
||
"Strikeout" : item.get("linethrough"),
|
||
"x" : parseInt((item.get("left") - background_image1.left).toFixed(0)),
|
||
"y" : parseInt((item.get("top") - background_image1.top).toFixed(0)),
|
||
"h" : parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w" : parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate" : parseInt(item.get("angle").toFixed(0)),
|
||
"circleCenter" : objs2[idx - 1].circleCenter
|
||
});
|
||
} else if (type == 4) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 3,
|
||
"name": objs2[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"DefaultText": item.get("text"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontBackgroudColor": item.get("textBackgroundColor"),
|
||
"FontColor": item.get("fill"),
|
||
"Exceed": objs2[idx - 1].exceed,
|
||
"AutoWrap": objs2[idx - 1].autoWrap,
|
||
"FixSize": objs2[idx - 1].fixSize,
|
||
"Bold": item.get("fontWeight") == "bold",
|
||
"Underline": item.get("underline"),
|
||
"Italic": item.get("fontStyle") == "italic",
|
||
"Strikeout": item.get("linethrough"),
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0)),
|
||
align: objs2[idx - 1].align
|
||
});
|
||
} else if (type == 8) {
|
||
//二维码
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 4,
|
||
"name": objs2[idx - 1].name,
|
||
"FontColor": objs2[idx - 1].color,
|
||
"DefaultText": objs2[idx - 1].val,
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 9) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 5,
|
||
"name": objs2[idx - 1].name,
|
||
"DefaultText": objs2[idx - 1].val,
|
||
"HideText": objs1[idx - 1].show,
|
||
"FontSize": parseInt(objs2[idx - 1].fontSize),
|
||
"FontFamily": objs2[idx - 1].font,
|
||
"FontColor": objs2[idx - 1].color,
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
} else if (type == 10) {
|
||
let xy = getAbsoluteXY(item);
|
||
op.backData.push({
|
||
"type": 6,
|
||
"name": objs2[idx - 1].name,
|
||
"FontFamily": item.get("fontFamily"),
|
||
"FontSize": parseInt(item.get("fontSize")),
|
||
"FontColor": item.get("fill"),
|
||
"start": parseInt(objs2[idx - 1].start),
|
||
"add": parseInt(objs2[idx - 1].add),
|
||
"x": parseInt((xy[0] - background_image2.left).toFixed(0)),
|
||
"y": parseInt((xy[1] - background_image2.top).toFixed(0)),
|
||
"h": parseInt((item.get("scaleY") * item.get("height")).toFixed(0)),
|
||
"w": parseInt((item.get("scaleX") * item.get("width")).toFixed(0)),
|
||
"rotate": parseInt(item.get("angle").toFixed(0))
|
||
});
|
||
}
|
||
}
|
||
dialog.showSaveDialog({
|
||
title: language_str("saveFile"),//'保存文件'
|
||
filters: [
|
||
{ name: 'CS File Type', extensions: ['cs'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.canceled) return;
|
||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
||
result.filePath += '.cs';
|
||
}
|
||
let fs = require('fs')
|
||
op.soonType = 1
|
||
fs.writeFileSync(result.filePath, JSON.stringify(op))
|
||
}).catch(err => {
|
||
console.log()
|
||
})
|
||
//return false 开启该代码可禁止点击该按钮关闭
|
||
})
|
||
})
|
||
});
|
||
var _keyctrl = false, _keyc = false, _textEdit = false, _inputEdit = false;
|
||
$("input").focus(function () {
|
||
console.log(1)
|
||
_inputEdit = true
|
||
})
|
||
$("input").blur(function () {
|
||
_inputEdit = false
|
||
})
|
||
$("textarea").focus(function () {
|
||
console.log(1)
|
||
_inputEdit = true
|
||
})
|
||
$("textarea").blur(function () {
|
||
_inputEdit = false
|
||
})
|
||
$("body").keyup(function (event) {
|
||
// 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta)
|
||
if (event.keyCode == 17 || event.keyCode == 91 || event.keyCode == 93) { // Ctrl 键或 Meta 键(Mac Cmd)释放
|
||
_keyctrl = false;
|
||
};
|
||
if (event.keyCode == 67) {
|
||
_keyc = false;
|
||
};
|
||
})
|
||
$("body").keydown(function (event) {
|
||
// 统一的快捷键处理(兼容 Windows/Linux: Ctrl, Mac: Cmd/Meta)
|
||
const isModifierKey = event.ctrlKey || event.metaKey; // 兼容三端
|
||
|
||
// 快捷键处理(在输入框或文本区域中时不触发,除了删除相关的)
|
||
if (!_inputEdit && !_textEdit) {
|
||
// CTRL/CMD+N - 新建
|
||
if (isModifierKey && event.keyCode == 78) {
|
||
event.preventDefault();
|
||
$("#new").click();
|
||
return;
|
||
}
|
||
// CTRL/CMD+O - 打开
|
||
if (isModifierKey && event.keyCode == 79) {
|
||
event.preventDefault();
|
||
$("#open").click();
|
||
return;
|
||
}
|
||
// CTRL/CMD+S - 保存
|
||
if (isModifierKey && !event.shiftKey && event.keyCode == 83) {
|
||
event.preventDefault();
|
||
$("#save").click();
|
||
return;
|
||
}
|
||
// CTRL/CMD+SHIFT+S - 保存副本
|
||
if (isModifierKey && event.shiftKey && event.keyCode == 83) {
|
||
event.preventDefault();
|
||
output(null, saveAs);
|
||
return;
|
||
}
|
||
// CTRL/CMD+Z - 还原
|
||
if (isModifierKey && !event.shiftKey && event.keyCode == 90) {
|
||
event.preventDefault();
|
||
$("#previous").click();
|
||
return;
|
||
}
|
||
// CTRL/CMD+Y - 重做
|
||
if (isModifierKey && !event.shiftKey && event.keyCode == 89) {
|
||
event.preventDefault();
|
||
$("#next").click();
|
||
return;
|
||
}
|
||
// CTRL/CMD+C - 复制
|
||
if (isModifierKey && event.keyCode == 67 && event.target.nodeName == 'BODY') {
|
||
event.preventDefault();
|
||
copySelection();
|
||
return;
|
||
}
|
||
// CTRL/CMD+V - 粘贴
|
||
if (isModifierKey && event.keyCode == 86 && event.target.nodeName == 'BODY') {
|
||
event.preventDefault();
|
||
pasteFromClipboard();
|
||
return;
|
||
}
|
||
|
||
// CTRL/CMD + SHIFT + DEL (Windows) 或 CMD + SHIFT + Backspace (Mac) - 清空
|
||
if (isModifierKey && event.shiftKey && (event.keyCode == 46 || event.keyCode == 8)) {
|
||
event.preventDefault();
|
||
$("#clean").click();
|
||
return;
|
||
}
|
||
|
||
// CTRL/CMD + DEL (Windows) 或 CMD + Backspace (Mac) - 删除
|
||
if (isModifierKey && !event.shiftKey && (event.keyCode == 46 || event.keyCode == 8)) {
|
||
event.preventDefault();
|
||
$("#delete").click();
|
||
return;
|
||
}
|
||
|
||
}
|
||
// 兼容三端的 modifier key 检测(Windows/Linux: Ctrl, Mac: Cmd/Meta)
|
||
if (event.keyCode == 17 || event.metaKey) { // Ctrl 键或 Meta 键(Mac Cmd)
|
||
_keyctrl = true;
|
||
if (_keyc && _textEdit) {
|
||
//同时按下且在编辑状态
|
||
setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1)
|
||
//clipboard.writeText((clipboard.readText()+' '))
|
||
}
|
||
}
|
||
if (event.keyCode == 67) {
|
||
_keyc = true;
|
||
if (_keyctrl & _textEdit) {
|
||
//同时按下且在编辑状态
|
||
setTimeout("clipboard.writeText( (clipboard.readText()+' ') );", 1)
|
||
//clipboard.writeText((clipboard.readText()+' '))
|
||
}
|
||
}
|
||
if (event.keyCode == 37) {
|
||
//left
|
||
let v = -1;
|
||
if (_keyctrl || event.ctrlKey || event.metaKey) {
|
||
v = -5;
|
||
}
|
||
let x = canvas.getActiveObject().get("left");
|
||
x += v;
|
||
canvas.getActiveObject().set("left", x);
|
||
canvas.renderAll();
|
||
recordState();
|
||
updateControls();
|
||
}
|
||
if (event.keyCode == 38) {
|
||
//up
|
||
let v = -1;
|
||
if (_keyctrl || event.ctrlKey || event.metaKey) {
|
||
v = -5;
|
||
}
|
||
let y = canvas.getActiveObject().get("top");
|
||
y += v;
|
||
canvas.getActiveObject().set("top", y);
|
||
canvas.renderAll();
|
||
recordState();
|
||
updateControls();
|
||
}
|
||
if (event.keyCode == 39) {
|
||
//right
|
||
let v = 1;
|
||
if (_keyctrl || event.ctrlKey || event.metaKey) {
|
||
v = 5;
|
||
}
|
||
let x = canvas.getActiveObject().get("left");
|
||
x += v;
|
||
canvas.getActiveObject().set("left", x);
|
||
canvas.renderAll();
|
||
recordState();
|
||
updateControls();
|
||
}
|
||
if (event.keyCode == 40) {
|
||
//down
|
||
let v = +1;
|
||
if (_keyctrl || event.ctrlKey || event.metaKey) {
|
||
v = 5;
|
||
}
|
||
let y = canvas.getActiveObject().get("top");
|
||
y += v;
|
||
canvas.getActiveObject().set("top", y);
|
||
canvas.renderAll();
|
||
recordState();
|
||
updateControls();
|
||
}
|
||
// 普通删除键(DEL键,没有按CTRL/CMD)
|
||
if (event.keyCode == 46 && !isModifierKey && !_inputEdit && !_textEdit) {
|
||
let actObjs = canvas.getActiveObjects();
|
||
let allObjs = canvas.getObjects();
|
||
let flag = 0;
|
||
for (let item of actObjs) {
|
||
if (item != allObjs[0]) {
|
||
let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1
|
||
objs.splice(i - 1, 1);
|
||
canvas.remove(item);
|
||
flag = 1;
|
||
|
||
}
|
||
}
|
||
updateList();
|
||
canvas.discardActiveObject();
|
||
if (flag == 1) {
|
||
recordState();
|
||
canvas.renderAll();
|
||
handleObjectSelected()
|
||
}
|
||
}
|
||
});
|
||
let pre_add_image;
|
||
$("#addPic").click(function () {
|
||
OpenDialog();
|
||
function OpenDialog() {
|
||
dialog.showOpenDialog({
|
||
title: language_str("selectPic"),//请选择图片
|
||
buttonLabel: language_str("comf"),//"确认"
|
||
filters: [
|
||
{ name: 'Image File Type', extensions: ['png', 'jpg', 'jpeg'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.canceled) return;
|
||
//console.log(result.filePaths)
|
||
fabric.Image.fromURL(result.filePaths[0], function (image) {
|
||
//image.left = pointer.x;
|
||
//image.top = pointer.y;
|
||
image.setSrc(image.toDataURL(), function (image) {
|
||
pre_add_image = image;
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 1;
|
||
});
|
||
//canvas.add(image);
|
||
//objs.push({type: 1});
|
||
//canvas.renderAll();
|
||
//updateList();
|
||
//recordState();
|
||
});
|
||
}).catch(err => {
|
||
console.log(err)
|
||
})
|
||
}
|
||
});
|
||
$("#addOutPic").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 2;
|
||
});
|
||
$("#addText").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 3;
|
||
});
|
||
|
||
$("#addCircleText").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 11;
|
||
});
|
||
$("#addOutText").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 4;
|
||
});
|
||
$("#addRect").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 5;
|
||
});
|
||
$("#addCircle").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 6;
|
||
});
|
||
$("#addLine").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 7;
|
||
});
|
||
$("#addQrCode").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 8;
|
||
});
|
||
$("#addBarCode").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addCounter").css("background-color", "");
|
||
addState = 9;
|
||
});
|
||
$("#addCounter").click(function () {
|
||
background_image.hoverCursor = "crosshair";
|
||
$(this).css("background-color", "#646E76");
|
||
|
||
$("#addPic").css("background-color", "");
|
||
$("#addOutPic").css("background-color", "");
|
||
$("#addText").css("background-color", "");
|
||
$("#addCircleText").css("background-color", "");
|
||
$("#addOutText").css("background-color", "");
|
||
$("#addRect").css("background-color", "");
|
||
$("#addCircle").css("background-color", "");
|
||
$("#addLine").css("background-color", "");
|
||
$("#addQrCode").css("background-color", "");
|
||
$("#addBarCode").css("background-color", "");
|
||
addState = 10;
|
||
});
|
||
$("#version_change").click(function () {
|
||
if (bg_version == 1) {
|
||
bg_version = 2;
|
||
} else {
|
||
bg_version = 1;
|
||
}
|
||
// 类型改变
|
||
$("#source_front").attr("src", "./public/images/front_bg" + bg_version + "_1.png");
|
||
canvas.renderAll();
|
||
|
||
});
|
||
$("#front_side").click(function () {
|
||
$(this).addClass("ui-button-active");
|
||
$("#back_side").removeClass("ui-button-active");
|
||
$(".canvas-container:eq(0)").show();
|
||
$(".canvas-container:eq(1)").hide();
|
||
console.log("------");
|
||
console.log(recordObjs1);
|
||
console.log("------");
|
||
canvas = canvas1;
|
||
objs = objs1;
|
||
background_image = background_image1;
|
||
next_objs = next_objs1;
|
||
pre_objs = pre_objs1;
|
||
next_json = next_json1;
|
||
pre_json = pre_json1;
|
||
recordObjs = recordObjs1;
|
||
recordJson = recordJson1;
|
||
step = step1;
|
||
updateList();
|
||
|
||
$("#line_control").hide();
|
||
$("#base_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
$("#component_type").text(language_str("bg"));//背景
|
||
});
|
||
$("#back_side").click(function () {
|
||
$(this).addClass("ui-button-active");
|
||
$("#front_side").removeClass("ui-button-active");
|
||
$(".canvas-container:eq(0)").hide();
|
||
$(".canvas-container:eq(1)").show();
|
||
canvas = canvas2;
|
||
objs = objs2;
|
||
background_image = background_image2;
|
||
next_objs = next_objs2;
|
||
pre_objs = pre_objs2;
|
||
next_json = next_json2;
|
||
pre_json = pre_json2;
|
||
recordObjs = recordObjs2;
|
||
recordJson = recordJson2;
|
||
step = step2;
|
||
updateList();
|
||
$("#line_control").hide();
|
||
$("#base_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
$("#component_type").text(language_str("bg"));//"背景"
|
||
});
|
||
$("#top_alignment").click(function () {
|
||
let _objs = canvas.getActiveObjects();
|
||
if (_objs.length == 1) {
|
||
//只选中了一个
|
||
_objs[0].set("top", background_image.get("top"));
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let top = 0;
|
||
for (let item of _objs) {
|
||
let t_top = item.get("top");
|
||
if (t_top < top) {
|
||
top = t_top;
|
||
}
|
||
}
|
||
groupItems = [];
|
||
for (let item of _objs) {
|
||
item.set("top", top);
|
||
groupItems.push(item);
|
||
}
|
||
canvas.discardActiveObject();
|
||
let sel = new fabric.ActiveSelection(groupItems, {
|
||
canvas: canvas,
|
||
});
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
canvas.renderAll();
|
||
|
||
});
|
||
$("#bottom_alignment").click(function () {
|
||
let _objs = canvas.getActiveObjects();
|
||
if (_objs.length == 1) {
|
||
//只选中了一个
|
||
let idx = getIndex(_objs[0]);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = _objs[0].get("strokeWidth")
|
||
}
|
||
_objs[0].set("top", background_image.get("top") + background_image.get("height") - _objs[0].get("height") * _objs[0].get("scaleY") - other);
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let bottom = 0;
|
||
for (let item of _objs) {
|
||
let idx = getIndex(item);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
let t_b = item.get("top") + item.get("height") * item.get("scaleY") + other;
|
||
if (t_b > bottom) {
|
||
bottom = t_b;
|
||
}
|
||
}
|
||
groupItems = []
|
||
for (let item of _objs) {
|
||
let idx = getIndex(item);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
item.set("top", bottom - item.get("height") * item.get("scaleY") - other);
|
||
groupItems.push(item)
|
||
}
|
||
canvas.discardActiveObject();
|
||
let sel = new fabric.ActiveSelection(groupItems, {
|
||
canvas: canvas,
|
||
});
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
canvas.renderAll();
|
||
|
||
});
|
||
$("#center_y_alignment").click(function () {
|
||
let _objs = canvas.getActiveObjects();
|
||
if (_objs.length == 1) {
|
||
//只选中了一个
|
||
let idx = getIndex(_objs[0]);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = _objs[0].get("strokeWidth")
|
||
}
|
||
_objs[0].set("top", background_image.get("top") + (background_image.get("height") - (_objs[0].get("height") + other) * _objs[0].get("scaleY")) / 2);
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let top = 0;
|
||
for (let item of _objs) {
|
||
let t_top = item.get("top");
|
||
if (t_top < top) {
|
||
top = t_top;
|
||
}
|
||
}
|
||
groupItems = []
|
||
for (let item of _objs) {
|
||
let idx = getIndex(item);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
item.set("top", top + (item.group.height - (item.get("height") + other) * item.get("scaleY")) / 2);
|
||
groupItems.push(item)
|
||
}
|
||
canvas.discardActiveObject();
|
||
let sel = new fabric.ActiveSelection(groupItems, {
|
||
canvas: canvas,
|
||
});
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
canvas.renderAll();
|
||
});
|
||
$("#left_alignment").click(function () {
|
||
let _objs = canvas.getActiveObjects();
|
||
if (_objs.length == 1) {
|
||
//只选中了一个
|
||
_objs[0].set("left", background_image.get("left"));
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let left = 0;
|
||
for (let item of _objs) {
|
||
let t_left = item.get("left");
|
||
if (t_left < left) {
|
||
left = t_left;
|
||
}
|
||
}
|
||
groupItems = []
|
||
for (let item of _objs) {
|
||
item.set("left", left);
|
||
groupItems.push(item)
|
||
}
|
||
canvas.discardActiveObject();
|
||
let sel = new fabric.ActiveSelection(groupItems, {
|
||
canvas: canvas,
|
||
});
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
canvas.renderAll();
|
||
});
|
||
$("#right_alignment").click(function () {
|
||
let _objs = canvas.getActiveObjects();
|
||
if (_objs.length == 1) {
|
||
//只选中了一个
|
||
let idx = getIndex(_objs[0]);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
_objs[0].set("left", background_image.get("left") + background_image.get("width") - _objs[0].get("width") * _objs[0].get("scaleX") - other);
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let right = 0;
|
||
for (let item of _objs) {
|
||
let idx = getIndex(item);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
let t_r = item.get("left") + item.get("width") * item.get("scaleX") + other;
|
||
if (t_r > right) {
|
||
right = t_r;
|
||
}
|
||
}
|
||
let groupItems = []
|
||
|
||
for (let item of _objs) {
|
||
let idx = getIndex(item);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
item.set("left", right - item.get("width") * item.get("scaleX") - other);
|
||
groupItems.push(item)
|
||
}
|
||
//BUG1
|
||
canvas.discardActiveObject();
|
||
let sel = new fabric.ActiveSelection(groupItems, {
|
||
canvas: canvas,
|
||
});
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
canvas.renderAll();
|
||
});
|
||
$("#center_x_alignment").click(function () {
|
||
let _objs = canvas.getActiveObjects();
|
||
if (_objs.length == 1) {
|
||
//只选中了一个
|
||
let idx = getIndex(_objs[0]);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = _objs[0].get("strokeWidth")
|
||
}
|
||
_objs[0].set("left", background_image.get("left") + (background_image.get("width") - (_objs[0].get("width") + other) * _objs[0].get("scaleX")) / 2);
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let left = 0;
|
||
for (let item of _objs) {
|
||
let t_left = item.get("left");
|
||
if (t_left < left) {
|
||
left = t_left;
|
||
}
|
||
}
|
||
groupItems = []
|
||
for (let item of _objs) {
|
||
let idx = getIndex(item);
|
||
let type = objs[idx - 1].type;
|
||
let other = 0;//strokeWidth
|
||
if (type == 5 || type == 6 || type == 7) {
|
||
other = item.get("strokeWidth")
|
||
}
|
||
item.set("left", left + (item.group.width - (item.get("width") + other) * item.get("scaleX")) / 2);
|
||
groupItems.push(item)
|
||
}
|
||
canvas.discardActiveObject();
|
||
let sel = new fabric.ActiveSelection(groupItems, {
|
||
canvas: canvas,
|
||
});
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
canvas.renderAll();
|
||
});
|
||
$("#up_obj").click(function () {//上移,放到前面 数组中在后面
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if (idx + 1 != canvas.getObjects().length) {
|
||
canvas.bringForward(canvas.getActiveObject());
|
||
canvas.renderAll();
|
||
let temp = objs[idx - 1];
|
||
objs[idx - 1] = objs[idx];
|
||
objs[idx] = temp;
|
||
//console.log(objs);
|
||
//[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]];
|
||
|
||
recordState();
|
||
updateList();
|
||
selectObj(idx);
|
||
}
|
||
});
|
||
$("#down_obj").click(function () {//下移,放到后面 数组中在前面
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if (idx != 1) {
|
||
canvas.sendBackwards(canvas.getActiveObject());
|
||
canvas.renderAll();
|
||
//[objs[idx-2],objs[idx-1]] = [objs[idx-1],objs[idx-2]];
|
||
|
||
let temp = objs[idx - 1];
|
||
objs[idx - 1] = objs[idx - 2];
|
||
objs[idx - 2] = temp;
|
||
recordState();
|
||
updateList();
|
||
selectObj(idx - 2);
|
||
}
|
||
});
|
||
$("#set_bg").click(function () {//设置为背景
|
||
let obj = canvas.getActiveObject();
|
||
console.log(obj, obj.get("selectable"))
|
||
let idx = getIndex(obj);
|
||
const scaleX = 2787 / obj.width
|
||
const scaleY = 2787 / obj.height
|
||
obj.set({
|
||
scaleX: scaleX,
|
||
scaleY: scaleY,
|
||
left: ($('#canvas1').width() - 2787) / 2,
|
||
top: ($('#canvas1').height() - 2787) / 2,
|
||
});
|
||
$('#text_w').val(2787)
|
||
$('#text_h').val(2787)
|
||
$('#text_x').val(0)
|
||
$('#text_y').val(0)
|
||
if (obj.get("selectable")) {
|
||
obj.set("selectable", false);
|
||
$("#lock_img").attr("src", "public/images/lock20.png")
|
||
}
|
||
canvas.sendToBack(obj);
|
||
canvas.bringForward(obj);
|
||
canvas.renderAll();
|
||
let objItem = objs.splice(idx - 1, 1)[0]
|
||
objs.unshift(objItem)
|
||
recordState();
|
||
updateList();
|
||
selectObj(0);
|
||
});
|
||
|
||
// ==========================================
|
||
// 【新增】状态恢复后的回调函数
|
||
// 作用:确保图片加载完毕后,再刷新界面,防止白屏或对象丢失
|
||
// ==========================================
|
||
function onStateRestored() {
|
||
// 1. 重新获取背景图引用 (因为旧对象被销毁了)
|
||
// 注意:canvas 是全局变量,指向当前激活的画板
|
||
if (canvas.getObjects().length > 0) {
|
||
background_image = canvas.getObjects()[0];
|
||
background_image.selectable = false; // 确保背景不可选
|
||
background_image.evented = false;
|
||
}
|
||
|
||
// 2. 渲染画布
|
||
canvas.requestRenderAll();
|
||
|
||
// 3. 取消选中状态
|
||
selectObj(-1);
|
||
|
||
// 4. 隐藏所有属性面板
|
||
$("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide();
|
||
|
||
// 5. 刷新左侧列表
|
||
updateList();
|
||
}
|
||
// ==========================================
|
||
// 撤销操作 (修复版)
|
||
// ==========================================
|
||
$("#previous").click(function () {
|
||
if (step.val == 0) return;
|
||
|
||
step.val--;
|
||
|
||
// 判断当前是正面还是背面
|
||
if ($("#front_side").hasClass("ui-button-active")) {
|
||
// 1. 恢复业务数据
|
||
objs1 = JSON.parse(recordObjs1[step.val]);
|
||
objs = objs1;
|
||
|
||
// 2. 恢复画布 (使用回调函数!)
|
||
canvas.loadFromJSON(recordJson1[step.val], function() {
|
||
onStateRestored(); // 图片加载完才执行这一步
|
||
});
|
||
} else {
|
||
// 背面逻辑
|
||
objs2 = JSON.parse(recordObjs2[step.val]);
|
||
objs = objs2;
|
||
|
||
canvas.loadFromJSON(recordJson2[step.val], function() {
|
||
onStateRestored();
|
||
});
|
||
}
|
||
});
|
||
// ==========================================
|
||
// 重做操作 (修复版)
|
||
// ==========================================
|
||
$("#next").click(function () {
|
||
// 获取当前历史记录的最大长度
|
||
let maxLen = $("#front_side").hasClass("ui-button-active") ? recordObjs1.length : recordObjs2.length;
|
||
|
||
if (step.val >= maxLen - 1) return;
|
||
|
||
step.val++;
|
||
|
||
if ($("#front_side").hasClass("ui-button-active")) {
|
||
objs1 = JSON.parse(recordObjs1[step.val]);
|
||
objs = objs1;
|
||
|
||
canvas.loadFromJSON(recordJson1[step.val], function() {
|
||
onStateRestored(); // 图片加载完才执行这一步
|
||
});
|
||
} else {
|
||
objs2 = JSON.parse(recordObjs2[step.val]);
|
||
objs = objs2;
|
||
|
||
canvas.loadFromJSON(recordJson2[step.val], function() {
|
||
onStateRestored();
|
||
});
|
||
}
|
||
});
|
||
|
||
$("#clean").click(function () {
|
||
objs.splice(0, objs.length);
|
||
|
||
let allObjs = canvas.getObjects();
|
||
for (let item of allObjs) {
|
||
if (item != allObjs[0]) {
|
||
canvas.remove(item);
|
||
}
|
||
}
|
||
updateList();
|
||
recordState();
|
||
});
|
||
$("#rotate").click(function () {
|
||
let obj = canvas.getActiveObject();
|
||
obj.rotate(Math.round((obj.get("angle") + 90) % 360));
|
||
$("#text_r").val(obj.get("angle"));
|
||
canvas.renderAll();
|
||
updateControls();
|
||
recordState();
|
||
});
|
||
$('#vertical_obj').click(function () {
|
||
let obj = canvas.getActiveObject();
|
||
obj.set("flipY", !obj.get("flipY"));
|
||
canvas.renderAll();
|
||
updateControls();
|
||
recordState();
|
||
});
|
||
$('#align_obj').click(function () {
|
||
let obj = canvas.getActiveObject();
|
||
obj.set("flipX", !obj.get("flipX"));
|
||
canvas.renderAll();
|
||
updateControls();
|
||
recordState();
|
||
});
|
||
$("#text_italics").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("fontStyle", "normal")
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("fontStyle", "italic")
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#text_bold").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选,恢复正常
|
||
canvas.getActiveObject().set("fontWeight", "normal")
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("fontWeight", "bold")
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#text_underline").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("underline", false)
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("underline", true)
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#text_linethrough").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("linethrough", false)
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("linethrough", true)
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
|
||
$("#circle_text_italics").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("fontStyle", "normal")
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("fontStyle", "italic")
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#circle_text_bold").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选,恢复正常
|
||
canvas.getActiveObject().set("fontWeight", "normal")
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("fontWeight", "bold")
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
|
||
$('#out_left_alignment').click(function () {
|
||
$('#out_left_alignment').parent().removeClass('tool1')
|
||
$('#out_right_alignment').parent().removeClass('tool1')
|
||
$('#out_center_alignment').parent().removeClass('tool1')
|
||
setTimeout(() => {
|
||
$('#out_left_alignment').parent().addClass('tool1')
|
||
});
|
||
canvas.getActiveObject().set('textAlign', 'left')
|
||
let idx = getIndex(canvas.getActiveObject())
|
||
objs[idx - 1].align = 'left'
|
||
recordState()
|
||
canvas.renderAll()
|
||
})
|
||
$('#out_right_alignment').click(function () {
|
||
$('#out_left_alignment').parent().removeClass('tool1')
|
||
$('#out_right_alignment').parent().removeClass('tool1')
|
||
$('#out_center_alignment').parent().removeClass('tool1')
|
||
setTimeout(() => {
|
||
$('#out_right_alignment').parent().addClass('tool1')
|
||
});
|
||
canvas.getActiveObject().set('textAlign', 'right')
|
||
let idx = getIndex(canvas.getActiveObject())
|
||
objs[idx - 1].align = 'right'
|
||
recordState()
|
||
canvas.renderAll()
|
||
})
|
||
$('#out_center_alignment').click(function () {
|
||
$('#out_left_alignment').parent().removeClass('tool1')
|
||
$('#out_right_alignment').parent().removeClass('tool1')
|
||
$('#out_center_alignment').parent().removeClass('tool1')
|
||
setTimeout(() => {
|
||
$('#out_center_alignment').parent().addClass('tool1')
|
||
});
|
||
canvas.getActiveObject().set('textAlign', 'center')
|
||
let idx = getIndex(canvas.getActiveObject())
|
||
objs[idx - 1].align = 'center'
|
||
recordState()
|
||
canvas.renderAll()
|
||
})
|
||
|
||
$("#out_text_italics").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("fontStyle", "normal")
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("fontStyle", "italic")
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#out_text_bold").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选,恢复正常
|
||
canvas.getActiveObject().set("fontWeight", "normal")
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("fontWeight", "bold")
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#out_text_underline").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("underline", false)
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("underline", true)
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#out_text_linethrough").click(function () {
|
||
if ($(this).hasClass("ui-radio-acitve")) {
|
||
//已选
|
||
canvas.getActiveObject().set("linethrough", false)
|
||
$(this).removeClass("ui-radio-acitve")
|
||
} else {
|
||
//未选
|
||
canvas.getActiveObject().set("linethrough", true)
|
||
$(this).addClass("ui-radio-acitve")
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#lock").click(function () {
|
||
canvas.getActiveObject().set("selectable", !canvas.getActiveObject().get("selectable"));
|
||
if (canvas.getActiveObject().get("selectable")) {
|
||
$("#lock_img").attr("src", "public/images/unlock20.png")//已经上锁,需要解锁
|
||
} else {
|
||
$("#lock_img").attr("src", "public/images/lock20.png")//没上锁,可以上锁
|
||
}
|
||
recordState();
|
||
canvas.renderAll();
|
||
});
|
||
$("#text_back_transparent").click(function () {
|
||
canvas.getActiveObject().set("textBackgroundColor", "");
|
||
$("#text_back_color").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
$("#circle_text_back_transparent").click(function () {
|
||
canvas.getActiveObject().set("textBackgroundColor", "");
|
||
$("#circle_text_back_color").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
$("#out_text_back_transparent").click(function () {
|
||
canvas.getActiveObject().set("textBackgroundColor", "");
|
||
$("#out_text_back_color").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
$("#rect_transparent").click(function () {
|
||
canvas.getActiveObject().set("fill", "");
|
||
$("#rect_color").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
$("#rect_stroke_transparent").click(function () {
|
||
canvas.getActiveObject().set("stroke", "");
|
||
$("#rect_stroke").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
$("#circle_transparent").click(function () {
|
||
canvas.getActiveObject().set("fill", "");
|
||
$("#circle_color").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
$("#circle_stroke_transparent").click(function () {
|
||
canvas.getActiveObject().set("stroke", "");
|
||
$("#circle_stroke").val("#ffffff");
|
||
canvas.renderAll();
|
||
});
|
||
|
||
function saveAs(op1, callback) {
|
||
let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let _g1 = [], _g2 = [];
|
||
let left = 0, top = 0;
|
||
for (let _o of canvas1.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g1.push(fabric.util.object.clone(_o));
|
||
}
|
||
let fp = new fabric.Group(_g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
left = 0, top = 0;
|
||
for (let _o of canvas2.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g2.push(fabric.util.object.clone(_o));
|
||
}
|
||
//let fp = new fabric.Group(_g1).toDataURL();
|
||
let bp = new fabric.Group(_g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let o = { f: j, b: {}, fo: objs1, bo: objs2, fp: fp, bp: '' };
|
||
let con_o = Object.assign(o, op1);
|
||
dialog.showSaveDialog({
|
||
title: language_str("saveFile"),//'保存文件'
|
||
filters: [
|
||
{ name: 'Soon File Type', extensions: ['soon'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.filePath == "") { return; }
|
||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
||
result.filePath += '.soon';
|
||
}
|
||
let fs = require('fs')
|
||
con_o.soonType = 1
|
||
fs.writeFileSync(result.filePath, JSON.stringify(con_o))
|
||
openAs.name = result.filePath;
|
||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||
saveHistory();
|
||
if (callback && typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
}).catch(err => {
|
||
console.log()
|
||
})
|
||
}
|
||
function save(op1, callback) {
|
||
let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let _g1 = [], _g2 = [];
|
||
let left = 0, top = 0;
|
||
for (let _o of canvas1.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g1.push(fabric.util.object.clone(_o));
|
||
}
|
||
let fp = new fabric.Group(_g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
left = 0, top = 0;
|
||
for (let _o of canvas2.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g2.push(fabric.util.object.clone(_o));
|
||
}
|
||
//let fp = new fabric.Group(_g1).toDataURL();
|
||
let bp = new fabric.Group(_g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let o = { f: j, b: {}, fo: objs1, bo: objs2, fp: fp, bp: '' };
|
||
let con_o = Object.assign(o, op1);
|
||
if (openAs.name != "") {
|
||
//打开的文件
|
||
let fs = require('fs')
|
||
con_o.soonType = 1
|
||
fs.writeFileSync(openAs.name, JSON.stringify(con_o))
|
||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||
saveHistory();
|
||
if (callback && typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
return;
|
||
}
|
||
dialog.showSaveDialog({
|
||
title: language_str("saveFile"),//'保存文件'
|
||
filters: [
|
||
{ name: 'Soon File Type', extensions: ['soon'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.filePath == "") { return; }
|
||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
||
result.filePath += '.soon';
|
||
}
|
||
let fs = require('fs')
|
||
con_o.soonType = 1
|
||
fs.writeFileSync(result.filePath, JSON.stringify(con_o))
|
||
openAs.name = result.filePath;
|
||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||
saveHistory();
|
||
if (callback && typeof callback === 'function') {
|
||
callback();
|
||
}
|
||
}).catch(err => {
|
||
console.log()
|
||
})
|
||
}
|
||
|
||
// ===========================================================
|
||
// 1. 剪贴板数据定义 (修改:改为存储数据 data,而不是对象引用)
|
||
// ===========================================================
|
||
let clipboardData = {
|
||
data: null, // 存储序列化后的 JSON 数据 + 业务属性
|
||
offset: 10 // 粘贴位置偏移量
|
||
};
|
||
|
||
// ===========================================================
|
||
// 2. 复制函数:深度拷贝当前选中对象的数据
|
||
// ===========================================================
|
||
function copySelection() {
|
||
const activeObjects = canvas.getActiveObjects();
|
||
|
||
if (!activeObjects || activeObjects.length === 0) {
|
||
layer.msg(language_str("selectPic") || "请先选择对象");
|
||
return;
|
||
}
|
||
|
||
// 【核心修复】
|
||
// 遍历选中的对象,同时保存它的 Fabric 画面数据 和 我们的 objs 业务数据
|
||
clipboardData.data = activeObjects.map(obj => {
|
||
let idx = getIndex(obj); // 获取对象在画布中的索引
|
||
|
||
// 获取业务属性 (objs数组中对应的那一项)
|
||
// 注意:idx=0 是背景图,objs数组是从下标0开始存第1个对象的,所以是 idx-1
|
||
let appData = (idx > 0 && objs[idx-1]) ? objs[idx-1] : { type: 0 };
|
||
|
||
return {
|
||
// 1. 保存画面样式 (坐标、颜色、字号等)
|
||
fabricJson: obj.toObject(['id', 'name', 'selectable', 'evented', 'data']),
|
||
// 2. 保存业务属性 (深拷贝,防止引用冲突)
|
||
appData: JSON.parse(JSON.stringify(appData))
|
||
};
|
||
});
|
||
|
||
clipboardData.offset = 10; // 重置偏移量
|
||
console.log(`已复制 ${activeObjects.length} 个对象`);
|
||
layer.msg("已复制");
|
||
}
|
||
|
||
// ===========================================================
|
||
// 3. 粘贴函数:根据保存的数据重建对象
|
||
// ===========================================================
|
||
function pasteFromClipboard() {
|
||
// 检查是否有数据
|
||
if (!clipboardData.data || clipboardData.data.length === 0) {
|
||
// layer.msg("剪贴板为空");
|
||
return;
|
||
}
|
||
|
||
// 1. 提取 Fabric JSON 准备恢复画面
|
||
const jsonToEnliven = clipboardData.data.map(item => item.fabricJson);
|
||
|
||
// 2. 恢复对象 (异步过程)
|
||
fabric.util.enlivenObjects(jsonToEnliven, function(objects) {
|
||
canvas.discardActiveObject();
|
||
|
||
objects.forEach((clone, index) => {
|
||
// --- A. 处理画面位置 ---
|
||
clone.set({
|
||
left: clone.left + clipboardData.offset,
|
||
top: clone.top + clipboardData.offset,
|
||
evented: true
|
||
});
|
||
|
||
// 如果是组内对象,需要特殊处理坐标
|
||
if (clone.group) {
|
||
clone.set({
|
||
left: clone.group.left + clipboardData.offset,
|
||
top: clone.group.top + clipboardData.offset
|
||
});
|
||
}
|
||
|
||
// --- B. 处理业务数据 ---
|
||
// 取出复制时保存的 appData
|
||
let savedAppData = clipboardData.data[index].appData;
|
||
let newAppData = JSON.parse(JSON.stringify(savedAppData)); // 再次深拷贝
|
||
|
||
// 修改名称,防止 ID 冲突 (例如 TEXT_1 -> TEXT_1_copy)
|
||
if (newAppData.name) {
|
||
newAppData.name = newAppData.name + "_copy";
|
||
}
|
||
|
||
// --- C. 添加到画布和数据数组 ---
|
||
canvas.add(clone);
|
||
objs.push(newAppData); // 将新业务数据推入当前页面的 objs 数组
|
||
});
|
||
|
||
// 3. 选中新粘贴出来的对象
|
||
let sel = new fabric.ActiveSelection(objects, { canvas: canvas });
|
||
canvas.setActiveObject(sel);
|
||
canvas.requestRenderAll();
|
||
|
||
// 4. 刷新列表和历史记录
|
||
updateList();
|
||
recordState();
|
||
|
||
// 5. 高亮左侧列表最后一项 (即新粘贴的项)
|
||
if(objs.length > 0) selectObj(objs.length - 1);
|
||
|
||
// 6. 增加下次粘贴的偏移量 (让用户知道粘贴了新东西)
|
||
clipboardData.offset += 10;
|
||
});
|
||
}
|
||
|
||
// ===========================================================
|
||
// 4. 按钮事件绑定 (保持原样)
|
||
// ===========================================================
|
||
// 复制
|
||
$("#copy").click(function () {
|
||
copySelection();
|
||
})
|
||
// 粘贴
|
||
$("#paste").click(function () {
|
||
pasteFromClipboard();
|
||
})
|
||
|
||
// 保存 (保持你原有的保存逻辑不变)
|
||
$("#save").click(function () {
|
||
output(); // 这里调用你的 output 函数
|
||
return;
|
||
// ... (下面是你原有的被 return 截断的代码,建议以后清理掉,但这里我按要求保留)
|
||
let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
// ... (省略你原来那段很长的保存代码) ...
|
||
});
|
||
|
||
|
||
function getDate() {
|
||
let date = new Date();
|
||
return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
|
||
}
|
||
function getAbsoluteXY(_obj) {
|
||
let coord = _obj.get("lineCoords");
|
||
return [_obj.get("left"), _obj.get("top")]
|
||
}
|
||
let fullPath = path.join(exePath, 'data.json')
|
||
// ==========================================
|
||
// 历史记录保存 (修复结构Bug + 自动置顶)
|
||
// ==========================================
|
||
function saveHistory() {
|
||
let fs = require('fs');
|
||
let j = { history: [] }; // 默认结构必须是数组
|
||
|
||
try {
|
||
// 1. 读取并解析现有文件
|
||
if (fs.existsSync(fullPath)) {
|
||
let content = fs.readFileSync(fullPath).toString();
|
||
// 防止空文件报错
|
||
if (content.trim()) {
|
||
j = JSON.parse(content);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error("读取历史记录失败,将重置:", e);
|
||
// 出错时使用默认空数组,不中断流程
|
||
j = { history: [] };
|
||
}
|
||
|
||
// 确保 j.history 是数组 (防御性编程)
|
||
if (!Array.isArray(j.history)) {
|
||
j.history = [];
|
||
}
|
||
|
||
// 2. 【核心优化】先过滤掉当前文件(如果已存在),然后加到最前面
|
||
// 这样可以实现“最近使用的文件排在第一位”的效果
|
||
let currentPath = openAs.name;
|
||
let newList = j.history.filter(item => item.path !== currentPath);
|
||
|
||
// 3. 插入到头部 (Unshift)
|
||
newList.unshift({
|
||
time: getDate(),
|
||
path: currentPath,
|
||
// type: 1 // 如果需要记录文件类型也可以加在这里
|
||
});
|
||
|
||
// 4. (可选) 限制历史记录数量,比如只保留最近20条,防止文件无限膨胀
|
||
if (newList.length > 20) {
|
||
newList = newList.slice(0, 20);
|
||
}
|
||
|
||
j.history = newList;
|
||
|
||
// 5. 统一写入
|
||
try {
|
||
fs.writeFileSync(fullPath, JSON.stringify(j));
|
||
} catch (e) {
|
||
console.error("写入历史记录失败:", e);
|
||
}
|
||
}
|
||
|
||
function open(file) {
|
||
console.log(file)
|
||
let fs = require('fs')
|
||
var fsData = fs.readFileSync(file)
|
||
openAs.name = file;
|
||
let j = JSON.parse(fsData.toString());
|
||
let left = background_image.left;
|
||
let top = background_image.top;
|
||
let new_left = j.f.objects[0].left;
|
||
let new_top = j.f.objects[0].top;
|
||
for (let o of j.f.objects) {
|
||
o.left = o.left - new_left + left;
|
||
o.top = o.top - new_top + top;
|
||
}
|
||
// for (let o of j.b.objects) {
|
||
// o.left = o.left - new_left + left;
|
||
// o.top = o.top - new_top + top;
|
||
// }
|
||
console.log(j.f)
|
||
canvas1.loadFromJSON(j.f);
|
||
canvas2.loadFromJSON(j.b);
|
||
background_image1 = canvas1.getObjects()[0];
|
||
background_image2 = canvas2.getObjects()[0];
|
||
|
||
objs2 = j.bo;
|
||
objs1 = j.fo;
|
||
step1.val = 0;
|
||
step2.val = 0;
|
||
recordJson1 = [];
|
||
recordJson2 = [];
|
||
recordObjs1 = [];
|
||
recordObjs2 = [];
|
||
if ($("#front_side").hasClass("ui-button-active")) {
|
||
objs = objs1;
|
||
recordObjs = recordObjs1;
|
||
recordJson = recordJson1;
|
||
step = step1;
|
||
background_image = background_image1;
|
||
} else if ($("#back_side").hasClass("ui-button-active")) {
|
||
objs = objs2;
|
||
recordObjs = recordObjs2;
|
||
recordJson = recordJson2;
|
||
background_image = background_image2;
|
||
step = step2;
|
||
}
|
||
canvas1.renderAll();
|
||
canvas2.renderAll();
|
||
updateList(); //修复打开新文件后无法撤销的bug
|
||
setTimeout(() => {
|
||
recordObjs1.push(JSON.stringify(objs1))
|
||
let j1 = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
j1.objects[0].hoverCursor = "default";
|
||
recordJson1.push(j1);
|
||
|
||
recordObjs2.push(JSON.stringify(objs2))
|
||
let j2 = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
// j2.objects[0].hoverCursor = "default";
|
||
recordJson2.push(j2);
|
||
}, 0);
|
||
}
|
||
$("#open").click(function () {
|
||
if (step.val == 0) {
|
||
OpenDialog();
|
||
return;
|
||
}
|
||
layer.confirm('<font style="color:black">' + language_str("whetherSave") + '</font>', function (index) {//confirm 是否保存当前文件?
|
||
output(OpenDialog);
|
||
layer.close(index);
|
||
|
||
}, function (index) {
|
||
OpenDialog();
|
||
});
|
||
function OpenDialog() {
|
||
dialog.showOpenDialog({
|
||
title: "请选择文件",//confirm
|
||
buttonLabel: language_str("comf"),//"确认"
|
||
filters: [
|
||
{ name: 'Soon File Type', extensions: ['soon'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.canceled) return;
|
||
console.log(result.filePaths)
|
||
let fs = require('fs')
|
||
var fsData = fs.readFileSync(result.filePaths[0])
|
||
openAs.name = result.filePaths[0];
|
||
let j = JSON.parse(fsData.toString());
|
||
let type = j.soonType ? j.soonType : j.backBlackPic ? 2 : 1;
|
||
if (type == 2) {
|
||
ipcRenderer.send('open-design-page', openAs.name, type);
|
||
return
|
||
}
|
||
let left = background_image.left;
|
||
let top = background_image.top;
|
||
let new_left = j.f.objects[0].left;
|
||
let new_top = j.f.objects[0].top;
|
||
for (let o of j.f.objects) {
|
||
o.left = o.left - new_left + left;
|
||
o.top = o.top - new_top + top;
|
||
}
|
||
// for (let o of j.b.objects) {
|
||
// o.left = o.left - new_left + left;
|
||
// o.top = o.top - new_top + top;
|
||
// }
|
||
canvas1.loadFromJSON(j.f);
|
||
canvas2.loadFromJSON(j.b);
|
||
background_image1 = canvas1.getObjects()[0];
|
||
background_image2 = canvas2.getObjects()[0];
|
||
|
||
objs2 = j.bo;
|
||
objs1 = j.fo;
|
||
step1.val = 0;
|
||
step2.val = 0;
|
||
recordJson1 = [];
|
||
recordJson2 = [];
|
||
recordObjs1 = [];
|
||
recordObjs2 = [];
|
||
if ($("#front_side").hasClass("ui-button-active")) {
|
||
objs = objs1;
|
||
recordObjs = recordObjs1;
|
||
recordJson = recordJson1;
|
||
step = step1;
|
||
background_image = background_image1;
|
||
} else if ($("#back_side").hasClass("ui-button-active")) {
|
||
objs = objs2;
|
||
recordObjs = recordObjs2;
|
||
recordJson = recordJson2;
|
||
background_image = background_image2;
|
||
step = step2;
|
||
}
|
||
canvas1.renderAll();
|
||
canvas2.renderAll();
|
||
updateList();
|
||
// 修复打开新文件后无法撤销的bug
|
||
setTimeout(() => {
|
||
recordObjs1.push(JSON.stringify(objs1))
|
||
let j1 = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
j1.objects[0].hoverCursor = "default";
|
||
recordJson1.push(j1);
|
||
|
||
recordObjs2.push(JSON.stringify(objs2))
|
||
let j2 = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
j2.objects[0].hoverCursor = "default";
|
||
recordJson2.push(j2);
|
||
}, 0);
|
||
}).catch(err => {
|
||
console.log(err)
|
||
})
|
||
}
|
||
});
|
||
function clearAll() {
|
||
//let blank = "{\"f\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"#000000\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"b\":{\"version\":\"4.6.0\",\"objects\":[{\"type\":\"image\",\"version\":\"4.6.0\",\"originX\":\"left\",\"originY\":\"top\",\"left\":253.5,\"top\":121.5,\"width\":2787,\"height\":2787,\"fill\":\"rgb(0,0,0)\",\"stroke\":null,\"strokeWidth\":0,\"strokeDashArray\":null,\"strokeLineCap\":\"butt\",\"strokeDashOffset\":0,\"strokeLineJoin\":\"miter\",\"strokeUniform\":false,\"strokeMiterLimit\":4,\"scaleX\":1,\"scaleY\":1,\"angle\":0,\"flipX\":false,\"flipY\":false,\"opacity\":1,\"shadow\":null,\"visible\":true,\"backgroundColor\":\"\",\"fillRule\":\"nonzero\",\"paintFirst\":\"fill\",\"globalCompositeOperation\":\"source-over\",\"skewX\":0,\"skewY\":0,\"cropX\":0,\"cropY\":0,\"selectable\":false,\"hoverable\":false,\"hoverCursor\":\"default\",\"src\":\"data:image/png;base64,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YFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIEDpfCiFAAAcY0lEQVSAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMTBAgQIECAAAECBAgQIECgTkAwqDu5hQkQIECAAAECBAgQIECAQBYQDLKRCQIECBAgQIAAAQIECBAgUCcgGNSd3MIECBAgQIAAAQIECBAgQCALCAbZyAQBAgQIECBAgAABAgQIEKgTEAzqTm5hAgQIECBAgAABAgQIECCQBQSDbGSCAAECBAgQIECAAAECBAjUCQgGdSe3MAECBAgQIECAAAECBAgQyAKCQTYyQYAAAQIECBAgQIAAAQIE6gQEg7qTW5gAAQIECBAgQIAAAQIECGQBwSAbmSBAgAABAgQIECBAgAABAnUCgkHdyS1MgAABAgQIECBAgAABAgSygGCQjUwQIECAAAECBAgQIECAAIE6AcGg7uQWJkCAAAECBAgQIECAAAECWUAwyEYmCBAgQIAAAQIECBAgQIBAnYBgUHdyCxMgQIAAAQIECBAgQIAAgSwgGGQjEwQIECBAgAABAgQIECBAoE5AMKg7uYUJECBAgAABAgQIECBAgEAWEAyykQkCBAgQIECAAAECBAgQIFAnIBjUndzCBAgQIECAAAECBAgQIEAgCwgG2cgEAQIECBAgQIAAAQIECBCoExAM6k5uYQIECBAgQIAAAQIECBAgkAUEg2xkggABAgQIECBAgAABAgQI1AkIBnUntzABAgQIECBAgAABAgQIEMgCgkE2MkGAAAECBAgQIECAAAECBOoEBIO6k1uYAAECBAgQIECAAAECBAhkAcEgG5kgQIAAAQIECBAgQIAAAQJ1AoJB3cktTIAAAQIECBAgQIAAAQIEsoBgkI1MECBAgAABAgQIECBAgACBOgHBoO7kFiZAgAABAgQIECBAgAABAllAMMhGJggQIECAAAECBAgQIECAQJ2AYFB3cgsTIECAAAECBAgQIECAAIEsIBhkIxMECBAgQIAAAQIECBAgQKBOQDCoO7mFCRAgQIAAAQIECBAgQIBAFhAMspEJAgQIECBAgAABAgQIECBQJyAY1J3cwgQIECBAgAABAgQIECBAIAsIBtnIBAECBAgQIECAAAECBAgQqBMQDOpObmECBAgQIECAAAECBAgQIJAFBINsZIIAAQIECBAgQIAAAQIECNQJCAZ1J7cwAQIECBAgQIAAAQIECBDIAoJBNjJBgAABAgQIECBAgAABAgTqBASDupNbmAABAgQIECBAgAABAgQIZAHBIBuZIECAAAECBAgQIECAAAECdQKCQd3JLUyAAAECBAgQIECAAAECBLKAYJCNTBAgQIAAAQIECBAgQIAAgToBwaDu5BYmQIAAAQIECBAgQIAAAQJZQDDIRiYIECBAgAABAgQIECBAgECdgGBQd3ILEyBAgAABAgQIECBAgACBLCAYZCMT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\",\"crossOrigin\":null,\"filters\":[]}],\"hoverCursor\":\"move\"},\"fo\":[],\"bo\":[]}";
|
||
//let j = JSON.parse(blank);
|
||
//canvas1.setZoom(1);
|
||
//canvas2.setZoom(1);
|
||
//canvas1.loadFromJSON(j.f);
|
||
//canvas2.loadFromJSON(j.b);
|
||
let t_objs1 = canvas1.getObjects();
|
||
let t_objs2 = canvas2.getObjects();
|
||
for (let i = 1; i < t_objs1.length; i++) {
|
||
canvas1.remove(t_objs1[i]);
|
||
}
|
||
for (let i = 1; i < t_objs2.length; i++) {
|
||
canvas2.remove(t_objs2[i]);
|
||
}
|
||
objs2 = [];
|
||
objs1 = [];
|
||
step1.val = 0;
|
||
step2.val = 0;
|
||
recordJson1 = [];
|
||
recordJson2 = [];
|
||
recordObjs1 = [];
|
||
recordObjs2 = [];
|
||
if ($("#front_side").hasClass("ui-button-active")) {
|
||
objs = objs1;
|
||
recordObjs = recordObjs1;
|
||
recordJson = recordJson1;
|
||
step = step1;
|
||
} else if ($("#back_side").hasClass("ui-button-active")) {
|
||
objs = objs2;
|
||
recordObjs = recordObjs2;
|
||
recordJson = recordJson2;
|
||
step = step2;
|
||
}
|
||
openAs.name = "";
|
||
canvas1.renderAll();
|
||
canvas2.renderAll();
|
||
updateList();
|
||
console.log();
|
||
}
|
||
$("#new").click(function () {
|
||
if (step.val == 0) {
|
||
ipcRenderer.send('open-first-page');
|
||
return;
|
||
}
|
||
layer.confirm('<font style="color:black">' + language_str("whetherSave") + '</font>', function (index) {//confirm 是否保存当前文件?
|
||
output(() => ipcRenderer.send('open-first-page'));
|
||
return;
|
||
let j = canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let b = canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
let _g1 = [], _g2 = [];
|
||
let left = 0, top = 0;
|
||
for (let _o of canvas1.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g1.push(fabric.util.object.clone(_o));
|
||
}
|
||
let fp = new fabric.Group(_g1).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
left = 0, top = 0;
|
||
for (let _o of canvas2.getObjects()) {
|
||
if (getCoordsMinX(background_image.getCoords()) - getCoordsMinX(_o.getCoords()) > left) {
|
||
left = -(getCoordsMinX(_o.getCoords()) - getCoordsMinX(background_image.getCoords()));
|
||
}
|
||
if (getCoordsMinY(background_image.getCoords()) - getCoordsMinY(_o.getCoords()) > top) {
|
||
top = -(getCoordsMinY(_o.getCoords()) - getCoordsMinY(background_image.getCoords()));
|
||
}
|
||
_g2.push(fabric.util.object.clone(_o));
|
||
}
|
||
//let fp = new fabric.Group(_g1).toDataURL();
|
||
let bp = new fabric.Group(_g2).toDataURL({
|
||
height: 2787,
|
||
width: 2787,
|
||
top: top,
|
||
left: left
|
||
});
|
||
let o = { f: j, b: {}, fo: objs1, bo: objs2, fp: fp, bp: '' };
|
||
if (openAs.name != "") {
|
||
//打开的文件
|
||
let fs = require('fs')
|
||
o.soonType = 1
|
||
fs.writeFileSync(openAs.name, JSON.stringify(o))
|
||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||
/*
|
||
2022-07-16 直接跳转至首页
|
||
*/
|
||
ipcRenderer.send('open-first-page');
|
||
//saveHistory();
|
||
//clearAll();
|
||
return;
|
||
}
|
||
dialog.showSaveDialog({
|
||
title: language_str("saveFile"),//'保存文件'
|
||
filters: [
|
||
{ name: 'Soon File Type', extensions: ['soon'] },
|
||
]
|
||
}).then(result => {
|
||
if (result.filePath == "") { return; }
|
||
if (result.filePath.substring(result.filePath.length - 5).indexOf('.') == -1) {
|
||
result.filePath += '.soon';
|
||
}
|
||
let fs = require('fs')
|
||
o.soonType = 1
|
||
fs.writeFileSync(result.filePath, JSON.stringify(o))
|
||
openAs.name = result.filePath;
|
||
layer.msg(language_str("saveSucc") + openAs.name);//'保存成功至'
|
||
/*
|
||
2022-07-16 直接跳转至首页
|
||
*/
|
||
ipcRenderer.send('open-first-page');
|
||
//saveHistory();
|
||
//clearAll();
|
||
}).catch(err => {
|
||
console.log()
|
||
})
|
||
layer.close(index);
|
||
|
||
}, function (index) {
|
||
/*
|
||
2022-07-16 直接跳转至首页
|
||
*/
|
||
//clearAll();
|
||
ipcRenderer.send('open-first-page');
|
||
});
|
||
});
|
||
function chagneTitle() {
|
||
|
||
}
|
||
function addBackground() {
|
||
// 类型改变
|
||
fabric.Image.fromURL('./public/images/bg_front_1.png', function (image) {
|
||
let width = $("#canvas1").width()
|
||
|
||
image.left = ($("#canvas1").width() - image.width * image.get("scaleX")) / 2;
|
||
image.top = ($("#canvas1").height() - image.height * image.get("scaleY")) / 2;
|
||
|
||
image.selectable = false;
|
||
image.hoverable = false;
|
||
image.hoverCursor = "default"
|
||
image.setSrc(image.toDataURL(), function (image) {
|
||
image.scale(1, 1);
|
||
background_image1 = image;
|
||
background_image = background_image1;
|
||
canvas.add(image);
|
||
canvas.renderAll();
|
||
//pre_objs1.push(JSON.stringify(objs1));
|
||
//pre_json1.push(canvas1.toJSON(["selectable","hoverable","hoverCursor"]));
|
||
|
||
recordObjs1.push(JSON.stringify(objs1));
|
||
recordJson1.push(canvas1.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]));
|
||
});
|
||
// 类型改变
|
||
fabric.Image.fromURL('./public/images/bg_back.png', function (image) {
|
||
image.left = ($("#canvas2").width() - image.width) / 2;
|
||
image.top = ($("#canvas2").height() - image.height) / 2;
|
||
|
||
image.selectable = false;
|
||
image.hoverable = false;
|
||
image.hoverCursor = "default"
|
||
|
||
image.setSrc(image.toDataURL(), function (image) {
|
||
background_image2 = image;
|
||
canvas2.add(image);
|
||
canvas2.renderAll();
|
||
//pre_objs2.push(JSON.stringify(objs2));
|
||
//pre_json2.push(canvas2.toJSON(["selectable","hoverable","hoverCursor"]));
|
||
|
||
recordObjs2.push(JSON.stringify(objs2));
|
||
recordJson2.push(canvas2.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]));
|
||
|
||
let file = GetFile().get('file')
|
||
console.log(file)
|
||
if (file && file != 'empty') {
|
||
open(file)
|
||
}
|
||
});
|
||
});
|
||
is_bgi_add = true;
|
||
});
|
||
}
|
||
function selectObject(target, index) {
|
||
updateControls();
|
||
|
||
$("#base_control").show();
|
||
//$("#text_x").val((target.left - background_image.left).toFixed(1));
|
||
//$("#text_y").val((target.top - background_image.top).toFixed(1));
|
||
//$("#text_w").val(parseFloat(target.get("scaleX") * target.get("width")).toFixed(1));
|
||
//$("#text_h").val(parseFloat(target.get("scaleY") * target.get("height")).toFixed(1));
|
||
//$("#text_r").val(target.get("angle").toFixed(0));
|
||
}
|
||
function updateControls() {
|
||
$("#text_r").val(canvas.getActiveObject().get("angle").toFixed(0));
|
||
$("#text_x").val((canvas.getActiveObject().get("left") - background_image.left).toFixed(0));
|
||
$("#text_y").val((canvas.getActiveObject().get("top") - background_image.top).toFixed(0));
|
||
$("#text_h").val((canvas.getActiveObject().get("scaleY") * canvas.getActiveObject().get("height")).toFixed(0));
|
||
$("#text_w").val((canvas.getActiveObject().get("scaleX") * canvas.getActiveObject().get("width")).toFixed(0));
|
||
if (canvas.getActiveObject().get("selectable")) {
|
||
$("#lock_img").attr("src", "public/images/unlock20.png")//已经上锁,需要解锁
|
||
} else {
|
||
$("#lock_img").attr("src", "public/images/lock20.png")//没上锁,可以上锁
|
||
}
|
||
}
|
||
function checkName(name) {
|
||
//检查字段名是否重复了
|
||
for (let item of objs1) {
|
||
if (item.name == name) {
|
||
return false;
|
||
}
|
||
}
|
||
for (let item of objs2) {
|
||
if (item.name == name) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
function resName(pre_name) {
|
||
//返回的是不重复的字段名
|
||
let num = (objs1.length + objs2.length) - 1;
|
||
do {
|
||
num++;
|
||
}
|
||
while (!checkName(pre_name + num));//重复了就再加1
|
||
return pre_name + num;
|
||
}
|
||
function addPic(pointer) {
|
||
|
||
pre_add_image.left = pointer.x;
|
||
pre_add_image.top = pointer.y;
|
||
|
||
canvas.add(pre_add_image);
|
||
|
||
objs.push({ type: 1, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
//OpenDialog();
|
||
//function OpenDialog()
|
||
//{
|
||
// dialog.showOpenDialog({
|
||
// title: "请选择图片",
|
||
// buttonLabel: "确认",
|
||
// filters: [
|
||
// { name: 'Image File Type', extensions: ['png', 'jpg'] },
|
||
// ]
|
||
// }).then(result => {
|
||
// if(result.canceled)return;
|
||
// //console.log(result.filePaths)
|
||
// fabric.Image.fromURL(result.filePaths[0], function(image) {
|
||
// image.left = pointer.x;
|
||
// image.top = pointer.y;
|
||
//
|
||
// canvas.add(image);
|
||
// objs.push({type: 1});
|
||
// canvas.renderAll();
|
||
// updateList();
|
||
// recordState();
|
||
// } );
|
||
// }).catch(err => {
|
||
// console.log(err)
|
||
// })
|
||
//}
|
||
}
|
||
function selectPic(target, index) {
|
||
//透明度
|
||
|
||
$("#pic_control").show();
|
||
$("#set_bg").show();
|
||
pic_op.setValue(100 - (canvas.getActiveObject().get("opacity") * 100));
|
||
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
// $("#pic_black").prop("checked", objs[idx-1].black ? 'checked' : '');
|
||
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
|
||
}
|
||
function addOutPic(pointer) {
|
||
fabric.Image.fromURL('./public/images/outpic_extra.png', function (image) {
|
||
let width = canvas.getWidth();
|
||
let height = canvas.getHeight();
|
||
image.left = pointer.x;
|
||
image.top = pointer.y;
|
||
image.opacity = 1;
|
||
//image.on("selected",function(){//test well
|
||
// console.log(222);
|
||
//});
|
||
image.setSrc(image.toDataURL(), function (image) {
|
||
canvas.add(image);
|
||
objs.push({ type: 2, name: resName("OUT_PIC_"), black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
});
|
||
});
|
||
}
|
||
function selectOutPic(target, index) {
|
||
//字段名
|
||
$("#out_pic_control").show();
|
||
out_pic_op.setValue(100 - (canvas.getActiveObject().get("opacity") * 100));
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#out_pic_field_name").val(objs[idx - 1].name);
|
||
// $("#out_pic_black").prop("checked", objs[idx-1].black ? 'checked' : '');
|
||
|
||
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
}
|
||
|
||
function addText(pointer) {
|
||
let text = new fabric.Text('TEXT', {//源:文本
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
fill: "#000000",
|
||
textBackgroundColor: "",
|
||
fontStyle: "normal",
|
||
fontWeight: "normal",
|
||
fontSize: 100,
|
||
underline: false,
|
||
linethrough: false,
|
||
fontFamily: 'Arial'
|
||
});
|
||
text.setControlVisible("ml", false);
|
||
text.setControlVisible("mt", false);
|
||
text.setControlVisible("mr", false);
|
||
text.setControlVisible("mb", false);
|
||
canvas.add(text);
|
||
objs.push({ type: 3, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
function selectText() {
|
||
//console.log(canvas.getActiveObject().get("fontFamily"));
|
||
$("#text_control").show();
|
||
$("#text_color").val(canvas.getActiveObject().get("fill"));
|
||
$("#text_back_color").val(canvas.getActiveObject().get("textBackgroundColor") == "" ? '#ffffff' : canvas.getActiveObject().get("textBackgroundColor"));
|
||
let val = parseFloat(canvas.getActiveObject().get("fontSize"))*72/dpi
|
||
if (val%0.5!==0) val = Math.round(val*2)/2
|
||
$("#text_size").val(val);
|
||
$("#text_text").val(canvas.getActiveObject().get("text"));
|
||
$("#text_font_family").val(canvas.getActiveObject().get("fontFamily"));
|
||
|
||
if (canvas.getActiveObject().get("underline") == true) {
|
||
$("#text_underline").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#text_underline").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("fontWeight") == "bold") {
|
||
$("#text_bold").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#text_bold").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("fontStyle") == "italic") {
|
||
$("#text_italics").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#text_italics").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("linethrough") == true) {
|
||
$("#text_linethrough").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#text_linethrough").removeClass("ui-radio-acitve")
|
||
}
|
||
$("#circle_text_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
|
||
}
|
||
function getDisdance(x1, y1, x2, y2) {
|
||
var dx = Math.abs(x2 - x1); // 计算x轴上的距离差,并取绝对值
|
||
var dy = Math.abs(y2 - y1); // 计算y轴上的距离差,并取绝对值
|
||
var distance = Math.sqrt(dx * dx + dy * dy); // 应用勾股定理计算距离
|
||
return distance;
|
||
}
|
||
function getDeg(pointer) {
|
||
// 计算点击位置与画布中心的坐标差
|
||
var centerX = canvas.width / 2;
|
||
var centerY = canvas.height / 2;
|
||
var mouseX = pointer.x;
|
||
var mouseY = pointer.y;
|
||
var dx = mouseX - centerX;
|
||
var dy = mouseY - centerY;
|
||
// 计算旋转角度(弧度)
|
||
var angleRad = Math.atan2(dy, dx);
|
||
// 将角度转换为度数
|
||
var angleDeg = angleRad * (180/Math.PI);
|
||
if (angleDeg < 0) {
|
||
angleDeg += 360;
|
||
}
|
||
angleDeg += 90
|
||
return angleDeg
|
||
}
|
||
function addCircleText(pointer) {
|
||
let distance = getDisdance(pointer.x, pointer.y, canvas.width/2,canvas.height/2)
|
||
let angleDeg = getDeg(pointer)
|
||
let text = new fabric.CurvedText('Circle TEXT', {//源:圆形文本
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
fill: "#000000",
|
||
textBackgroundColor: "",
|
||
fontStyle: "normal",
|
||
fontWeight: "normal",
|
||
diameter: distance*2,
|
||
fontSize: 100,
|
||
underline: false,
|
||
linethrough: false,
|
||
lockScalingX: true,
|
||
lockScalingY: true,
|
||
fontFamily: 'Arial',
|
||
originX: 'center',
|
||
// originY: 'center',
|
||
angle: angleDeg,
|
||
flipped: pointer.y > canvas.height/2 ? true : false
|
||
});
|
||
// distance = getDisdance(pointer.x+text.width/2, pointer.y, canvas.width/2,canvas.height/2)
|
||
// text.set({diameter: distance*2})
|
||
text.setControlVisible("ml", false);
|
||
text.setControlVisible("mt", false);
|
||
text.setControlVisible("mr", false);
|
||
text.setControlVisible("mb", false);
|
||
canvas.add(text);
|
||
objs.push({ type: 11, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
function selectCircleText() {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#circle_text_control").show();
|
||
$("#circle_text_color").val(canvas.getActiveObject().get("fill"));
|
||
$("#circle_text_back_color").val(canvas.getActiveObject().get("textBackgroundColor") == "" ? '#ffffff' : canvas.getActiveObject().get("textBackgroundColor"));
|
||
circle_text_size.setValue(canvas.getActiveObject().get("fontSize") - 10);
|
||
circle_text_diameter.setValue(canvas.getActiveObject().get("diameter")-500);
|
||
$("#circle_text_center").prop("checked", objs[idx - 1].circleCenter ? 'checked' : '');
|
||
$("#circle_text_text").val(canvas.getActiveObject().get("text"));
|
||
$("#circle_text_font_family").val(canvas.getActiveObject().get("fontFamily"));
|
||
|
||
if (canvas.getActiveObject().get("underline") == true) {
|
||
$("#circle_text_underline").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#circle_text_underline").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("fontWeight") == "bold") {
|
||
$("#circle_text_bold").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#circle_text_bold").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("fontStyle") == "italic") {
|
||
$("#circle_text_italics").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#circle_text_italics").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("linethrough") == true) {
|
||
$("#circle_text_linethrough").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#circle_text_linethrough").removeClass("ui-radio-acitve")
|
||
}
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#rotate").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
|
||
}
|
||
function addOutText(pointer) {
|
||
//MERGE_TEXT_1
|
||
let text = new fabric.Text("MERGE TEXT", {//源:合成文本
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
fill: "#000000",
|
||
fontStyle: "normal",
|
||
fontWeight: "normal",
|
||
fontSize: 100,
|
||
textBackgroundColor: "",
|
||
underline: false,
|
||
linethrough: false,
|
||
fontFamily: 'Arial',
|
||
textAlign: 'center'
|
||
});
|
||
|
||
//text.on({
|
||
// 'scaling': function(e) {
|
||
// var obj = this,
|
||
// w = obj.width * obj.scaleX,
|
||
// h = obj.height * obj.scaleY;
|
||
//
|
||
// obj.set({
|
||
// 'height' : h,
|
||
// 'width' : w,
|
||
// 'scaleX' : 1,
|
||
// 'scaleY' : 1
|
||
// });
|
||
// }
|
||
//});
|
||
text.setControlVisible("ml", false);
|
||
text.setControlVisible("mt", false);
|
||
text.setControlVisible("mr", false);
|
||
text.setControlVisible("mb", false);
|
||
|
||
canvas.add(text);
|
||
objs.push({ type: 4, name: resName("OUT_TEXT_"), exceed: false, autoWrap: false, fixSize: false, black: false, align: 'center' });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
function selectOutText() {
|
||
//color
|
||
//size
|
||
const align = canvas.getActiveObject().get('textAlign')
|
||
if (align === 'left') {
|
||
$('#out_left_alignment').parent().addClass('tool1')
|
||
} else if (align === 'right') {
|
||
$('#out_right_alignment').parent().addClass('tool1')
|
||
} else {
|
||
$('#out_center_alignment').parent().addClass('tool1')
|
||
}
|
||
$("#out_text_control").show();
|
||
$("#out_text_color").val(canvas.getActiveObject().get("fill"));
|
||
$("#out_text_text").val(canvas.getActiveObject().get("text"));
|
||
let val = parseFloat(canvas.getActiveObject().get("fontSize"))*72/dpi
|
||
if (val%0.5!==0) val = Math.round(val*2)/2
|
||
$("#out_text_size").val(val);
|
||
$("#out_text_back_color").val(canvas.getActiveObject().get("textBackgroundColor") == "" ? '#ffffff' : canvas.getActiveObject().get("textBackgroundColor"));
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#out_text_field_name").val(objs[idx - 1].name);
|
||
$("#out_text_font_family").val(canvas.getActiveObject().get("fontFamily"));
|
||
$("#exceed").prop("checked", objs[idx - 1].exceed ? 'checked' : '');
|
||
$("#autoWrap").prop("checked", objs[idx - 1].autoWrap ? 'checked' : '');
|
||
$("#fixSize").prop("checked", objs[idx - 1].fixSize ? 'checked' : '');
|
||
if (canvas.getActiveObject().get("underline") == true) {
|
||
$("#out_text_underline").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#out_text_underline").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("fontWeight") == "bold") {
|
||
$("#out_text_bold").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#out_text_bold").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("fontStyle") == "italic") {
|
||
$("#out_text_italics").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#out_text_italics").removeClass("ui-radio-acitve")
|
||
}
|
||
if (canvas.getActiveObject().get("linethrough") == true) {
|
||
$("#out_text_linethrough").addClass("ui-radio-acitve")
|
||
} else {
|
||
$("#out_text_linethrough").removeClass("ui-radio-acitve")
|
||
}
|
||
|
||
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
}
|
||
function addRect(pointer) {
|
||
let rect = new fabric.Rect({
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
fill: '',
|
||
stroke: "#ff0000",
|
||
strokeWidth: 10,
|
||
width: 300,
|
||
height: 300
|
||
});
|
||
canvas.add(rect);
|
||
objs.push({ type: 5, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
function selectRect() {
|
||
//color
|
||
$("#rect_control").show();
|
||
$("#rect_color").val(canvas.getActiveObject().get("fill") == "" ? "#ffffff" : canvas.getActiveObject().get("fill"));
|
||
$("#rect_stroke").val(canvas.getActiveObject().get("stroke") == "" ? "#ffffff" : canvas.getActiveObject().get("stroke"));
|
||
$("#rect_stroke_width").val(canvas.getActiveObject().get("strokeWidth"));
|
||
$("#rect_radius").val(canvas.getActiveObject().get("rx"));
|
||
rect_op.setValue(100 - (canvas.getActiveObject().get("opacity") * 100));
|
||
let a = canvas.getActiveObject().getCoords();
|
||
console.log(getCoordsMinX(a));
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
}
|
||
function addCircle(pointer) {
|
||
let circle = new fabric.Circle({
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
fill: '',
|
||
stroke: '#ff0000',
|
||
strokeWidth: 10,
|
||
radius: 150,
|
||
strokeUniform: true,
|
||
});
|
||
canvas.add(circle);
|
||
objs.push({ type: 6, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
function selectCircle() {
|
||
//border-color
|
||
//color
|
||
$("#circle_control").show();
|
||
$("#circle_color").val(canvas.getActiveObject().get("fill") == "" ? "#ffffff" : canvas.getActiveObject().get("fill"));
|
||
$("#circle_stroke").val(canvas.getActiveObject().get("stroke") == "" ? "#ffffff" : canvas.getActiveObject().get("stroke"));
|
||
$("#circle_stroke_width").val(canvas.getActiveObject().get("strokeWidth"));
|
||
circle_op.setValue(100 - (canvas.getActiveObject().get("opacity") * 100));
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#line_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
}
|
||
function addLine(pointer) {
|
||
let line = new fabric.Line([100, 200, 400, 200], {
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
stroke: '#ff0000',
|
||
strokeWidth: 10,
|
||
strokeDashArray: [0, 0],
|
||
});
|
||
|
||
line.setControlVisible("tl", false);
|
||
line.setControlVisible("tr", false);
|
||
line.setControlVisible("br", false);
|
||
line.setControlVisible("bl", false);
|
||
line.setControlVisible("mt", false);
|
||
line.setControlVisible("mb", false);
|
||
canvas.add(line);
|
||
objs.push({ type: 7, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
function selectLine() {
|
||
//color
|
||
//weight
|
||
$("#line_control").show();
|
||
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#line_color").val(canvas.getActiveObject().get("stroke"));
|
||
$("#line_dist").val(canvas.getActiveObject().get("strokeDashArray")[0]);
|
||
$("#text_h").val(canvas.getActiveObject().get("strokeWidth"))
|
||
|
||
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
}
|
||
function addQrCode(pointer) {
|
||
|
||
let qr = jrQrcode.getQrBase64('https://www.cardsoon.com', { padding: 0 });
|
||
fabric.Image.fromURL(qr, function (image) {
|
||
image.left = pointer.x;
|
||
image.top = pointer.y;
|
||
image.scale(2.4, 2.4)
|
||
canvas.add(image);
|
||
objs.push({ type: 8, name: resName("QR_CODE_"), color: "#000000", val: "https://www.cardsoon.com", black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
});
|
||
}
|
||
function selectQrCode() {
|
||
//字段名
|
||
//background-color
|
||
//color
|
||
$("#qrcode_Controll").show();
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#qrcode_field_name").val(objs[idx - 1].name);
|
||
$("#qrcode_color").val(objs[idx - 1].color);
|
||
$("#qrcode_val").val(objs[idx - 1].val);
|
||
$("#line_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#barcode_controll").hide();
|
||
}
|
||
function addBarCode(pointer) {
|
||
JsBarcode("#barcode", "123456789", { margin: 0, lineColor: "#000000", fontSize: 18, font: "Arial" });
|
||
let barcode = document.getElementById('barcode');
|
||
let bar = barcode.toDataURL("image/png");
|
||
fabric.Image.fromURL(bar, function (image) {
|
||
image.left = pointer.x;
|
||
image.top = pointer.y;
|
||
image.scale(2.4, 2.4)
|
||
canvas.add(image);
|
||
objs.push({ type: 9, name: resName("BAR_CODE_"), val: "123456789", color: "#000000", fontSize: 18, font: "Arial", show: false, black: false });//show是取消文字显示
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
});
|
||
}
|
||
function selectBarCode() {
|
||
//字段名
|
||
//background-color
|
||
//color
|
||
$("#barcode_controll").show();
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#barcode_field_name").val(objs[idx - 1].name);
|
||
$("#barcode_font_family").val(objs[idx - 1].font);
|
||
let val = parseFloat(objs[idx - 1].fontSize)*72/dpi
|
||
if (val%0.5!==0) val = Math.round(val*2)/2
|
||
$("#barcode_size").val(val);
|
||
$("#barcode_val").val(objs[idx - 1].val);
|
||
$("#barcode_show").prop("checked", objs[idx - 1].show ? 'checked' : '');
|
||
$("#line_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#counter_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
}
|
||
function addCounter(pointer) {
|
||
let text = new fabric.Text('0', {
|
||
left: pointer.x,
|
||
top: pointer.y,
|
||
fontSize: 100,
|
||
fill: "#000000",
|
||
});
|
||
canvas.add(text);
|
||
objs.push({ type: 10, name: resName("COUNTER_"), start: 0, add: 1, black: false });
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
console.log(canvas.getObjects())
|
||
}
|
||
function selectCounter() {
|
||
//起始
|
||
//终止
|
||
//增量
|
||
$("#counter_control").show();
|
||
|
||
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
$("#counter_start").val(objs[idx - 1].start);
|
||
$("#counter_add").val(objs[idx - 1].add);
|
||
$("#counter_color").val(canvas.getActiveObject().get("fill"));
|
||
$("#count_font_family").val(canvas.getActiveObject().get("fontFamily"));
|
||
let val = parseFloat(canvas.getActiveObject().get("fontSize"))*72/dpi
|
||
if (val%0.5!==0) val = Math.round(val*2)/2
|
||
$("#count_size").val(val);
|
||
|
||
$("#line_control").hide();
|
||
$("#pic_control").hide();
|
||
$("#set_bg").hide();
|
||
$("#out_pic_control").hide();
|
||
$("#text_control").hide();
|
||
$("#circle_text_control").hide();
|
||
$("#out_text_control").hide();
|
||
$("#rect_control").hide();
|
||
$("#circle_control").hide();
|
||
$("#qrcode_Controll").hide();
|
||
$("#barcode_controll").hide();
|
||
|
||
}
|
||
function getIndex(target, _canvas = null) {
|
||
let temp_objs;
|
||
if (_canvas == null) {
|
||
temp_objs = canvas.getObjects();
|
||
} else {
|
||
temp_objs = _canvas.getObjects();
|
||
}
|
||
|
||
let i = 0;
|
||
for (let res of temp_objs) {
|
||
if (target == res) {
|
||
return i;
|
||
}
|
||
i++;
|
||
}
|
||
return 0;
|
||
}
|
||
function getType(target) {
|
||
let temp_objs = canvas.getObjects();
|
||
let i = 0;
|
||
for (let res of temp_objs) {
|
||
if (target == res) {
|
||
return objs[i].type;
|
||
}
|
||
i++;
|
||
}
|
||
}
|
||
// ===========================================================
|
||
// 1. 刷新对象列表 (序号顺序:底层=1,顶层=N,修复:Flex布局防遮挡 + 序号靠右)
|
||
// ===========================================================
|
||
function updateList() {
|
||
let str = "";
|
||
let i = 0;
|
||
|
||
// 定义行样式:Flex布局,两端对齐,相对定位防止溢出
|
||
const rowStyle = "display:flex; justify-content:space-between; align-items:center; height:32px; padding:0 5px; cursor:pointer; border-bottom:1px solid #444; color:#ccc; font-size:12px; position:relative;";
|
||
// 定义左侧内容样式
|
||
const leftStyle = "display:flex; align-items:center; overflow:hidden; white-space:nowrap; max-width:180px;";
|
||
// 定义序号样式:靠右,有左边框
|
||
const indexStyle = "min-width:24px; text-align:center; padding-left:5px; color:#666; border-left:1px solid #555;";
|
||
|
||
for (let item of objs) {
|
||
let displayIndex = i + 1; // 序号底层为1
|
||
|
||
// 图标逻辑
|
||
let iconName = "rect.svg";
|
||
switch (item.type) {
|
||
case 1: iconName = "images.svg"; break;
|
||
case 2: iconName = "images_add.svg"; break;
|
||
case 3: iconName = "text.svg"; break;
|
||
case 4: iconName = "text2.svg"; break;
|
||
case 5: iconName = "rect.svg"; break;
|
||
case 6: iconName = "round.svg"; break;
|
||
case 7: iconName = "line.svg"; break;
|
||
case 8: iconName = "qrcode.svg"; break;
|
||
case 9: iconName = "barcode.svg"; break;
|
||
case 10: iconName = "counter.svg"; break;
|
||
case 11: iconName = "text3.svg"; break;
|
||
}
|
||
|
||
// 名称逻辑
|
||
let nameText = item.name ? item.name :
|
||
(item.type === 3 ? "TEXT_" + displayIndex :
|
||
(item.type === 1 ? "IMG_" + displayIndex : "OBJ_" + displayIndex));
|
||
|
||
// 组装 HTML
|
||
str = `<div style="${rowStyle}">
|
||
<div style="${leftStyle}">
|
||
<img src="public/images/${iconName}" id="obj${i}" style="width:16px; margin-right:5px;">
|
||
<span title="${nameText}">${nameText}</span>
|
||
</div>
|
||
<span style="${indexStyle}">${displayIndex}</span>
|
||
</div>` + str;
|
||
i++;
|
||
}
|
||
$(".obj_list").html(str);
|
||
|
||
// 重新绑定点击事件(防止 updateList 后点击失效)
|
||
$(".obj_list > div").on("click", function () {
|
||
let imgId = $(this).find("img").attr("id");
|
||
if(imgId) {
|
||
let idx = parseInt(imgId.replace("obj", ""));
|
||
selectObj(idx);
|
||
}
|
||
});
|
||
}
|
||
|
||
// ===========================================================
|
||
// 2. 列表选中高亮 (修复:自动滚动 + 防冲突)
|
||
// ===========================================================
|
||
function selectObj(objIndices, isFromCanvas = false) {
|
||
let indicesArray = (Array.isArray(objIndices)) ? objIndices : ((typeof objIndices === 'number' && objIndices >= 0) ? [objIndices] : []);
|
||
|
||
// 清除所有高亮
|
||
$('.obj_list > div').css("background-color", "transparent");
|
||
|
||
// 遍历列表查找并高亮
|
||
$('.obj_list > div').each(function () {
|
||
let $img = $(this).find("img");
|
||
if ($img.length === 0) return;
|
||
|
||
let idIndex = parseInt($img.attr("id").replace("obj", ""));
|
||
|
||
if (indicesArray.includes(idIndex)) {
|
||
$(this).css("background-color", "#6F7A84");
|
||
|
||
// 自动滚动到可视区域
|
||
if (isFromCanvas && indicesArray[0] === idIndex) {
|
||
this.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
||
}
|
||
}
|
||
});
|
||
|
||
// 如果是点击列表,触发画布选中
|
||
if (!isFromCanvas && indicesArray.length === 1) {
|
||
let target = canvas.getObjects()[indicesArray[0] + 1];
|
||
if (target) {
|
||
canvas.setActiveObject(target);
|
||
canvas.requestRenderAll();
|
||
handleObjectSelected();
|
||
}
|
||
}
|
||
}
|
||
function recordState() {
|
||
//pre_objs.push(JSON.stringify(objs));
|
||
//pre_json.push(canvas.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"]));
|
||
//next_json = [];
|
||
//next_objs = [];
|
||
//recordObjs.push(JSON.stringify(objs));
|
||
//recordJson.push(canvas.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"]));
|
||
++step.val;
|
||
for (let i = step.val; i < recordObjs.length; i++) {
|
||
recordObjs.pop();
|
||
recordJson.pop();
|
||
}
|
||
//recordObjs.splice(step.val, 1, JSON.stringify(objs))
|
||
//recordJson.splice(step.val, 1, canvas.toJSON(["selectable","hoverable","hoverCursor","text","fontStyle","fontWeight","underline"]))
|
||
recordObjs.push(JSON.stringify(objs))
|
||
j = canvas.toJSON(["selectable", "hoverable", "hoverCursor", "text", "fontStyle", "fontWeight", "underline"]);
|
||
j.objects[0].hoverCursor = "default";
|
||
recordJson.push(j);
|
||
}
|
||
function getCoordsMinX(acoords) {
|
||
x = acoords[0].x;
|
||
for (let item of acoords) {
|
||
if (item.x < x) {
|
||
x = item.x
|
||
}
|
||
}
|
||
return x;
|
||
}
|
||
function getCoordsMaxX(acoords) {
|
||
x = acoords[0].x;
|
||
for (let item of acoords) {
|
||
if (item.x > x) {
|
||
x = item.x
|
||
}
|
||
}
|
||
return x;
|
||
|
||
}
|
||
function getCoordsMinY(acoords) {
|
||
y = acoords[0].y;
|
||
for (let item of acoords) {
|
||
if (item.y < y) {
|
||
y = item.y
|
||
}
|
||
}
|
||
return y;
|
||
|
||
}
|
||
function getCoordsMaxY(acoords) {
|
||
y = acoords[0].y;
|
||
for (let item of acoords) {
|
||
if (item.y > y) {
|
||
y = item.y
|
||
}
|
||
}
|
||
return y;
|
||
}
|
||
|
||
$("#text_y").bind('input propertychange', function () {
|
||
if ($("#text_y").val() == "") {
|
||
$("#text_y").val(0)
|
||
}
|
||
let val = background_image.top;
|
||
if ($("#text_y").val() != "") {
|
||
val = background_image.top + parseInt($("#text_y").val());
|
||
}
|
||
canvas.getActiveObject().set("top", val)
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#text_x").bind('input propertychange', function () {
|
||
if ($("#text_x").val() == "") {
|
||
$("#text_x").val(0)
|
||
}
|
||
let val = background_image.left;
|
||
if ($("#text_x").val() != "") {
|
||
val = background_image.left + parseInt($("#text_x").val());
|
||
}
|
||
canvas.getActiveObject().set("left", val)
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#text_w").bind('input propertychange', function () {
|
||
let val = "0";
|
||
if ($("#text_w").val() != "") {
|
||
val = $("#text_w").val();
|
||
}
|
||
let type = objs[getIndex(canvas.getActiveObject()) - 1].type;
|
||
if (type == 3 || type == 4) {
|
||
canvas.getActiveObject().set("width", parseInt(val))
|
||
} else {
|
||
canvas.getActiveObject().set("scaleX", parseInt(val) / canvas.getActiveObject().get("width"))
|
||
}
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#text_h").bind('input propertychange', function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if (objs[idx - 1].type == 7) {
|
||
if ($("#text_h").val() == "") {
|
||
$("#text_h").val(canvas.getActiveObject().get("strokeWidth"));
|
||
}
|
||
canvas.getActiveObject().set("strokeWidth", parseInt($("#text_h").val()));
|
||
canvas.renderAll();
|
||
return;
|
||
}
|
||
let val = "0";
|
||
if ($("#text_h").val() != "") {
|
||
val = $("#text_h").val();
|
||
}
|
||
let type = objs[getIndex(canvas.getActiveObject()) - 1].type;
|
||
if (type == 3 || type == 4) {
|
||
canvas.getActiveObject().set("height", parseInt(val))
|
||
} else {
|
||
canvas.getActiveObject().set("scaleY", parseInt(val) / canvas.getActiveObject().get("height"))
|
||
}
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#text_r").bind('input propertychange', function () {
|
||
|
||
if ($("#text_r").val() == "") {
|
||
$("#text_r").val("0")
|
||
}
|
||
$("#text_r").val(parseInt($("#text_r").val()) % 360)
|
||
//canvas.getActiveObject().set("rotate", val)
|
||
canvas.getActiveObject().rotate(parseInt($("#text_r").val()))
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#out_pic_field_name").bind('input propertychange', function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
objs[idx - 1].name = $("#out_pic_field_name").val();
|
||
updateList();
|
||
recordState();
|
||
})
|
||
|
||
$("#text_black").click(function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if ($(this).prop("checked")) {
|
||
objs[idx - 1].black = true;
|
||
} else {
|
||
objs[idx - 1].black = false;
|
||
}
|
||
recordState();
|
||
});
|
||
$("#out_text_field_name").bind('input propertychange', function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
objs[idx - 1].name = $("#out_text_field_name").val();
|
||
updateList();
|
||
recordState();
|
||
})
|
||
$("#qrcode_field_name").bind('input propertychange', function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
objs[idx - 1].name = $("#qrcode_field_name").val();
|
||
updateList();
|
||
recordState();
|
||
})
|
||
$("#qrcode_color").bind('input propertychange', function () {
|
||
let item = canvas.getActiveObject();
|
||
let qr = jrQrcode.getQrBase64($("#qrcode_val").val(), { padding: 0, foreground: $(this).val() });
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].color = $(this).val();
|
||
item.setSrc(qr, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
});
|
||
$("#qrcode_val").bind('change', function () {
|
||
let val = $(this).val() ? $(this).val() : 'https://www.cardsoon.com'
|
||
let item = canvas.getActiveObject();
|
||
let qr = jrQrcode.getQrBase64(val, { padding: 0, foreground: $("#qrcode_color").val() });
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].val = val;
|
||
item.setSrc(qr, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
});
|
||
$("#barcode_color").bind('input propertychange', function () {
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].color = $(this).val();
|
||
JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font });
|
||
let barcode = document.getElementById('barcode');
|
||
let bar = barcode.toDataURL("image/png");
|
||
item.setSrc(bar, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
});
|
||
$("#barcode_field_name").bind('input propertychange', function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
objs[idx - 1].name = $("#barcode_field_name").val();
|
||
updateList();
|
||
recordState();
|
||
})
|
||
$("#text_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("fill", $("#text_color").val());
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#text_back_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("textBackgroundColor", $("#text_back_color").val());
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#text_size").bind('input propertychange', function () {
|
||
let val = 1
|
||
if (parseFloat($("#text_size").val())) {
|
||
val = parseFloat($("#text_size").val())
|
||
if (val < 1) {
|
||
val = 1
|
||
} else if (val > dpi) {
|
||
val = dpi
|
||
} else if (val%0.5!==0) {
|
||
val = Math.round(val*2)/2
|
||
}
|
||
|
||
}
|
||
$("#text_size").val(val)
|
||
canvas.getActiveObject().set("fontSize", val*dpi/72);
|
||
$("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0));
|
||
$("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0));
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#circle_text_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("fill", $("#circle_text_color").val());
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#circle_text_back_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("textBackgroundColor", $("#circle_text_back_color").val());
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#circle_text_text").bind('input propertychange', function () {
|
||
let val = $("#circle_text_text").val().trim()
|
||
canvas.getActiveObject().set("text", ` ${val} `);
|
||
canvas.renderAll();
|
||
updateList();
|
||
recordState();
|
||
})
|
||
$("#out_text_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("fill", $("#out_text_color").val());
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#out_text_back_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("textBackgroundColor", $("#out_text_back_color").val());
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#out_text_size").bind('input propertychange', function () {
|
||
let val = 1
|
||
if (parseFloat($("#out_text_size").val())) {
|
||
val = parseFloat($("#out_text_size").val())
|
||
if (val < 1) {
|
||
val = 1
|
||
} else if (val > dpi) {
|
||
val = dpi
|
||
} else if (val%0.5!==0) {
|
||
val = Math.round(val*2)/2
|
||
}
|
||
|
||
}
|
||
$("#out_text_size").val(val)
|
||
canvas.getActiveObject().set("fontSize", val*dpi/72);
|
||
$("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0));
|
||
$("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0));
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
// 监听合成文本输入框 (占位符)
|
||
$("#out_text_text").on('input propertychange', function () {
|
||
let val = $(this).val();
|
||
|
||
// 【核心修改】如果值为空,强制给 2 个空格
|
||
// 这样宽度足够宽,容易点击选中
|
||
if (val === "") {
|
||
val = " ";
|
||
}
|
||
|
||
let obj = canvas.getActiveObject();
|
||
if (obj) {
|
||
obj.set("text", val);
|
||
obj.setCoords();
|
||
canvas.requestRenderAll();
|
||
updateList();
|
||
recordState();
|
||
}
|
||
});
|
||
$("#rect_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("fill", $("#rect_color").val());
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#rect_stroke").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("stroke", $("#rect_stroke").val());
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#rect_stroke_width").bind('input propertychange', function () {
|
||
if ($("#rect_stroke_width").val() == "") {
|
||
$("#rect_stroke_width").val("0")
|
||
} else {
|
||
$("#rect_stroke_width").val(parseInt($("#rect_stroke_width").val()))
|
||
}
|
||
canvas.getActiveObject().set("strokeWidth", parseInt($("#rect_stroke_width").val()));
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#rect_radius").bind('input propertychange', function () {
|
||
if ($("#rect_radius").val() == "") {
|
||
$("#rect_radius").val("0")
|
||
} else {
|
||
$("#rect_radius").val(parseInt($("#rect_radius").val()))
|
||
}
|
||
canvas.getActiveObject().set("rx", parseInt($("#rect_radius").val()));
|
||
canvas.getActiveObject().set("ry", parseInt($("#rect_radius").val()));
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#circle_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("fill", $("#circle_color").val());
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#circle_stroke").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("stroke", $("#circle_stroke").val());
|
||
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#circle_stroke_width").bind('input propertychange', function () {
|
||
if ($("#circle_stroke_width").val() == "") {
|
||
$("#circle_stroke_width").val("0")
|
||
} else {
|
||
$(this).val(parseInt($(this).val()))
|
||
}
|
||
canvas.getActiveObject().set("strokeWidth", parseInt($("#circle_stroke_width").val()));
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#counter_start").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("text", $("#counter_start").val());
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].start = $(this).val();
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#counter_add").bind('input propertychange', function () {
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].add = $(this).val();
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#counter_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("fill", $("#counter_color").val());
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#count_size").bind('input propertychange', function () {
|
||
let val = 1
|
||
if (parseFloat($("#count_size").val())) {
|
||
val = parseFloat($("#count_size").val())
|
||
if (val < 1) {
|
||
val = 1
|
||
} else if (val > dpi) {
|
||
val = dpi
|
||
} else if (val%0.5!==0) {
|
||
val = Math.round(val*2)/2
|
||
}
|
||
|
||
}
|
||
$("#count_size").val(val)
|
||
canvas.getActiveObject().set("fontSize", val*dpi/72);
|
||
$("#text_h").val((canvas.getActiveObject().get("height")).toFixed(0));
|
||
$("#text_w").val((canvas.getActiveObject().get("width")).toFixed(0));
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#line_color").bind('input propertychange', function () {
|
||
canvas.getActiveObject().set("stroke", $("#line_color").val());
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
$("#line_dist").bind('input propertychange', function () {
|
||
if ($("#line_dist").val() == "") {
|
||
$("#line_dist").val(0)
|
||
}
|
||
canvas.getActiveObject().set("strokeDashArray", [parseInt($("#line_dist").val()), parseInt($("#line_dist").val())])
|
||
canvas.renderAll();
|
||
recordState();
|
||
})
|
||
// 监听普通文本输入 (占位符)
|
||
$("#text_text").on('input propertychange', function () {
|
||
// 1. 获取输入框的值,不要用 trim(),否则无法输入空格
|
||
let val = $(this).val();
|
||
|
||
// 2. 核心修改:只有当删光时,才给 4 个空格作为占位符
|
||
if (val === "") {
|
||
val = " "; // 4个空格,比原来的2个更宽,更好点
|
||
}
|
||
// 3. 更新对象
|
||
// 注意:这里直接用 val,不再用 ` ${val} `,这样有文字时就不会强制加空格了
|
||
canvas.getActiveObject().set("text", val);
|
||
canvas.requestRenderAll(); // 使用 requestRenderAll 性能更好
|
||
updateList();
|
||
recordState();
|
||
});
|
||
$("#barcode_val").bind('input propertychange', function () {
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].val = $(this).val();
|
||
JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font });
|
||
|
||
let barcode = document.getElementById('barcode');
|
||
let bar = barcode.toDataURL("image/png");
|
||
item.setSrc(bar, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
})
|
||
$("#barcode_show").click(function () {
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
let val = $("#barcode_size").val()
|
||
if ($(this).prop("checked")) {
|
||
objs[idx - 1].show = true;
|
||
val = 0
|
||
} else {
|
||
objs[idx - 1].show = false;
|
||
}
|
||
JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: val*dpi/72, font: objs[idx - 1].font });
|
||
let barcode = document.getElementById('barcode');
|
||
let bar = barcode.toDataURL("image/png");
|
||
item.setSrc(bar, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
});
|
||
$("#barcode_size").bind('input propertychange', function () {
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(item);
|
||
let val = 1
|
||
if (parseFloat($(this).val())) {
|
||
val = parseFloat($(this).val())
|
||
if (val < 1) {
|
||
val = 1
|
||
} else if (val > dpi) {
|
||
val = dpi
|
||
} else if (val%0.5!==0) {
|
||
val = Math.round(val*2)/2
|
||
}
|
||
|
||
}
|
||
$("#barcode_size").val(val)
|
||
objs[idx - 1].fontSize = val*dpi/72;
|
||
JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font });
|
||
|
||
let barcode = document.getElementById('barcode');
|
||
let bar = barcode.toDataURL("image/png");
|
||
item.setSrc(bar, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
})
|
||
$('#count_font_family').on('change', function () {
|
||
canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text())
|
||
canvas.renderAll()
|
||
recordState();
|
||
});
|
||
$('#text_font_family').on('change', function () {
|
||
canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text())
|
||
canvas.renderAll()
|
||
recordState();
|
||
});
|
||
|
||
$('#circle_text_font_family').on('change', function () {
|
||
canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text())
|
||
canvas.renderAll()
|
||
recordState();
|
||
});
|
||
|
||
$('#language_select').on('change', function () {//语言选择
|
||
langua_ge($(this).find('option:selected').val());
|
||
s_lan = $(this).find('option:selected').val();
|
||
localStorage.setItem("lang", s_lan);
|
||
});
|
||
$('#barcode_font_family').on('change', function () {
|
||
let item = canvas.getActiveObject();
|
||
let idx = getIndex(item);
|
||
objs[idx - 1].font = $(this).find('option:selected').text();
|
||
JsBarcode("#barcode", objs[idx - 1].val, { margin: 0, lineColor: objs[idx - 1].color, fontSize: objs[idx - 1].fontSize, font: objs[idx - 1].font });
|
||
|
||
let barcode = document.getElementById('barcode');
|
||
let bar = barcode.toDataURL("image/png");
|
||
item.setSrc(bar, function (img) {
|
||
canvas.renderAll();
|
||
recordState();
|
||
});
|
||
//recordState();
|
||
});
|
||
$('#out_text_font_family').on('change', function () {
|
||
canvas.getActiveObject().set("fontFamily", $(this).find('option:selected').text())
|
||
canvas.renderAll()
|
||
recordState();
|
||
});
|
||
$(".obj_list").on("click", "div", function () {
|
||
let idx = objs.length - 1 - $(this).index();
|
||
selectObj(idx);
|
||
});
|
||
$("#exceed").click(function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if ($(this).prop("checked")) {
|
||
objs[idx - 1].exceed = true;
|
||
} else {
|
||
objs[idx - 1].exceed = false;
|
||
}
|
||
recordState();
|
||
});
|
||
$("#autoWrap").click(function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if ($(this).prop("checked")) {
|
||
|
||
objs[idx - 1].autoWrap = true;
|
||
} else {
|
||
objs[idx - 1].autoWrap = false;
|
||
}
|
||
recordState();
|
||
});
|
||
$("#fixSize").click(function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if ($(this).prop("checked")) {
|
||
|
||
objs[idx - 1].fixSize = true;
|
||
} else {
|
||
objs[idx - 1].fixSize = false;
|
||
}
|
||
recordState();
|
||
});
|
||
$("#circle_text_center").click(function () {
|
||
let idx = getIndex(canvas.getActiveObject());
|
||
if ($(this).prop("checked")) {
|
||
objs[idx - 1].circleCenter = 1;
|
||
} else {
|
||
objs[idx - 1].circleCenter = 0;
|
||
}
|
||
recordState();
|
||
});
|
||
$("#delete").click(function () {
|
||
let actObjs = canvas.getActiveObjects();
|
||
let allObjs = canvas.getObjects();
|
||
let flag = 0;
|
||
for (let item of actObjs) {
|
||
if (item != allObjs[0]) {
|
||
let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1
|
||
objs.splice(i - 1, 1);
|
||
canvas.remove(item);
|
||
flag = 1;
|
||
|
||
}
|
||
}
|
||
updateList();
|
||
canvas.discardActiveObject();
|
||
if (flag == 1) {
|
||
recordState();
|
||
canvas.renderAll();
|
||
}
|
||
// let actObjs = canvas.getActiveObjects();
|
||
// let allObjs = canvas.getObjects();
|
||
// let flag = 0;
|
||
// for( let item of actObjs){
|
||
// if ( item != allObjs[0]){
|
||
// let i = getIndex(item);//0是背景,所以从1开始,但objs不包含背景图片,故要-1
|
||
// objs.splice(i-1,1);
|
||
// canvas.remove(item);
|
||
// flag = 1;
|
||
// updateList();
|
||
// }
|
||
// }
|
||
// selectObj(-1);
|
||
// if(flag == 1){
|
||
// recordState();
|
||
// }
|
||
});
|
||
|
||
//在关于我们页面,获取版本号。
|
||
// 注意:function 前面加了 async 关键字
|
||
$("#about").click(async function () {
|
||
// 1. 先异步获取版本号
|
||
let version = "0.0.0"; // 默认值,防止获取失败
|
||
try {
|
||
if (window.sysAPI && window.sysAPI.getAppVersion) {
|
||
const v = await window.sysAPI.getAppVersion();
|
||
version = "v" + v; // 拼接一个 v,变成 v2.3.017
|
||
}
|
||
} catch (e) {
|
||
console.error("获取版本号失败", e);
|
||
}
|
||
|
||
// 2. 获取成功后再弹出窗口
|
||
layer.open({
|
||
type: 1
|
||
, title: language_str("about")
|
||
, area: '450px;'
|
||
, id: 'LAY_layuipro'
|
||
, moveType: 1
|
||
, content: '<div style="padding-top:20px;padding-bottom:30px;background-color: #32363A; color: #fff; font-weight: 300;text-align:center;">' +
|
||
'<div style="width: 120px;margin: 0 auto;"><img style="width: 120px;" src="./public/images/IconA.png"></div>' +
|
||
'<div style="font-size:24px;">Soon Design</div>' +
|
||
// 【修改点】这里使用了刚才获取到的 version 变量
|
||
'<div style="font-size:14px;">' + language_str("vers") + ' ' + version + '</div>' +
|
||
'<div style="font-size:14px;">' + language_str("copyright") + '</div>' +
|
||
'</div>'
|
||
});
|
||
})
|
||
$("#help").click(() => {
|
||
ipcRenderer.send('open-help-file');
|
||
});
|
||
|
||
|
||
// ===========================================================
|
||
// 对象选中处理
|
||
// ===========================================================
|
||
function handleObjectSelected() {
|
||
let select_obj = canvas.getActiveObject();
|
||
|
||
// 1. 未选中任何对象
|
||
if (!select_obj) {
|
||
$("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide();
|
||
$("#component_type").text(language_str("bg"));
|
||
selectObj(-1, true); // 传 true,只更新UI
|
||
return;
|
||
}
|
||
|
||
// 2. 获取索引
|
||
let i = getIndex(select_obj);
|
||
|
||
if (i != 0) {
|
||
// --- 选中了普通对象 ---
|
||
--i; // 转换为 objs 数组下标
|
||
|
||
if(objs[i]) {
|
||
switch (objs[i].type) {
|
||
case 1: // 图片
|
||
$("#component_type").text(language_str("img"));
|
||
selectObject(select_obj, i); selectPic(select_obj, i); break;
|
||
case 2: // 合成图片
|
||
$("#component_type").text(language_str("simg"));
|
||
selectObject(select_obj, i); selectOutPic(select_obj, i); break;
|
||
case 3: // 文本
|
||
$("#component_type").text(language_str("text"));
|
||
selectObject(select_obj, i); selectText(select_obj, i); break;
|
||
case 4: // 合成文本
|
||
$("#component_type").text(language_str("stext"));
|
||
selectObject(select_obj, i); selectOutText(select_obj, i); break;
|
||
case 5: // 矩形
|
||
$("#component_type").text(language_str("rect"));
|
||
selectObject(select_obj, i); selectRect(select_obj, i); break;
|
||
case 6: // 圆形
|
||
$("#component_type").text(language_str("circ"));
|
||
selectObject(select_obj, i); selectCircle(select_obj, i); break;
|
||
case 7: // 直线
|
||
$("#component_type").text(language_str("line"));
|
||
selectObject(select_obj, i); selectLine(select_obj, i); break;
|
||
case 8: // 二维码
|
||
$("#component_type").text(language_str("qrc"));
|
||
selectObject(select_obj, i); selectQrCode(select_obj, i); break;
|
||
case 9: // 条形码
|
||
$("#component_type").text(language_str("barc"));
|
||
selectObject(select_obj, i); selectBarCode(select_obj, i); break;
|
||
case 10: // 计数器
|
||
$("#component_type").text(language_str("counter"));
|
||
selectObject(select_obj, i); selectCounter(select_obj, i); break;
|
||
case 11: // 圆形文本
|
||
$("#component_type").text(language_str("ctext"));
|
||
selectObject(select_obj, i); selectCircleText(select_obj, i); break;
|
||
}
|
||
}
|
||
|
||
// 【关键】这里传入 true!
|
||
// 意思是:因为我已经是在画布上选中它了,selectObj 函数只负责把左边的条目变灰,不要再回头去 setActiveObject 了
|
||
selectObj(i, true);
|
||
|
||
} else {
|
||
// --- 选中了背景 ---
|
||
$("#base_control, #line_control, #pic_control, #out_pic_control, #text_control, #circle_text_control, #out_text_control, #rect_control, #circle_control, #counter_control, #qrcode_Controll, #barcode_controll").hide();
|
||
selectObj(-1, true);
|
||
$("#component_type").text(language_str("bg"));
|
||
}
|
||
}
|
||
|
||
// ===========================================================
|
||
// 统一事件监听 (替代原有的 canvas1.on 和 canvas2.on)
|
||
// ===========================================================
|
||
// 提取对象移动逻辑 (供正反面复用)
|
||
function handleObjectMoving(e) {
|
||
let obj = e.target;
|
||
let idx = getIndex(obj);
|
||
// 圆形文本特殊处理
|
||
if (idx > 0 && idx <= objs.length && objs[idx - 1] && objs[idx - 1].type === 11 && $("#circle_text_center").prop("checked")) {
|
||
let pointer = { x: obj.left, y: obj.top };
|
||
let distance = getDisdance(pointer.x, pointer.y, canvas.width / 2, canvas.height / 2);
|
||
let angleDeg = getDeg(pointer);
|
||
let flipped = pointer.y > canvas.height / 2 ? true : false;
|
||
|
||
if(typeof circle_text_diameter !== 'undefined') circle_text_diameter.setValue(distance * 2 - 500);
|
||
obj.set("diameter", distance * 2);
|
||
obj.set("angle", angleDeg);
|
||
obj.set("flipped", flipped);
|
||
}
|
||
updateControls();
|
||
}
|
||
|
||
// 启动监听
|
||
// ===========================================================
|
||
// 统一事件绑定 (已集成边界检测)
|
||
// ===========================================================
|
||
// ===========================================================
|
||
// 3. 统一事件绑定 (修复:使用 Global Composite Operation 实现完美遮罩)
|
||
// ===========================================================
|
||
function initCanvasEvents() {
|
||
[canvas1, canvas2].forEach(currentCanvas => {
|
||
|
||
// 1. 鼠标移动
|
||
currentCanvas.on("mouse:move", (e) => {
|
||
let offsetX = 0, offsetY = 0;
|
||
if (currentCanvas === canvas2 && typeof background_image !== 'undefined') {
|
||
offsetX = background_image.left;
|
||
offsetY = background_image.top;
|
||
}
|
||
if(e.pointer) {
|
||
$("#posText").text("X: " + (e.pointer.x - offsetX).toFixed(0) + " Y: " + (e.pointer.y - offsetY).toFixed(0));
|
||
}
|
||
updateRulerGuides(e.e);
|
||
});
|
||
|
||
// 2. 鼠标移出
|
||
currentCanvas.on("mouse:out", () => {
|
||
$("#ruler-guide-h").hide(); $("#ruler-guide-v").hide();
|
||
});
|
||
|
||
// 3. 选中处理
|
||
currentCanvas.on('mouse:down', handleObjectSelected);
|
||
|
||
// 4. 鼠标松开 (添加对象)
|
||
currentCanvas.on("mouse:up", (e) => {
|
||
if (addState === 0) return;
|
||
const ptr = e.pointer;
|
||
switch (addState) {
|
||
case 1: addPic(ptr); break;
|
||
case 2: addOutPic(ptr); break;
|
||
case 3: addText(ptr); break;
|
||
case 4: addOutText(ptr); break;
|
||
case 5: addRect(ptr); break;
|
||
case 6: addCircle(ptr); break;
|
||
case 7: addLine(ptr); break;
|
||
case 8: addQrCode(ptr); break;
|
||
case 9: addBarCode(ptr); break;
|
||
case 10: addCounter(ptr); break;
|
||
case 11: addCircleText(ptr); break;
|
||
}
|
||
addState = 0;
|
||
if(typeof background_image !== 'undefined') background_image.hoverCursor = "default";
|
||
currentCanvas.renderAll();
|
||
$("#addPic, #addOutPic, #addText, #addOutText, #addRect, #addCircle, #addLine, #addQrCode, #addBarCode, #addCounter, #addCircleText").css("background-color", "");
|
||
});
|
||
|
||
// 5. 对象移动 (只保留圆形文本逻辑,去掉了 checkOutOfBounds)
|
||
currentCanvas.on("object:moving", (e) => {
|
||
handleObjectMoving(e);
|
||
});
|
||
|
||
// 6. 变换事件
|
||
currentCanvas.on("object:rotating", updateControls);
|
||
currentCanvas.on("object:scaling", updateControls);
|
||
currentCanvas.on("object:rotated", () => { recordState(); });
|
||
currentCanvas.on('text:editing:entered', () => { _textEdit = true; });
|
||
currentCanvas.on('text:editing:exited', () => { _textEdit = false; });
|
||
currentCanvas.on("text:changed", (e) => { $("#text_text").val(e.target.get("text")); });
|
||
|
||
// 7. 对象修改后
|
||
currentCanvas.on('object:modified', function (event) {
|
||
if (currentCanvas.getActiveObjects().length > 1) return;
|
||
let idx = getIndex(event.target);
|
||
if(idx <= 0) return;
|
||
let objData = objs[idx - 1];
|
||
let target = event.target;
|
||
|
||
if ([3, 4, 10].includes(objData.type)) {
|
||
target.fontSize = (target.fontSize * target.scaleX).toFixed(0);
|
||
target.scaleX = 1; target.scaleY = 1;
|
||
target._clearCache();
|
||
if(objData.type == 3) $("#text_size").val(target.fontSize);
|
||
if(objData.type == 4) $("#out_text_size").val(target.fontSize);
|
||
if(objData.type == 10) $("#count_size").val(target.fontSize);
|
||
currentCanvas.renderAll();
|
||
updateControls();
|
||
} else if (objData.type == 5) {
|
||
target.width *= target.scaleX; target.height *= target.scaleY;
|
||
target.scaleX = 1; target.scaleY = 1;
|
||
updateControls();
|
||
}
|
||
recordState();
|
||
});
|
||
// ==================================================
|
||
// 8. 【完美修复版】渲染后绘制:外部蒙版 + 中心圆孔 (修复三角形Bug)
|
||
// ==================================================
|
||
currentCanvas.on('after:render', function () {
|
||
let bgObj = (currentCanvas === canvas1) ? background_image1 : background_image2;
|
||
|
||
if (bgObj) {
|
||
const ctx = currentCanvas.getContext();
|
||
const width = currentCanvas.width;
|
||
const height = currentCanvas.height;
|
||
|
||
// 1. 计算圆心
|
||
const cx = bgObj.left + (bgObj.width * bgObj.scaleX) / 2;
|
||
const cy = bgObj.top + (bgObj.height * bgObj.scaleY) / 2;
|
||
|
||
// 2. 计算半径
|
||
// 外半径 (光盘大小)
|
||
const r_outer = (bgObj.width * bgObj.scaleX) / 2;
|
||
|
||
// 内半径 (中心孔)
|
||
const dpi = 600;
|
||
const mmToPx = dpi / 25.4;
|
||
let holeDiameterMm = 24; // 默认 15mm
|
||
|
||
// 切换版本判断 (15mm vs 38mm)
|
||
if (currentCanvas === canvas1 && typeof bg_version !== 'undefined' && bg_version === 2) {
|
||
holeDiameterMm = 42;
|
||
}
|
||
|
||
// 比例计算法:确保孔径随缩放适配
|
||
// r_inner = r_outer * (孔径 / 光盘标准直径120mm)
|
||
const r_inner = r_outer * (holeDiameterMm / 120);
|
||
|
||
ctx.save();
|
||
ctx.beginPath();
|
||
|
||
// A. 绘制全屏矩形 (顺时针)
|
||
ctx.rect(0, 0, width, height);
|
||
|
||
// B. 挖掉外圆 (逆时针)
|
||
// 【关键修复】画圆前,必须把笔移动到圆的起点 (cx + r, cy)
|
||
// 否则 Canvas 会画一条线连过来,形成奇怪的三角形
|
||
ctx.moveTo(cx + r_outer, cy);
|
||
ctx.arc(cx, cy, r_outer, 0, Math.PI * 2, true);
|
||
|
||
// C. 填补内圆 (顺时针)
|
||
// 【关键修复】同理,把笔移动到内圆的起点
|
||
ctx.moveTo(cx + r_inner, cy);
|
||
ctx.arc(cx, cy, r_inner, 0, Math.PI * 2, false);
|
||
|
||
ctx.closePath();
|
||
ctx.fillStyle = "rgba(0, 0, 0, 0.9)"; // 90% 遮罩
|
||
ctx.fill();
|
||
ctx.restore();
|
||
}
|
||
});
|
||
});
|
||
}
|
||
// 立即启动
|
||
initCanvasEvents();
|
||
// ===========================================================
|
||
// Slider 滑块初始化 (保持原样)
|
||
// ===========================================================
|
||
var circle_text_size = slider.render({
|
||
elem: '#circle_text_size',
|
||
min: 10, max: 120,
|
||
change: function (value) {
|
||
canvas.getActiveObject().set("fontSize", value);
|
||
canvas.renderAll();
|
||
}
|
||
});
|
||
var circle_text_diameter = slider.render({
|
||
elem: '#circle_text_diameter',
|
||
min: 500, max: 4000,
|
||
change: function (value) {
|
||
canvas.getActiveObject().set("diameter", value);
|
||
canvas.renderAll();
|
||
}
|
||
});
|
||
var out_pic_op = slider.render({
|
||
elem: '#out_pic_op',
|
||
change: function (value) {
|
||
canvas.getActiveObject().set('opacity', (100 - value) / 100);
|
||
canvas.renderAll();
|
||
}
|
||
});
|
||
var pic_op = slider.render({
|
||
elem: '#pic_op',
|
||
change: function (value) {
|
||
canvas.getActiveObject().set("opacity", (100 - value) / 100);
|
||
canvas.renderAll();
|
||
}
|
||
});
|
||
var rect_op = slider.render({
|
||
elem: '#rect_op',
|
||
change: function (value) {
|
||
canvas.getActiveObject().set("opacity", (100 - value) / 100);
|
||
canvas.renderAll();
|
||
}
|
||
});
|
||
var circle_op = slider.render({
|
||
elem: '#circle_op',
|
||
change: function (value) {
|
||
canvas.getActiveObject().set("opacity", (100 - value) / 100);
|
||
canvas.renderAll();
|
||
}
|
||
});
|
||
// ===========================================================
|
||
// 3. 标尺功能 (0点复位 + 拖拽辅助线 + 透明度)
|
||
// ===========================================================
|
||
function initRulers() {
|
||
const dpi = 600;
|
||
const mmToPx = dpi / 25.4;
|
||
const rulerHeight = 20;
|
||
const rulerWidth = 20;
|
||
|
||
const canvasWrapper = $('.canvas-wrapper');
|
||
const canvasBox = $('.canvas_box');
|
||
|
||
// 确保容器定位
|
||
if(canvasWrapper.css('position') === 'static') canvasWrapper.css('position', 'relative');
|
||
|
||
// 初始化尺寸
|
||
let canvasWidth = canvasWrapper.width() || 800;
|
||
let canvasHeight = canvasWrapper.height() || 600;
|
||
|
||
const $rulerH = $('#ruler-h');
|
||
const $rulerV = $('#ruler-v');
|
||
|
||
$rulerH.attr('width', canvasWidth).attr('height', rulerHeight);
|
||
$rulerV.attr('width', rulerWidth).attr('height', canvasHeight);
|
||
|
||
// --- 1. 绑定拖拽事件 (核心新功能) ---
|
||
// 定义临时拖拽线 DOM
|
||
let $dragLine = null;
|
||
|
||
// 通用拖拽开始函数
|
||
const startDragGuide = (type, e) => {
|
||
e.preventDefault();
|
||
e.stopPropagation();
|
||
|
||
// 创建临时显示的线
|
||
$dragLine = $('<div class="guide-line-drag"></div>');
|
||
$('.canvas-wrapper').append($dragLine);
|
||
|
||
if (type === 'horizontal') {
|
||
// 从上往下拖 (水平线)
|
||
$dragLine.css({
|
||
left: 0, width: '100%', height: '1px', top: e.offsetY
|
||
});
|
||
} else {
|
||
// 从左往右拖 (垂直线)
|
||
$dragLine.css({
|
||
top: 0, height: '100%', width: '1px', left: e.offsetX
|
||
});
|
||
}
|
||
|
||
// 绑定 document 移动事件
|
||
$(document).on('mousemove.ruler', function(moveEvent) {
|
||
let wrapperOffset = canvasWrapper.offset();
|
||
if (type === 'horizontal') {
|
||
let relY = moveEvent.pageY - wrapperOffset.top;
|
||
$dragLine.css('top', relY + 'px');
|
||
} else {
|
||
let relX = moveEvent.pageX - wrapperOffset.left;
|
||
$dragLine.css('left', relX + 'px');
|
||
}
|
||
});
|
||
|
||
// 绑定松开事件 (创建真实的 Fabric 线)
|
||
$(document).on('mouseup.ruler', function(upEvent) {
|
||
$(document).off('mousemove.ruler mouseup.ruler');
|
||
|
||
if (!$dragLine) return;
|
||
|
||
// 获取最终位置
|
||
let wrapperOffset = canvasWrapper.offset();
|
||
let finalX = upEvent.pageX - wrapperOffset.left;
|
||
let finalY = upEvent.pageY - wrapperOffset.top;
|
||
|
||
// 移除临时线
|
||
$dragLine.remove();
|
||
$dragLine = null;
|
||
|
||
// 只有拖入画布区域才创建
|
||
if (finalX > rulerWidth && finalY > rulerHeight) {
|
||
createFabricGuide(type, finalX, finalY);
|
||
}
|
||
});
|
||
};
|
||
|
||
// 绑定到标尺 DOM
|
||
$rulerH.off('mousedown').on('mousedown', (e) => startDragGuide('horizontal', e));
|
||
$rulerV.off('mousedown').on('mousedown', (e) => startDragGuide('vertical', e));
|
||
|
||
// --- 2. 在画布中创建辅助线 ---
|
||
function createFabricGuide(type, domX, domY) {
|
||
// 计算画布内的逻辑坐标 (减去 margin 偏移,除以缩放)
|
||
// 注意:这里我们重新回到“原点在画布0,0”的逻辑
|
||
// canvasBox.offset() 是画布容器的绝对位置
|
||
let boxOffset = canvasBox.offset();
|
||
let wrapperOffset = canvasWrapper.offset();
|
||
|
||
// 计算相对于 canvasBox 的像素位置
|
||
let relX = domX - (boxOffset.left - wrapperOffset.left);
|
||
let relY = domY - (boxOffset.top - wrapperOffset.top);
|
||
|
||
// 转为 Fabric 坐标 (除以 zoom)
|
||
let canvasX = relX / zoom;
|
||
let canvasY = relY / zoom;
|
||
|
||
// 构造线对象
|
||
let linePoints = [];
|
||
if (type === 'horizontal') {
|
||
// 水平线:贯穿整个画布宽度
|
||
// 为了让线足够长,我们设一个很大的值,或者设为 canvas.width
|
||
linePoints = [-5000, canvasY, 5000, canvasY];
|
||
} else {
|
||
// 垂直线
|
||
linePoints = [canvasX, -5000, canvasX, 5000];
|
||
}
|
||
|
||
let guideLine = new fabric.Line(linePoints, {
|
||
stroke: '#00FFFF', // 青色高亮
|
||
strokeWidth: 1 / zoom, // 线条粗细随缩放调整,保持视觉一致
|
||
strokeDashArray: [5, 5], // 虚线
|
||
selectable: true, // 允许选中移动
|
||
evented: true,
|
||
hasControls: false, // 没有缩放控制点
|
||
hasBorders: false,
|
||
lockRotation: true, // 锁定旋转
|
||
lockScalingX: true,
|
||
lockScalingY: true,
|
||
hoverCursor: type === 'horizontal' ? 'ns-resize' : 'ew-resize',
|
||
// 自定义属性标记
|
||
isGuideLine: true,
|
||
ignoreSave: true // 保存时可以根据这个标记过滤掉
|
||
});
|
||
|
||
// 限制移动方向
|
||
guideLine.on('moving', function(e) {
|
||
if (type === 'horizontal') {
|
||
this.left = -5000; // 锁定 X 轴不许动
|
||
} else {
|
||
this.top = -5000; // 锁定 Y 轴不许动
|
||
}
|
||
});
|
||
|
||
canvas.add(guideLine);
|
||
canvas.setActiveObject(guideLine);
|
||
canvas.renderAll();
|
||
}
|
||
|
||
|
||
// --- 3. 绘制标尺 (核心绘制循环) ---
|
||
function updateAndDraw() {
|
||
const pxPerMm = zoom * mmToPx;
|
||
|
||
// 【修改点】原点复位逻辑
|
||
// 现在原点就是 Canvas 的 (0,0) 点
|
||
// 加上 canvasBox 的 margin 偏移量,让标尺 0 刻度对齐画布边缘
|
||
let boxMarginLeft = parseFloat(canvasBox.css('margin-left')) || 0;
|
||
let boxMarginTop = parseFloat(canvasBox.css('margin-top')) || 0;
|
||
|
||
let originX = boxMarginLeft;
|
||
let originY = boxMarginTop;
|
||
|
||
const ctxH = document.getElementById('ruler-h').getContext('2d');
|
||
const ctxV = document.getElementById('ruler-v').getContext('2d');
|
||
|
||
const drawAxis = (ctx, isH) => {
|
||
let len = isH ? canvasWidth : canvasHeight;
|
||
ctx.clearRect(0, 0, isH ? len : rulerWidth, isH ? rulerHeight : len);
|
||
|
||
// 背景改为透明 (配合 CSS)
|
||
// ctx.fillStyle = 'rgba(44, 44, 44, 0.7)'; // 也可以在这里画
|
||
// ctx.fillRect(...)
|
||
// 这里我们留空,让 CSS 背景色透出来
|
||
|
||
ctx.strokeStyle = '#999'; // 刻度颜色稍亮一点
|
||
ctx.lineWidth = 1;
|
||
ctx.beginPath();
|
||
|
||
// 绘制底边线
|
||
if(isH) { ctx.moveTo(0, 19); ctx.lineTo(len, 19); }
|
||
else { ctx.moveTo(19, 0); ctx.lineTo(19, len); }
|
||
ctx.stroke();
|
||
|
||
ctx.fillStyle = '#CCC';
|
||
ctx.font = '9px Arial';
|
||
ctx.textAlign = isH ? 'left' : 'center';
|
||
ctx.textBaseline = isH ? 'top' : 'middle';
|
||
ctx.beginPath();
|
||
|
||
// 绘制刻度 (只向正方向绘制)
|
||
// 既然原点复位到0了,我们只需要从0开始画
|
||
for (let mm = 0; ; mm += 1) {
|
||
let pos = (isH ? originX : originY) + (mm * pxPerMm);
|
||
|
||
if (pos > len) break;
|
||
|
||
let isMajor = mm % 10 === 0; // 1cm
|
||
let isMedium = mm % 5 === 0; // 0.5cm
|
||
let tickLen = isMajor ? 15 : (isMedium ? 8 : 4);
|
||
|
||
if(isH) {
|
||
ctx.moveTo(pos, 20 - tickLen); ctx.lineTo(pos, 20);
|
||
if(isMajor) ctx.fillText(mm/10, pos + 2, 2); // 显示 cm 数值
|
||
} else {
|
||
ctx.moveTo(20 - tickLen, pos); ctx.lineTo(20, pos);
|
||
if(isMajor) {
|
||
ctx.save();
|
||
ctx.translate(8, pos + 2);
|
||
ctx.rotate(-Math.PI/2);
|
||
ctx.fillText(mm/10, 0, 0);
|
||
ctx.restore();
|
||
}
|
||
}
|
||
}
|
||
ctx.stroke();
|
||
};
|
||
|
||
drawAxis(ctxH, true);
|
||
drawAxis(ctxV, false);
|
||
}
|
||
|
||
canvas1.on('after:render', updateAndDraw);
|
||
canvas2.on('after:render', updateAndDraw);
|
||
$(window).resize(() => setTimeout(updateAndDraw, 100));
|
||
updateAndDraw();
|
||
}
|
||
|
||
// 辅助函数:更新光标位置
|
||
function updateRulerGuides(nativeEvent) {
|
||
if (!nativeEvent) return;
|
||
const wrapper = $('.canvas-wrapper');
|
||
const offset = wrapper.offset();
|
||
if (!offset) return;
|
||
$("#ruler-guide-h").css({ left: (nativeEvent.pageX - offset.left) + 'px', display: 'block' });
|
||
$("#ruler-guide-v").css({ top: (nativeEvent.pageY - offset.top) + 'px', display: 'block' });
|
||
}
|
||
|
||
|
||
|
||
|
||
})
|
||
}); |