GraphEditor/js/editor.js
2025-08-16 08:37:11 +00:00

498 lines
22 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var fieldcolor = "rgb(0, 0, 0)";
shape = [];
var index = -1;
var legend = {}; // объект с айтемами легенды
var legend_img_margin_left = 5;
var text_height;
var element_ico_size = 16;
var dimension = [];
dimension["naprav"] = [[22, 10], [24, 13.33], [28, 15.56], [32, 17.78], [34, 18.89], [40, 22.22], [46, 25.56], [52, 28.89]];
dimension["petlya"] = [[16, 16], [18, 18], [20, 20], [24, 24], [28, 28], [32, 32], [36, 36], [40, 40]];
dimension["gazlift"] = [[16, 11.08], [18, 12.46], [20, 13.85], [24, 16.62], [28, 19.38], [32, 22.15], [36, 24.92], [40, 27.69]];
dimension["podyomnik"] = [[16, 16], [18, 16.88], [20, 18.75], [24, 22.5], [28, 26.25], [32, 30], [36, 33.75], [40, 37.5]];
dimension["sushka"] = [[16, 13], [18, 14.62], [20, 16.25], [24, 19.5], [28, 22.75], [32, 26], [36, 29.25], [40, 32.5]];
dimension["lotok"] = [[16, 16], [18, 18], [20, 20], [24, 24], [28, 28], [32, 32], [36, 36], [40, 40]];
dimension["vnutr-yaschik"] = [[16, 9], [18, 10.13], [20, 11.25], [26, 14.63], [30, 16.88], [34, 19.13], [38, 21.38], [42, 23.63]];
dimension["butilochnitsa"] = [[12, 18], [13.33,20], [14.67, 22], [17.33, 26], [20, 30], [22.67, 34], [25.33, 38], [28, 42]];
dimension["dampfer"] = [[16, 8], [18, 9], [22, 11], [26, 13], [30, 15], [34, 17], [38, 19], [42, 21]];
dimension["tip-on"] = [[16, 16], [18, 18], [20, 20], [24, 24], [28, 28], [32, 32], [36, 36], [40, 40]];
dimension["zamok"] = [[16, 16], [18, 18], [20, 20], [24, 24], [28, 28], [32, 32], [36, 36], [40, 40]];
dimension["skritiy-krepezh"] = [[18, 14.59], [22, 17.84], [24, 19.46], [30, 24.32], [32, 25.94], [36, 29.19], [44, 35.67], [50, 40.54]];
var text_item_width = 0;
var biggest_legend_item_width;
function changeTextWidth(item){
if(item.width < 10){
if(biggest_legend_item_width > 0 && /legend.*/.test(item.groupName)){
item.width = biggest_legend_item_width - (legend_back.margin * 2 + legend_img_margin_left);
}
else{
item.width = 10;
}
}
canvas.renderAll();
}
var editor_obj = {
add_text: function(e={}, x=canvas.getPointer(e.e).x, y=canvas.getPointer(e.e).y, ang = 0, text = "Выделите и кликните, чтобы ввести текст", group_name="shape_text", flag=false, fill = fieldcolor){
if(group_name != 'legend'){
var font_size = text_dimension[zoom_size];
}
else{
var font_size = 11;
}
let temp_shape;
if(group_name == "shape_text"){
temp_shape = new fabric.Textbox(text, {
selectable: true,
lockMovementX: flag,
lockMovementY: flag,
fontSize: font_size,
fontFamily: "Golos Text",
fill: fill,
backgroundColor: "rgba(0, 0, 0, 0)",
left: x,
top: y,
width: 295,
// height: 150,
angle: ang,
textAlign: 'left',
perPixelTargetFind: flag,
groupName: group_name + index,
index: index
})
}
else{
temp_shape = new fabric.IText(text, {
selectable: true,
lockMovementX: flag,
lockMovementY: flag,
fontSize: font_size,
fontFamily: "Golos Text",
fill: fill,
backgroundColor: "rgba(0, 0, 0, 0)",
left: x,
top: y,
width: 500,
height: 150,
angle: ang,
textAlign: 'center',
perPixelTargetFind: flag,
groupName: group_name + index,
index: index
})
}
temp_shape.parent = temp_shape;
if(group_name != 'legend'){
// canvas.setActiveObject(temp_shape);
}
else{
temp_shape.backgroundColor = legend_back.fill;
}
setTimeout(function(){
changeTextWidth(temp_shape);
}, 100);
temp_shape.on('changed', function () {
changeTextWidth(temp_shape);
});
canvas.add(temp_shape);
return temp_shape;
},
add_rect: function(e, flag=true, x=canvas.getPointer(e.e).x, y=canvas.getPointer(e.e).y, w=0, h=0, color='rgba(0, 0, 0, 0)', stroke=fieldcolor, group_name="shape_rect", ispart=false){
if(group_name == "socket"){
var stroke_width = 1;
}
else{
var stroke_width = zoom_size + 1;
}
let temp_shape = new fabric.Rect({
selectable: flag,
left: x,
top: y,
stroke: stroke,
strokeUniform: true,
strokeWidth: stroke_width,
fill: color,
width: w,
height: h,
hasControls: flag,
perPixelTargetFind: true,
groupName: group_name + index,
index: index
});
temp_shape.parent = temp_shape;
if(!ispart && group_name != "temp"){
if(group_name != "crop"){
canvas.setActiveObject(temp_shape);
}
canvas.add(temp_shape);
}
else{
temp_shape.originX = 'center';
temp_shape.originY = 'center';
}
return temp_shape;
},
add_circle: function(e, flag=true, x=canvas.getPointer(e.e).x, y=canvas.getPointer(e.e).y, r=1, color='rgba(0, 0, 0, 0)', stroke=fieldcolor, group_name="shape_circle", ispart=false, objects=undefined){
let temp_shape = new fabric.Circle({
selectable: flag,
left: x,
top: y,
radius: r,
stroke: stroke,
strokeWidth: zoom_size + 1,
strokeUniform: true,
fill: color,
objects: objects,
perPixelTargetFind: true,
groupName: group_name + index,
index: index
});
temp_shape.parent = temp_shape;
if(!ispart){
canvas.setActiveObject(temp_shape);
canvas.add(temp_shape);
}
else{
temp_shape.originX = 'center';
temp_shape.originY = 'center';
}
return temp_shape;
},
add_line: add_line,
add_size: add_size,
add_geometry: add_geometry,
add_cap: add_cap,
add_socket: add_socket,
add_arrow: add_arrow,
add_selection: function(){
element_cursor();
canvas.isDrawingMode = 0;
},
add_image: function(img, not_from_url = false){
let original = new Image();
original.src = img;
original.onload = function() {
let scaleX, scaleY;
scaleX = canvas.width*0.25 / this.width;
scaleY = scaleX;
if(!not_from_url){
new fabric.Image.fromURL(img,
function(temp_shape){
temp_shape.groupName = "shape_img" + index;
temp_shape.scaleX = scaleX;
temp_shape.scaleY = scaleY;
temp_shape.perPixelTargetFind = true,
temp_shape.index = index;
temp_shape.parent = temp_shape;
canvas.add(temp_shape);
temp_shape.sendToBack();
});
}
else{
var temp_shape = new fabric.Image(original);
temp_shape.groupName = "shape_img" + index;
temp_shape.left = crop_selection.left;
temp_shape.top = crop_selection.top;
temp_shape.setCoords();
temp_shape.index = index;
temp_shape.parent = temp_shape;
canvas.add(temp_shape);
temp_shape.sendToBack();
canvas.setActiveObject(temp_shape);
}
}
},
add_svg: function(e, img = element_pos.src, x = e.pointer.x, y = e.pointer.y, groupName = "shape_svg", flag = true, fill = fieldcolor){
new fabric.loadSVGFromURL(img,
function(objects, options) {
let temp_shape = fabric.util.groupSVGElements(objects, options);
temp_shape.set({
selectable: flag,
fill: fill,
centeredScaling: true,
perPixelTargetFind: true,
groupName: groupName + index,
caption: elements[element_pos.i].getAttribute("value"),
caption_type: elements[element_pos.i].id,
hasControls: false,
originX: "center",
originY: "center",
index: index
});
temp_shape.parent = temp_shape;
temp_shape.lockRotation = true;
if(element_pos.width / element_pos.height > 1){
temp_shape.scaleToWidth(element_pos.width);
}
else{
temp_shape.scaleToHeight(element_pos.height);
}
temp_shape.scaleConstX = temp_shape.scaleX;
temp_shape.scaleConstY = temp_shape.scaleY;
if(element_pos.width / element_pos.height > 1){
temp_shape.scaleToWidth(dimension[element_pos.id][zoom_size][0]);
}
else{
temp_shape.scaleToHeight(dimension[element_pos.id][zoom_size][1]);
}
// temp_shape.left = canvas.getPointer(e.e).x - window.devicePixelRatio / 2;
// temp_shape.top = canvas.getPointer(e.e).y + window.devicePixelRatio;
temp_shape.left = canvas.getPointer(e.e).x;
temp_shape.top = canvas.getPointer(e.e).y;
temp_shape.stroke_colorable = false;
canvas.add(temp_shape).renderAll();
endOfCreating(temp_shape);
editor_obj.add_legend();
}
);
},
add_legend: function(e, x = legend_back.left + legend_img_margin_left, y = legend_back.top){
biggest_legend_item_width = 0;
let array = canvas.getObjects();
for(let i in array){
let shape_type = /legend.*/.test(array[i].groupName);
if(shape_type){
let marker = array[i].caption_type + array[i].fill;
delete legend[marker];
// удаляем айтемы с канваса
canvas.remove(array[i]);
}
}
canvas.renderAll();
// создаем айтемы
legend_back.margin = 12;
const margin_top = 10;
const margin_bottom = 10;
text_height = margin_top;
for(let i in array){
let marker = array[i].caption_type + array[i].fill;
let shape_type = /shape_svg.*/.test(array[i].groupName);
// проверяем, есть ли айтем такого типа и цвета
if(shape_type && array[i].visible && !legend[marker]){
legend[marker] = true;
var img_item = fabric.util.object.clone(array[i]);
img_item.originX = 'center';
img_item.originY = 'center';
img_item.set({
"left": x + legend_back.margin,
"top": 0, // определено ниже
"scaleX": array[i].scaleConstX,
"scaleY": array[i].scaleConstY
});
img_item.groupName = "legend";
img_item.group = undefined;
img_item.selectable = false;
var text_item = editor_obj.add_text(e, x + legend_back.margin + legend_img_margin_left * 3, y + text_height, 0, array[i].caption, "legend", true, "black");
text_item.originY = 'center';
text_item.hasControls = false;
text_item.hasBorders = false;
text_item.fontFamily = 'Golos Text';
text_item.fontSize = 11;
text_item.textAlign = 'left';
text_item.index = array[i].index;
img_item.top = text_item.top = text_item.top + text_item.height / 2;
const outdent = img_item.left - legend_back.left;
canvas.renderAll();
text_item_width = text_item.width + outdent * 2;
if(text_item_width > biggest_legend_item_width){
biggest_legend_item_width = text_item_width;
}
text_height += text_item.height + margin_bottom;
legend_back.scaleX = (legend_back.margin + biggest_legend_item_width) / legend_back.width;
legend_back.scaleY = text_height / legend_back.height;
legend_back.rx = legend_back.border_radius * (1 / legend_back.scaleX);
legend_back.ry = legend_back.border_radius * (1 / legend_back.scaleY);
canvas.add(img_item);
text_item.on('changed', function () {
text_height = margin_top;
text_item_width = this.width + outdent * 2;
shape[this.index].caption = this.text;
if(text_item_width > biggest_legend_item_width){
biggest_legend_item_width = text_item_width;
}
if(legend_back.width * legend_back.scaleX < biggest_legend_item_width + legend_back.margin){
legend_back.scaleX = (legend_back.margin + biggest_legend_item_width) / legend_back.width;
}
let array = canvas.getObjects();
let array2 = [];
for(var i = 0; i < array.length; i++){
let shape_type = /legend.*/.test(array[i].groupName);
if(shape_type){
array2.push(array[i]);
}
}
for(var i = 0; i < array2.length; i+=2){
var img_item = array2[i + 1];
var text_item = array2[i];
if(img_item != undefined){
var top = legend_back.top + text_height + text_item.height / 2;
text_item.set("top", top);
img_item.set("top", top);
text_height += text_item.height + margin_bottom;
}
}
legend_back.scaleY = text_height / legend_back.height;
legend_back.rx = legend_back.border_radius * (1 / legend_back.scaleX);
legend_back.ry = legend_back.border_radius * (1 / legend_back.scaleY);
});
}
}
canvas.renderAll();
},
change_source: function(img){
let original = new Image();
original.src = img;
editor_start = true;
original.onload = function() {
let scaleX, scaleY, left, top;
if(canvas.width / canvas.height > this.width / this.height){
scaleY = canvas.height / this.height;
scaleX = scaleY;
}
else{
scaleX = canvas.width / this.width;
scaleY = scaleX;
}
let firstWidth = this.width * scaleX;
let firstHeight = this.height * scaleY;
let firstLeft = canvas.width / 2;
let firstTop = canvas.height / 2;
canvas.setBackgroundImage(img, function(){
canvas.backgroundImage.firstWidth = firstWidth;
canvas.backgroundImage.firstHeight = firstHeight;
canvas.backgroundImage.firstLeft = firstLeft;
canvas.backgroundImage.firstTop = firstTop;
canvas.renderAll()
}, {
scaleX: scaleX,
scaleY: scaleY,
left: firstLeft,
top: firstTop,
originX: 'center',
originY: 'center'
});
}
},
clone: function(){
let item = canvas.getActiveObject();
if(item != undefined && !group.cloneOne && item.groupName != "crop-1"){
if(item.type == "activeSelection" || item.parent.objects){
if(item.type == "activeSelection"){
var array = item._objects;
}
else{
var array = [];
for(let i of item.parent.objects){
array.push(item.parent[i]);
}
}
let array_temp = [];
canvas.discardActiveObject();
// let new_index = [];
for(let i = 0; i < array.length; i++){
// let index_temp = [Number(/\-*[0-9]+/.exec(array[i].groupName))];
let obj_temp = fabric.util.object.clone(array[i]);
obj_temp.clonned = true;
canvas.add(obj_temp);
let shape_type = /shape.*/.test(obj_temp.groupName); // если groupName не shape, то это примитив
if(!shape_type){ // если не примитив
obj_temp.groupName = obj_temp.groupName + "clone";
}
array_temp.push(obj_temp);
}
loadObjects(array_temp);
let selection_temp = new fabric.ActiveSelection(array_temp, {
canvas: canvas,
// originX: 'center',
// originY: 'center'
});
group = {groupName: undefined};
canvas.setActiveObject(selection_temp);
selection_temp.parent = selection_temp;
selection_temp.hasControls = false;
canvas.renderAll();
}
else{
let obj_temp = fabric.util.object.clone(item);
obj_temp.hasControls = false;
obj_temp.clonned = true;
canvas.add(obj_temp);
canvas.setActiveObject(shape[index]);
canvas.renderAll();
}
group.cloneOne = group.mousedown = true;
}
},
setClone: function(item){ // устанавливает клон в текущей позиции курсора, вызывается в undo_redo.js
group.cloneOne = false;
group.param_saved = false;
oldParam(item);
changes(item, "10");
actionsHist[actionsIndex].flag = 'add';
actionsHist.index = item.index;
if(item.type == "image"){
canvas.sendToBack(item);
}
if(item.groupType == "shape_rect" || item.groupType == "shape_circle"){
setTimeout(function(){
canvas.setActiveObject(item); // в _setActiveObject в fabric.js
}, 10);
}
group.param_saved = true;
canvas.renderAll();
}
};
var big_square_line_left = 0;
var big_square_line_top = 0;
class Cell{
constructor(scene, x, y, size, value, deltaX = 0, deltaY = 0, bg = true){
this.scene = scene;
this.x = x;
this.y = y;
this.deltaX = deltaX;
this.deltaY = deltaY;
this.size = size;
this.value = value;
this.bg = bg;
this._value;
}
set value(value){
this.scene.lineWidth = 0.4;
this._value = value;
this.scene.strokeStyle = value;
if(this.bg){
this.scene.strokeStyle = "#374448";
this.scene.fillStyle = value;
this.scene.fillRect(this.x * this.size + this.deltaX, this.y * this.size + this.deltaY, this.size, this.size);
this.scene.strokeRect(this.x * this.size + this.deltaX, this.y * this.size + this.deltaY, this.size, this.size);
}
else{
this.scene.strokeRect(this.x * this.size + this.deltaX + big_square_line_left, this.y * this.size + this.deltaY + big_square_line_top, this.size, this.size);
}
}
get value(){
return this._value;
}
}