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

1496 lines
60 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.

// Scripting by Oleg Okhotnikov, contact - svoboda200786@gmail.com
// Скрипт работает с элементами управления
let editor_start = true;
let ctrl = false;
let shift = false;
let stroke_width = 1;
let button_active;
let zoom_size = 0;
let default_zoom = {
text: 3,
rect: 0,
circle: 0,
pencil: 0,
line: 0,
size: 2,
geometry: 2,
arrow: 0,
socket: 3,
cap: 2,
svg: 1
};
let arrow_size_dimension = [[13, 5],[19, 8],[31, 13],[37, 16]];
let arrow_dimension = [[13, 5],[19, 8],[26, 11],[29, 12],[36, 15],[38, 16],[45, 19],[55, 24]];
let socket_dimension = [18, 21, 23, 28, 30, 34, 37, 42];
let text_dimension = [10, 12, 13, 14, 16, 20, 24, 32];
let resize_value;
let scroll_val;
let middle_button = false;
const zoom_item = document.querySelectorAll(".zoom .top-menu-items div");
const back_canvas = document.querySelector("#back-canvas");
const btn_delete = document.querySelector("#delete");
const btn_copy = document.querySelector("#copy");
const scroll_block = document.querySelector(".canvas-container");
const elements = document.querySelectorAll(".top-menu-button#elements .top-menu-items");
const palette = document.querySelector(".palette");
const scale_indicator = document.querySelector("#scale");
let element_pos = new Image;
let cur_ico = {
"cross": "url('cursors/cross.svg') " + element_ico_size / 2 + " " + element_ico_size / 2 + ", auto",
"pencil": "url('cursors/pencil.svg') " + 0 + " " + element_ico_size + ", auto",
"pointer": "url('cursors/move.svg') " + 0 + " " + 0 + ", auto",
"rotate": "url('cursors/rotate.svg') " + 8 + " " + 8 + ", auto"
}
canvas.freeDrawingCursor = cur_ico.pencil;
canvas.hoverCursor = cur_ico.pointer;
canvas.moveCursor = cur_ico.pointer;
let old_mouse_X = 0;
let old_arrow_X = 0;
let old_arrow_Y = 0;
let line_min_length = 20;
let geometry_obj = null;
let window_zoom = [0.5, 0.75, 1, 1.5, 2, 3, 4, 6, 8];
let window_zoom_index = 2;
window.global_zoom = 1;
let new_zoom = 1;
element_pos.active = 0;
canvas.defaultCursor_old = 'default';
let color_cell = document.querySelectorAll(".color-cell");
var editor_command;
var fake_selection_obj;
// temp — прямоугольник для расчета точного положения линии в _render в скрипте fabric.js.
// Стандартные свойства x1, y1, x2, y2 у линии дают погрешность,
// из-за чего стрелка (arrow) становится не посередине линии, что особенно заметно при большой толщине
let temp = editor_obj.add_rect(null, true, canvas.width, canvas.height, 200, 200, "#000", "transparent", "temp");
// temp.visible = false;
// canvas.add(temp);
// temp.excludeFromExport = true; // temp не добавляется на канвас и соответсвенно не попадает в экспорт (также в экспортне попадают объекты с visible = true)
var mouse_down_flag = false;
var rotate_flag = false;
let top_menu_buttons = document.querySelectorAll(".top-menu-button");
// scale_indicator.active = zoom_item[0];
for(let i = 0; i < zoom_item.length; i++){
zoom_item[i].setAttribute("size", i);
zoom_item[i].parentElement.addEventListener("click", function(){
setZoomingParam(i);
})
}
scale_indicator.addEventListener("mouseover", function(){
var item = canvas.getActiveObject();
if(item && !item.is_background){
var selected_item = document.querySelector(".zoom-size-selected");
if(selected_item){
selected_item.classList.remove("zoom-size-selected");
}
scale_indicator.active = document.querySelector("[size='" + item.parent.zoom_size + "']");
if(scale_indicator.active){
scale_indicator.active.classList.add("zoom-size-selected");
}
}
else{
scale_indicator.active = document.querySelector("[size='" + zoom_size + "']");
scale_indicator.active.classList.add("zoom-size-selected");
//scale_indicator.setAttribute("scale_value", (zoom_size + 1) + "x");
}
})
function setZoomingParam(i, item){
zoom_size = i;
if(scale_indicator.active){
scale_indicator.active.classList.remove("zoom-size-selected");
}
zoom_item[i].classList.add("zoom-size-selected");
var item = canvas.getActiveObject();
if(item){
changeStrokeWidth();
}
scale_indicator.active = zoom_item[i];
//scale_indicator.setAttribute("scale_value", (zoom_size + 1) + "x");
}
function selectStrokeWidth(type, name){
var stroke_width; // local var
switch(type){
case "size":
case "socket":
case "geometry":
if(name == "geometry_line_part1" || name == "geometry_line_part2"){
// десятые доли, чтобы не было пикселбной лесенки
if(zoom_size == 6 || zoom_size == 7){
stroke_width = 2.1;
}
else{
stroke_width = 1.1;
}
}
else{
if(zoom_size == 7){
stroke_width = 4;
}
else{
stroke_width = Math.ceil((zoom_size + 1) / 3);
}
}
break;
case "cap":
if(zoom_size == 7){
stroke_width = 4;
}
else{
stroke_width = Math.ceil((zoom_size + 1) / 3);
}
break;
default:
stroke_width = zoom_size + 1;
break;
}
return stroke_width;
}
function changeStrokeWidth(item){
if (canvas.isDrawingMode == 1){
canvas.freeDrawingBrush.width = zoom_size + 1;
}
if(item == undefined){
var active_object = canvas.getActiveObject();
if(active_object && !active_object.is_background){
item = active_object;
}
}
if(item != null && !/back/.test(item.groupName) && !/legend/.test(item.groupName) && zoom_size + 1 > 0 && !item.isEditing){
oldParam(item);
changeStrokeWidth_subfunction(item);
let shape_type = /shape_svg/.test(item.groupName);
if(!shape_type){ // если не svg,
//проходимся по всем частям составного объекта
if(item.parent.objects != undefined){
for(let i of item.parent.objects){
changeStrokeWidth_subfunction(item.parent[i]);
}
// ждем 10 милисекунд пока обновятся параметры, потом перерисовываем сцену
setTimeout(function(){
canvas.renderAll();
}, 10)
}
if(item.parent._objects != undefined){ // выделение или группа
for(let obj of item.parent._objects){
changeStrokeWidth_subfunction(obj, "group");
}
// пересчитываем размеры выделения после changeStrokeWidth_subfunction,
// поскольку они меняются в зависимости от размера линий, шрифта и т.п.
setTimeout(function(){
item._restoreObjectsState();
fabric.util.resetObjectTransform(item);
item._calcBounds();
item._updateObjectsCoords();
item.dirty = true;
item.setCoords();
canvas.renderAll();
}, 10)
}
canvas.renderAll();
}
}
if(item){
changes(item, "5");
}
var ctx = canvas.contextTop;
ctx.clearRect(0, 0, canvas2.width, canvas2.height);
drawBounds(item);
}
function changeStrokeWidth_subfunction(item, active_object_type){
let shape_type = /shape_svg.*/.test(item.groupName);
if(!shape_type && item.type != "activeSelection"
&& (!/socket.*/.test(item.parent.groupName)
|| (!/circle.*/.test(item.name)
&& item != item.parent) )
&& item.type != "polyline" && item.type != "path"
&& item.type != "image" && item.groupType != "crop"){
item.strokeWidth = selectStrokeWidth(item.groupType, item.groupType + "_" + item.name);
item.parent.zoom_size = zoom_size;
}
else if(shape_type){
if(element_pos.width / element_pos.height > 1){
item.scaleToWidth(dimension[item.caption_type][zoom_size][0]);
}
else{
item.scaleToHeight(dimension[item.caption_type][zoom_size][1]);
}
item.parent.zoom_size = zoom_size;
canvas.requestRenderAll();
}
if(item.text != undefined){
item.fontSize = text_dimension[zoom_size];
if(/shape_text.*/.test(item.groupName)){
item.setCoords();
}
}
if( ( (item.type == "polyline" || item.type == "path") && (item.pointType == "arrow_start"
|| item.pointType == "arrow_end") ) || item.type == "circle" && /cap.*/.test(item.groupName)){
// теперь изменение радиуса в fabric.js в render
let arrow = item;
scaleArrow(arrow);
}
if(item.type == "path" && item.groupType == "shape_pencil"){
item.strokeWidth = zoom_size + 1;
}
if(/socket.*/.test(item.groupName)){
scaleSocket(item.parent);
}
}
function scaleSocket(socket){
var zoom = socket_dimension[zoom_size] / socket_dimension[0];
socket.rect.scale(zoom);
socket.rect_back.scale(zoom);
}
function scaleArrow(arrow){
var old_angle = arrow.angle;
arrow.angle = 0;
if(/size.*/.test(arrow.groupName) || /socket.*/.test(arrow.groupName) || /geometry.*/.test(arrow.groupName)){
if(zoom_size == 7){
var id = 3;
}
else{
var id = Math.floor((zoom_size) / 3);
}
arrow.scaleX = arrow_dimension[id][0] / arrow.width;
arrow.scaleY = arrow_dimension[id][1] / arrow.height;
}
if(/arrow.*/.test(arrow.groupName)){
arrow.scaleX = arrow_dimension[zoom_size][0] / arrow.width;
arrow.scaleY = arrow_dimension[zoom_size][1] / arrow.height;
}
if(/cap.*/.test(arrow.groupName)){
// теперь изменение радиуса в fabric.js в render
// var diameter = arrow.parent.line.strokeWidth * 3 + 1;
// arrow.radius = diameter / 2;
}
// Обновление положения стрелки
if(arrow.parent && arrow.name != "arrow2" && arrow.name != "arrow_part2"){
if(!/socket.*/.test(arrow.parent.groupName)){
setTimeout(function(){
var fake_line = {
text2: arrow.parent.text2,
parent: arrow.parent,
line: {
x1: arrow.parent.arrow.left,
y1: arrow.parent.arrow.top,
x2: arrow.parent.arrow2.left,
y2: arrow.parent.arrow2.top,
}
}
textRotate(fake_line);
}, 10);
}
else{
setTimeout(function(){
var fake_line = {
text2: arrow.parent.line_part1.text2,
parent: arrow.parent,
line: {
x1: arrow.parent.arrow_part1.left,
y1: arrow.parent.arrow_part1.top,
x2: arrow.parent.left,
y2: arrow.parent.top
}
}
textRotate(fake_line);
fake_line = {
text2: arrow.parent.line_part2.text2,
parent: arrow.parent,
line: {
x1: arrow.parent.arrow_part2.left,
y1: arrow.parent.arrow_part2.top,
x2: arrow.parent.left,
y2: arrow.parent.top
}
}
textRotate(fake_line);
}, 10);
}
}
arrow.setCoords()
arrow.angle = old_angle;
}
for(let i = 0; i < color_cell.length; i++){
color_cell[i].setAttribute("color", getComputedStyle(color_cell[i]).backgroundColor);
color_cell[i].addEventListener("click", function(){
if(!mouse_down_flag){
fieldcolor = getComputedStyle(this).backgroundColor;
changeColor();
}
});
}
function changeColor(item){
if (canvas.isDrawingMode == 1){
canvas.freeDrawingBrush.color = fieldcolor;
}
if(item == undefined){
item = canvas.getActiveObject();
}
if(item != null && !/back/.test(item.groupName) && !item.isEditing){
oldParam(item);
changeColor_subfunction(item);
var has_svg = false;
if( (item.parent.objects || item.parent._objects != undefined) ){ // если не примтив,
//проходимся по всем частям составного объекта
if(item.parent.objects != undefined){
for(let i of item.parent.objects){
if(item.parent[i].groupType == "shape_svg"){
has_svg = true;
}
if(item.parent[i] != item){
changeColor_subfunction(item.parent[i])
}
}
}
if(item.parent._objects != undefined){ // выделение или группа и не часть другого объекта
for(let obj of item.parent._objects){
if(obj.groupType == "shape_svg"){
has_svg = true;
}
changeColor_subfunction(obj)
}
}
}
changes(item, "6");
if(has_svg){
editor_obj.add_legend();
}
canvas.renderAll();
}
}
function changeColor_subfunction(item){
if( ( item.type == "path" && item.groupType != "shape_pencil") || item.type == "polygon" || item.type == "i-text" || item.type == "textbox"
|| item.colorable || item.colorable == "undefined"){
item.fill = fieldcolor;
}
else if( (item.stroke_colorable || item.stroke_colorable == undefined) && item.groupType != "shape_svg" ){ // иначе - меняем цвет заливки
item.stroke = fieldcolor;
}
}
for (let i = 0; i < top_menu_buttons.length; i++){
let _this = top_menu_buttons[i];
if(_this.id != "" && _this.dataset.btn_type != "tool"){
top_menu_buttons[i].addEventListener("click", function(){
editor_command = this.id;
hideLens();
});
}
if(top_menu_buttons[i].closest(".panel").classList.contains("left-menu") && top_menu_buttons[i].dataset.btn_type != "tool"){
top_menu_buttons[i].addEventListener("click", function(){
showToolName(this);
});
}
else{
element_cursor();
}
};
function showToolName(element, change_cursor = true){
var styles = window.getComputedStyle(element,':before');
var img = styles['mask'];
var text_field = document.getElementById("selected-tool");
text_field.classList.remove("mfp-hide");
text_field.style = '--icon-img: ' + img;
var text = element.getAttribute("value")
text_field.setAttribute("value", text);
hideLens();
if(change_cursor){
canvas.defaultCursor = cur_ico.cross;
canvas.defaultCursor_old = canvas.defaultCursor;
}
if(!scale_indicator.active){
if(element.classList.contains("top-menu-items")){
zoom_size = default_zoom["svg"];
}
else{
zoom_size = default_zoom[element.id];
}
//scale_indicator.setAttribute("scale_value", (zoom_size + 1) + "x");
}
}
for(let i = 0; i < elements.length; i++){
elements[i].addEventListener("click", function(e){
showToolName(this, false);
canvas.discardActiveObject().renderAll();
if(button_active != undefined){
document.querySelector("#" + button_active).classList.remove("top-menu-button-selected");
}
element_pos.active = 1;
element_pos.src = "icons/3_" + this.id + ".svg";
element_pos.id = this.id;
element_pos.i = i;
canvas.defaultCursor_old = canvas.defaultCursor;
canvas.defaultCursor = 'none';
editor_command = "svg";
let array = canvas.getObjects();
// for(let n in array){
// array[n].selectable = false;
// }
})
}
document.querySelector("#pointer").addEventListener("click", function(){
element_cursor();
});
function element_cursor(from_exit_editing){ // очистка (элеменирование) курсора, обнуление переменных по esc или нажатию по полю
if(geometry_obj){
var item = geometry_obj;
oldParam(item);
changes(item, "7");
actionsHist[actionsIndex].flag = 'add';
actionsHist.index = item.index;
}
if(!from_exit_editing){ //если не после завершения редактирования текста составного элемента
editor_command = ""; // очищаем переменную, в которой хранится тип создаваемого объекта
hideLens()
if(button_active != undefined && button_active != "move"){
document.querySelector("#" + button_active).classList.remove("top-menu-button-selected");
}
button_active = undefined;
// canvas.defaultCursor = canvas.defaultCursor_old;
// canvas.defaultCursor_old = cur_ico.pointer;
}
geometry_obj = null;
mouse_down_flag = false;
if(element_pos.id){
var sizeX = dimension[element_pos.id][zoom_size][0] * window.global_zoom;
var sizeY = dimension[element_pos.id][zoom_size][1] * window.global_zoom;
canvas.contextTop.clearRect(element_pos.xor - sizeX / 2, element_pos.yor - sizeY / 2, sizeX, sizeY);
element_pos.id = "";
}
element_pos.active = 0;
if(group.cloneOne){
let obj = canvas.getActiveObject();
if(obj.type == "activeSelection"){
let objectsInSelection = obj._objects;
canvas.discardActiveObject();
objectsInSelection.forEach(function(object) {
canvas.remove(object);
});
}
else{
canvas.remove(obj);
}
// index = index_before.index;
group.cloneOne = false;
}
let array = canvas.getObjects();
var text_field = document.getElementById("selected-tool");
text_field.classList.add("mfp-hide");
text_field.style = '--icon-img: url("")';
if(button_active != "move"){
document.getElementById("pointer").click();
}
}
document.querySelector(".left-menu").addEventListener("click", function(e){
panelButtonFunctions(e);
});
document.querySelector(".top-menu").addEventListener("click", function(e){
panelButtonFunctions(e);
});
function panelButtonFunctions(e){
if(!/zoom.*/.test(e.target.className) && e.target.id != "undo-btn" && e.target.id != "redo-btn" && e.target.innerHTML == ""){
if(e.target.className != "color-cell color-cell-active"){
canvas.isDrawingMode = 0;
}
switch(e.target.id){
case "pointer":
canvas.defaultCursor = cur_ico.pointer;
canvas.defaultCursor_old = canvas.defaultCursor;
break;
case "selection":
canvas.defaultCursor = cur_ico.cross;
canvas.defaultCursor_old = canvas.defaultCursor;
editor_obj.add_selection();
break;
case "pencil":
canvas.freeDrawingBrush.width = zoom_size + 1;
canvas.freeDrawingBrush.color = fieldcolor;
canvas.defaultCursor = cur_ico.pencil;
canvas.defaultCursor_old = canvas.defaultCursor;
canvas.isDrawingMode = 1;
break;
}
if (e.target.classList.contains("top-menu-button")){
if(button_active != undefined && e.target.id != "stick"){
document.querySelector("#" + button_active).classList.remove("top-menu-button-selected");
}
if(!e.target.classList.contains("top-menu-button-selected")){
if(e.target.id != "move"){
e.target.classList.add("top-menu-button-selected");
}
if(e.target.id != "stick"){
button_active = e.target.id;
}
if(e.target.dataset.btn_type != "tool"){
element_pos.active = 2;
}
else{ // не фигуры, не объекты
element_pos.active = 0;
}
}
else{
if(e.target.id != "stick"){
element_cursor();
}
if(e.target.id != "move"){
e.target.classList.remove("top-menu-button-selected");
}
}
if(e.target.id == "move"){
e.target.classList.toggle("top-menu-button-selected");
}
else if(e.target.id != "stick"){
document.querySelector("#move").classList.remove("top-menu-button-selected");
}
}
}
}
document.querySelector(".palette").addEventListener("click", function(e){
if(e.target != this){
if(this.active != undefined){
this.active.classList.remove("color-cell-active");
}
e.target.classList.add("color-cell-active");
this.active = e.target;
}
});
document.addEventListener("keydown", function(e){
let item = canvas.getActiveObject();
switch(e.key){
case "Delete":
if(item && !item.isEditing){
deleteObj(item);
}
break;
case "Escape":
element_cursor();
canvas.isDrawingMode = 0;
break;
case "Shift":
shift = true;
break;
case "Control":
ctrl = true;
break;
case "ArrowLeft":
moveByStep(-1, 0);
break;
case "ArrowRight":
moveByStep(1, 0);
break;
case "ArrowUp":
moveByStep(0, -1);
break;
case "ArrowDown":
moveByStep(0, 1);
break;
}
if(e.ctrlKey){
if(e.keyCode == 67 || e.keyCode == 68){
e.preventDefault();
editor_obj.clone();
}
if(e.keyCode == 86){
e.preventDefault();
if(group.cloneOne){ // __onMouseDown в fabric.js, там установлен getActiveObject().setCoords()
let item = canvas.getActiveObject();
editor_obj.setClone(item);
// item.hasControls = true;
// canvas.setActiveObject(item);
canvas.renderAll();
element_cursor();
}
}
if(e.keyCode == 72){
e.preventDefault();
legend_back.visible = !legend_back.visible;
canvas.discardActiveObject();
canvas.renderAll();
}
let array = canvas.getObjects();
for(var i in array){
let shape_type = /legend.*/.test(array[i].groupName);
if(shape_type){
if(!legend_back.visible){
array[i].visible = false;
}
else{
array[i].visible = true;
}
canvas.bringToFront(array[i]).renderAll();
}
}
}
if (e.ctrlKey && e.code == "KeyZ") {
e.preventDefault();
myUndo.click();
poupup.classList.add("mfp-hide");
}
if (e.ctrlKey && e.code == "KeyX") {
e.preventDefault();
myRedo.click();
poupup.classList.add("mfp-hide");
}
});
document.addEventListener("keyup", function(e){
ctrl = false;
shift = false;
});
btn_copy.addEventListener("click", function(){//
editor_obj.clone();
});
btn_delete.addEventListener("click", function(){//
onObjectRemoved(canvas.getActiveObject());
deleteObj();
});
function deleteObj(item, flag){
if (item == undefined){
var item = canvas.getActiveObject();
}
if (!group.cloneOne && item != undefined && !/back/.test(item.groupName) && !/legend/.test(item.groupName)){
let shape_type = /shape.*/.test(item.groupName);
let has_svg = false;
if(!shape_type || item.type == "activeSelection"){ // если не примитив
// let array = canvas.getObjects();
if(!flag){ // если вызываем не после отмены создания, иначе просто скрываем и не перезаписываем свойства
// // с помощью oldParam
oldParam(item);
}
if(item.parent.objects != undefined){
for(let i of item.parent.objects){
item.parent[i].visible = false;
shape_type = /shape_svg.*/.test(item.parent[i].groupName);
if(shape_type){
has_svg = true;
}
}
var ctx = canvas.contextTop;
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
if(item.parent._objects != undefined){ // выделение или группа и не часть другого объекта
for(let obj of item.parent._objects){
obj.visible = false;
shape_type = /shape_svg.*/.test(obj.groupName);
if(shape_type){
has_svg = true;
}
}
}
if(!flag){ // если вызываем не после отмены создания
onObjectRemoved(item);
}
}
else{
if(!flag){ // если вызываем не после отмены создания
oldParam(item);
}
item.visible = false;
if(!flag){
onObjectRemoved(item);
}
shape_type = /shape_svg.*/.test(item.groupName);
if(shape_type){
has_svg = true;
}
}
// var ctx = canvas.contextTop;
// ctx.clearRect(0, 0, canvas.width, canvas.height);
canvas.discardActiveObject();
// shape_type = /shape_svg.*/.test(item.groupName);
if(has_svg){
editor_obj.add_legend();
}
}
canvas.renderAll();
}
canvas.on('mouse:move', function(e){
document.body.style.cursor = "default";
if(!canvas.isDragging){
if(button_active == "move"){
canvas.upperCanvasEl.style.cursor = "grab";
}
else if(canvas.upperCanvasEl.style.cursor.split("-")[1] != "resize" && editor_command != "svg" && !rotate_flag){
if(document.getElementById("selection").classList.contains("top-menu-button-selected") && (e.target != canvas._activeObject || !e.target && !canvas._activeObject) ){
canvas.upperCanvasEl.style.cursor = cur_ico["cross"]
}
else{
canvas.upperCanvasEl.style.cursor = canvas.defaultCursor_old;
}
}
}
else{
canvas.defaultCursor = "grabbing";
canvas.upperCanvasEl.style.cursor = "grabbing";
}
// if(document.getElementById("selection").classList.contains("top-menu-button-selected") && (e.target != canvas._activeObject || !e.target && !canvas._activeObject) ){
// console.log("1: ");
// canvas.upperCanvasEl.style.cursor = cur_ico["cross"]
// }
// else{
// canvas.upperCanvasEl.style.cursor = canvas.defaultCursor_old
// }
if(!move_flag && (!canvas.getActiveObject() || canvas.getActiveObject() == canvas.backgroundImage) && !top_panel_display ){
resizeBG(e);
}
})
function resizeBG(e){
if(canvas.backgroundImage){
canvas.backgroundImage.canvas = canvas;
// canvas.backgroundImage.drawControls(canvas.lowerCanvasEl.getContext('2d'));
}
if(canvas.backgroundImage && canvas.backgroundImage.oCoords && !mouse_down_flag){
let left_border = canvas.backgroundImage.oCoords.tl.x;
let right_border = canvas.backgroundImage.oCoords.tr.x;
let top_border = canvas.backgroundImage.oCoords.tl.y;
let bottom_border = canvas.backgroundImage.oCoords.bl.y;
var luft = 10;
if( (e.pointer.x >= left_border - luft && e.pointer.x <= left_border + luft ||
e.pointer.x >= right_border - luft && e.pointer.x <= right_border + luft) ){
// canvas.backgroundImage.hasControls = true;
if(canvas.getActiveObject() != canvas.backgroundImage){
canvas.setActiveObject(canvas.backgroundImage);
canvas.backgroundImage.canvas = canvas;
// canvas.backgroundImage.drawControls(canvas.lowerCanvasEl.getContext('2d'));
}
}
else if( (e.pointer.y <= bottom_border + luft && e.pointer.y >= bottom_border - luft ||
e.pointer.y >= top_border - luft && e.pointer.y <= top_border + luft) ){
// canvas.backgroundImage.hasControls = true;
if(canvas.getActiveObject() != canvas.backgroundImage){
canvas.setActiveObject(canvas.backgroundImage);
canvas.backgroundImage.canvas = canvas;
// canvas.backgroundImage.drawControls(canvas.lowerCanvasEl.getContext('2d'));
}
}
else{
if(canvas.getActiveObject() == canvas.backgroundImage){
canvas._activeObject = null;
// canvas.renderAll();
}
}
}
}
function drawSVGElements(e, obj, flag){
if(!obj){
obj = canvas.getActiveObject();
}
if(element_pos.active != 0 && !mouse_down_flag){
canvas.defaultCursor = 'none';
if(!flag){
element_pos.xor = e.pointer.x;
element_pos.yor = e.pointer.y;
}
if(editor_command != "pencil" && !(obj != undefined && obj.isEditing) && element_pos.active != 2){
canvas.contextTop.fillStyle = fieldcolor;
// canvas.defaultCursor = "default"; // отладка
var sizeX = dimension[element_pos.id][zoom_size][0] * window.global_zoom;
var sizeY = dimension[element_pos.id][zoom_size][1] * window.global_zoom;
canvas.contextTop.fillRect(element_pos.xor - sizeX/2, element_pos.yor - sizeY/2, sizeX, sizeY);
canvas.contextTop.globalCompositeOperation = 'destination-atop';
canvas.contextTop.drawImage(element_pos, 0, 0, element_pos.width, element_pos.height, element_pos.xor - sizeX / 2, element_pos.yor - sizeY / 2, sizeX, sizeY);
}
}
else{
canvas.contextTop.globalCompositeOperation = 'source-over';
}
}
canvas.on('mouse:move', function(e){
let item = canvas.getObjects()[canvas.getObjects().length - 1];
if(mouse_down_flag && editor_command != undefined && editor_command != "" && editor_command != "text" && editor_command != "socket"
&& editor_command != "svg" && editor_command != "pencil" && canvas.getActiveObject() == undefined && !text_editing){
let length = calcLineLength({x1: old_arrow_X, y1: old_arrow_Y, x2: canvas.getPointer(e.e).x, y2: canvas.getPointer(e.e).y});
if(length >= line_min_length || editor_command == "rect" || editor_command == "circle"){
if(typeof editor_obj["add_" + editor_command] == "function"){
editor_obj["add_" + editor_command](e);
}
}
}
mousePointer(e);
let obj = canvas.getActiveObject();
if(element_pos.width / element_pos.height > 2){
element_ico_size = 25;
}
else if(element_pos.width / element_pos.height > 1.4){
element_ico_size = 16;
}
else if(element_pos.width / element_pos.height > 1.3){
element_ico_size = 20;
}
else if(element_pos.width / element_pos.height < 1){
element_ico_size = 16;
}
else{
element_ico_size = 16;
}
drawSVGElements(e, obj);
if(obj != undefined && obj != legend_back){
if(mouse_down_flag && button_active != "move"){
canvas.upperCanvasEl.style.cursor = 'none';
}
canvas.preserveObjectStacking = false;
if(group.cloneOne){
canvas.defaultCursor = 'none';
canvas.defaultCursor_old = 'none';
if(e.target != undefined){
// e.target.selectable = false;
// e.target.hoverCursor = 'none';
}
if(obj.parent.originX != 'center' && obj.parent.originY != 'center'){
obj.left = canvas.getPointer(e.e).x - obj.parent.width*obj.parent.scaleX/2;
obj.top = canvas.getPointer(e.e).y - obj.parent.height*obj.parent.scaleY/2;
}
else{
obj.left = canvas.getPointer(e.e).x;
obj.top = canvas.getPointer(e.e).y;
}
canvas.renderAll();
}
}
});
canvas.on('mouse:down:before', function(e){
if(geometry_obj && geometry_obj.text2 != undefined && geometry_obj.text2.isEditing){
if(geometry_obj){
var item = geometry_obj;
oldParam(item);
changes(item, "8");
actionsHist[actionsIndex].flag = 'add';
actionsHist.index = item.index;
}
geometry_obj = null
}
if(!geometry_obj){
var item = e.target;
if(item && item.parent){
oldParam(item.parent);
}
}
})
canvas.on('mouse:down', function(e){
if(button_active != "move"){
fake_selection_obj = {};
}
let item = canvas.getActiveObject();
if(item != undefined){
var ctx = canvas.contextTop;
ctx.clearRect(0, 0, canvas2.width, canvas2.height);
let shape_type = /shape.*/.test(item.groupName);
if(shape_type && item.type != "activeSelection" && !/shape_svg.*/.test(item.groupName)){
item.hasControls = true;
item.hasBorders = true;
}
}
if(e.target != legend_back){
legend_back.selectable = false;
}
if(editor_command != "" && editor_command != undefined){
canvas.selection = false;
if(item != undefined && item.parent.added && !geometry_obj){
element_cursor();
}
else if(!text_editing){
// клик по полю либо по элементу создаваемого (в процессе создания) объекта geometry
// item равен null, поэтому используется geometry_obj
putObject(e);
}
}
// if( document.getElementById("selection").classList.contains("top-menu-button-selected") ){
// move_flag = true;
// canvas._groupSelector = true;
// }
if(geometry_obj){
item = geometry_obj;
if(item.text2 != undefined){
canvas.setActiveObject(item.text2);
item.text2.enterEditing();
item.text2.hiddenTextarea.focus();
item.text2.selectLine(1);
element_pos.style.display = "none";
}
// canvas.renderAll();
}
if(item && item.groupType == "geometry"){
window.geometry_selected = true;
}
mouse_down_flag = true;
if(!e.target){
if(palette.active){
palette.active.classList.remove("color-cell-active");
}
palette.active = document.querySelector("[color='" + fieldcolor + "']");
if(palette.active){
palette.active.classList.add("color-cell-active");
}
if(palette.active){
palette.active.classList.remove("color-cell-active");
}
palette.active = document.querySelector("[color='" + fieldcolor + "']");
if(palette.active){
palette.active.classList.add("color-cell-active");
}
if(scale_indicator.active){
scale_indicator.active.classList.remove("zoom-size-selected");
}
scale_indicator.active = document.querySelector("[size='" + zoom_size + "']");
if(scale_indicator.active){
scale_indicator.active.classList.add("zoom-size-selected");
//scale_indicator.setAttribute("scale_value", (zoom_size + 1) + "x");
}
}
});
function putObject(e){
if((editor_command == "text" || editor_command == "socket" || editor_command == "svg") && canvas.getActiveObject() == undefined){
editor_obj["add_" + editor_command](e);
}
move_flag = true; // нужно, чтобы не было выделения
mouse_down_flag = true;
old_arrow_X = canvas.getPointer(e.e).x;
old_arrow_Y = canvas.getPointer(e.e).y;
}
canvas.on('mouse:up', function(e){
if(scale_indicator.active){
scale_indicator.active.classList.remove("zoom-size-selected");
scale_indicator.active = null;
//scale_indicator.setAttribute("scale_value", (zoom_size + 1) + "x");
}
if( (e.target == null || element_pos.active != 1) && !geometry_obj){
endOfCreating(null, e);
}
mouse_down_flag = false;
shape_change_flag = false;
if(!crop_selection.visible){
crop_selection.added = false;
}
if(window.lens.style.display == "block"){
hideLens();
}
drawing_object = false;
var ctx = canvas.contextTop;
if(button_active != "move"){
ctx.clearRect(0, 0, canvas2.width, canvas2.height);
}
if(e.target){
var target = e.target;
}
else{
var target = canvas.getActiveObject();
}
// если было выделение, то сохраняем его после перемещения
if(target && target.parent && (target.parent.objects || target.parent._objects) && (!move_flag || move_flag && target.parent.was_selected) || button_active == "move" ){
if(button_active != "move"){
var item = e.target;
}
else{
var item = canvas.getActiveObject();
}
if(item){
drawBounds(item);
}
}
if(item && item.groupType == "geometry" && window.geometry_selected){
var ctx = canvas.contextTop;
ctx.clearRect(0, 0, canvas2.width, canvas2.height);
selection_temp2 = new fabric.ActiveSelection(geometry_array, {
canvas: canvas,
});
selection_temp2.parent = selection_temp2;
canvas.setActiveObject(selection_temp2);
window.geometry_selected = false;
}
// setTimeout(function(){
// canvas.renderAll();
// }, 100);
})
function drawBounds(item){
if(item){
if(item.parent.objects){
var array = [];
for(let i of item.parent.objects){ // добавляем в выделение части составного объекта
array.push(item.parent[i]);
};
if(item.groupType == "geometry"){
window.geometry_array = array;
}
selection_temp = new fabric.ActiveSelection([], {
canvas: canvas,
});
// объект, который подставляем аргументом вместо ActiveSelection, чтобы не менять положение выделения
fake_selection_obj = {_objects:array};
var ctx = canvas.contextTop;
for(var i in array){
selection_temp.addWithUpdate(item.parent[array[i]], true);
}
selection_temp._calcBounds(null, fake_selection_obj);
myDrawBorder_inner(ctx);
}
if(item.parent._objects){
var _this = canvas.getActiveObject();
const delta = 10;
_this.setCoords()
poupup.classList.remove("mfp-hide");
poupup.style.left = canvas.lowerCanvasEl.getBoundingClientRect().x + _this.oCoords.br.x - poupup.offsetWidth + "px";
poupup.style.top = canvas.lowerCanvasEl.getBoundingClientRect().y + _this.oCoords.br.y + delta + "px";
}
}
}
function endOfCreating(item, e){
if(editor_command != "" && editor_command != undefined && !geometry_obj){
if (!item){
item = canvas.getActiveObject();
}
if(item != undefined && !window.resizing_el){
let shape_type = /shape_svg.*/.test(item.groupName);
if(shape_type){
// item.hoverCursor = 'none';
}
if(item.text2 == undefined && item.text == undefined){
canvas.discardActiveObject();
}
else if(item.text2 != undefined){
canvas.setActiveObject(item.text2);
item.text2.enterEditing();
item.text2.hiddenTextarea.focus();
item.text2.selectLine(1);
element_pos.style.display = "none";
}
else{
canvas.setActiveObject(item);
item.enterEditing();
item.hiddenTextarea.focus();
item.selectLine(1);
// canvas.renderAll();
element_pos.style.display = "none";
}
if(!/geometry.*/.test(item.groupName)){
oldParam(item);
if(!item.ispart && file_loaded){
changes(item, "8");
actionsHist[actionsIndex].flag = 'add';
actionsHist.index = item.index;
}
}
if(item.parent.line_part1 != undefined && item.parent.line_part1.text2 == undefined){
item.parent.line_part1.set('x1', item.parent.line.x1);
item.parent.line_part1.set('y1', item.parent.line.y1);
item.parent.line_part2.set('x1', item.parent.line.x2);
item.parent.line_part2.set('y1', item.parent.line.y2);
}
item.parent.added = true;
if(/geometry.*/.test(item.groupName)){ // создан родительский объект (линия со стрелками) объекта geometry
canvas.setActiveObject(item.parent.line);
item.parent.line.first_center = {
x: item.parent.line.x1 + (item.parent.line.x2 - item.parent.line.x1) / 2,
y: item.parent.line.y1 + (item.parent.line.y2 - item.parent.line.y1) / 2
};
item.parent.line.first_click = {
x: canvas.getPointer(e.e).x,
y: canvas.getPointer(e.e).y
};
geometry_obj = item.parent; // объект geometry в процессе создания
// canvas.renderAll();
}
}
if(!geometry_obj){ // завершение создания объекта
mouse_down_flag = false;
}
else{
mouse_down_flag = true;
}
}
canvas.selection = true;
}
function mousePointer(e){
let item = canvas.getActiveObject();
if(item != null){
let shape_type = /shape.*/.test(item.groupName);
if(item != undefined && mouse_down_flag){
// если объект содержит стрелку, присваиваем координаты (процесс рисования, то есть объект не создан)
if (item.pointType == 'arrow_start' && !item.parent.added){
item.left = canvas.getPointer(e.e).x;
item.top = canvas.getPointer(e.e).y;
item.setCoords();
// canvas.renderAll();
}
if(shape_type && !item.added){
switch(editor_command){
case "rect":
item.width = canvas.getPointer(e.e).x - item.left;
if(ctrl){
item.height = item.width;
}
else{
item.height = canvas.getPointer(e.e).y - item.top;
}
break;
case "circle":
item.scaleX = (canvas.getPointer(e.e).x - item.left) / 2;
if(ctrl){
item.scaleY = item.scaleX;
}
else{
item.scaleY = (canvas.getPointer(e.e).y - item.top) / 2;
}
break;
// case "text":
// item.scaleX = (canvas.getPointer(e.e).x - item.left) / item.width;
// item.scaleY = item.scaleX;
// break;
}
canvas.renderAll();
}
}
}
}
function hideLens(){
var item = canvas.getActiveObject();
if(window.lens){
if(shape_change_flag || editor_command == "size" || editor_command == "arrow"
|| editor_command == "line" || editor_command == "cap"
|| document.getElementById("selection").classList.contains("top-menu-button-selected")
|| item && (item.pointType == "arrow_start" || item.pointType == "arrow_end") && mouse_down_flag ){
window.lens_move = true;
window.lens.style.display = "block";
}
else{
window.lens_move = false;
window.lens.style.display = "none";
}
if(editor_command == "cap" && mouse_down_flag){
window.lens_move = false;
window.lens.style.display = "none";
}
}
}
scroll_block.addEventListener("wheel", function(e){
zoomField(e);
// resizeWindow();
});
document.querySelectorAll(".zoom-btn").forEach(function(obj){
obj.addEventListener("click", function(e){
zoomField({
offsetX: canvas.width / 2,
offsetY: canvas.height / 2,
direct: this.id
});
canvas.viewportTransform[4] = canvas.width / 2 - canvas.backgroundImage.left * window_zoom[window_zoom_index];
canvas.viewportTransform[5] = canvas.height / 2 - canvas.backgroundImage.top * window_zoom[window_zoom_index];
});
});
function zoomField(e){
if(e.direct == "zoom-in" || e.deltaY < 0){
if(window_zoom_index < 8){
window_zoom_index++;
canvas.zoomToPoint(new fabric.Point(e.offsetX, e.offsetY), window_zoom[window_zoom_index]);
}
document.getElementById("zoom-text").setAttribute("value", window_zoom[window_zoom_index] + "x");
window.global_zoom = window_zoom[window_zoom_index];
}
else{
if(window_zoom_index > 0){
window_zoom_index--;
canvas.zoomToPoint(new fabric.Point(e.offsetX, e.offsetY), window_zoom[window_zoom_index]);
}
document.getElementById("zoom-text").setAttribute("value", window_zoom[window_zoom_index] + "x");
window.global_zoom = window_zoom[window_zoom_index];
}
window.screen_shot_available = true;
var item = canvas.getActiveObject();
if(item){
var ctx = canvas.contextTop;
ctx.clearRect(0, 0, canvas2.width, canvas2.height);
drawBounds(item);
}
else{
drawSVGElements(e, null, true);
}
}
document.querySelector("#move").addEventListener("click", function(){
element_cursor();
if(!this.classList.contains("top-menu-button-selected")){
canvas.defaultCursor_old = canvas.defaultCursor;
canvas.defaultCursor = "grab";
}
})
canvas.on('mouse:down', function(opt) {
event.preventDefault();
var evt = opt.e;
if (button_active == "move") {
this.isDragging = true;
this.isDrawingMode = 0;
this.selection = false;
this.lastPosX = evt.clientX;
this.lastPosY = evt.clientY;
}
});
document.addEventListener("mousedown", function(e){
if(e.button == 1){
middle_button = true;
}
if(middle_button) {
e.preventDefault();
canvas.isDragging = true;
canvas.isDrawingMode = 0;
canvas.selection = false;
canvas.lastPosX = e.clientX;
canvas.lastPosY = e.clientY;
}
});
document.addEventListener("mouseup", function(e){
if( document.querySelector("#pencil").classList.contains("top-menu-button-selected") ){
canvas.isDrawingMode = 1;
}
canvas.isDragging = false;
clearCursor();
if(middle_button ){
var item = canvas.getActiveObject();
if(item){
drawBounds(item);
}
}
middle_button = false;
if(button_active != "move"){
canvas.isDragging = false;
}
});
canvas.on('mouse:up', function(opt) {
this.selection = true;
});
document.addEventListener("keyup", function(e){
clearCursor();
});
function clearCursor(){
if(button_active != "move"){
canvas.defaultCursor = canvas.defaultCursor_old;
canvas.upperCanvasEl.style.cursor = canvas.defaultCursor_old;
}
else{
canvas.defaultCursor = "grab";
}
}
canvas.on('mouse:move', function(opt) {
if (this.isDragging) {
var e = opt.e;
window.vpt = this.viewportTransform;
if(window_zoom[window_zoom_index] >= 1){
var vpt4_temp = vpt[4] + e.clientX - this.lastPosX;
var vpt5_temp = vpt[5] + e.clientY - this.lastPosY;
if(typeof canvas.backgroundImage != "undefined" && canvas.backgroundImage){
window.borders_left = Math.round(canvas.backgroundImage.left - (canvas.backgroundImage.width / 2) * canvas.backgroundImage.scaleX) * window_zoom[window_zoom_index] + vpt4_temp;
window.borders_right = Math.round(canvas.backgroundImage.left + (canvas.backgroundImage.width / 2) * canvas.backgroundImage.scaleX) * window_zoom[window_zoom_index] + vpt4_temp;
window.borders_top = Math.round(canvas.backgroundImage.top - (canvas.backgroundImage.height / 2) * canvas.backgroundImage.scaleY) * window_zoom[window_zoom_index] + vpt5_temp;
window.borders_bottom = Math.round(canvas.backgroundImage.top + (canvas.backgroundImage.height / 2) * canvas.backgroundImage.scaleY) * window_zoom[window_zoom_index] + vpt5_temp;
if(canvas.backgroundImage.width * canvas.backgroundImage.scaleX * window_zoom[window_zoom_index] <= canvas.width){
vpt[4] += e.clientX - this.lastPosX;
if(borders_left <= 0){
vpt[4] = -Math.round(canvas.backgroundImage.left - (canvas.backgroundImage.width / 2) * canvas.backgroundImage.scaleX) * window_zoom[window_zoom_index];
}
if(borders_right >= canvas.width){
vpt[4] = canvas.width - Math.round(canvas.backgroundImage.left + (canvas.backgroundImage.width / 2) * canvas.backgroundImage.scaleX) * window_zoom[window_zoom_index];
}
}
else{
if(borders_left <= 0 && this.lastPosX <= e.clientX || borders_right >= canvas.width && this.lastPosX >= e.clientX){
vpt[4] = vpt4_temp;
}
}
if(canvas.backgroundImage.height * canvas.backgroundImage.scaleY * window_zoom[window_zoom_index] <= canvas.height){
vpt[5] += e.clientY - this.lastPosY;
if(borders_top <= 0){
vpt[5] = 0;
}
if(borders_bottom >= canvas.height){
vpt[5] = canvas.height - Math.round(canvas.backgroundImage.top + (canvas.backgroundImage.height / 2) * canvas.backgroundImage.scaleY) * window_zoom[window_zoom_index];
}
}
else{
if(borders_top <= 0 && this.lastPosY <= e.clientY || borders_bottom >= canvas.height && this.lastPosY >= e.clientY){
vpt[5] = vpt5_temp;
}
}
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
}
}
// if(canvas.getActiveObject() && canvas.getActiveObject().type == "activeSelection" && mouse_down_flag){
// poupup.classList.add("mfp-hide");
// }
if(mouse_down_flag || group.cloneOne){
move_flag = true;
poupup.classList.add("mfp-hide");
}
if(middle_button || button_active == "move" && mouse_down_flag){
poupup.classList.add("mfp-hide");
}
});
function resizeWindow(){
var deltaX = scroll_block.offsetWidth - canvas.width;
var deltaY = scroll_block.offsetHeight - canvas.height;
canvas.setWidth(scroll_block.offsetWidth);
canvas.setHeight(scroll_block.offsetHeight);
// canvas.viewportTransform[4] += deltaX * window_zoom[window_zoom_index];
// canvas.viewportTransform[5] += deltaY * window_zoom[window_zoom_index];
document.getElementById("back-canvas").width = scroll_block.offsetWidth;
document.getElementById("back-canvas").height = scroll_block.offsetHeight;
window.screen_shot_available = true;
// vpt в центр фона
if(canvas.backgroundImage){
canvas.viewportTransform[4] = canvas.width / 2 - canvas.backgroundImage.left * window_zoom[window_zoom_index];
canvas.viewportTransform[5] = canvas.height / 2 - canvas.backgroundImage.top * window_zoom[window_zoom_index];
}
// сбиваются координаты — обновляем
let array = canvas.getObjects();
for(var i in array){
array[i].setCoords();
}
// var qq = (canvas.viewportTransform[4] - (canvas.backgroundImage.left) + window_zoom[window_zoom_index] * (canvas.backgroundImage.left)) / window_zoom[window_zoom_index];
// canvas.viewportTransform[4] = (canvas.width / 2 * (1 - window_zoom[window_zoom_index]) + qq*window_zoom[window_zoom_index]);
// canvas.renderAll();
}
// canvas.upperCanvasEl.getContext('2d').fillRect(555 * 0.5, 400, 10, 10)
window.addEventListener('resize', function(event) {
resizeWindow();
}, true);
function init(){
window._x = 0;
window._y = 0;
window.field2 = [];
window.cellSize2 = 16;
window.canvas2 = document.querySelector("#back-canvas");
window.scene2 = canvas2.getContext("2d");
window.fieldWidth2 = Math.round(canvas2.width / cellSize2);
window.fieldHeight2 = Math.round(canvas2.height / cellSize2);
// canvas.setWidth(scroll_block.offsetWidth);
// canvas.setHeight(scroll_block.offsetHeight);
// document.getElementById("back-canvas").width = scroll_block.offsetWidth;
// document.getElementById("back-canvas").height = scroll_block.offsetHeight;
resizeWindow();
window.screen_shot_available = true;
document.getElementById("pointer").click();
if(canvas.backgroundImage && !canvas.backgroundImage.oCoords){
canvas.backgroundImage.lockMovementX = true;
canvas.backgroundImage.lockMovementY = true;
canvas.setActiveObject(canvas.backgroundImage)
canvas.backgroundImage.canvas = canvas
canvas.backgroundImage.drawControls(canvas.lowerCanvasEl.getContext('2d'));
canvas.discardActiveObject();
// canvas.renderAll();
}
canvas.renderAll();
}
init();
canvasEvents();