// 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();