diff --git a/src/js/config.js b/src/js/config.js index 4c67092..40aecce 100644 --- a/src/js/config.js +++ b/src/js/config.js @@ -73,10 +73,8 @@ config.TOOLS = [ { name: 'select', title: 'Select object tool', - on_update: 'on_params_update', attributes: { auto_select: true, - auto_snap: true, }, }, { diff --git a/src/js/core/base-gui.js b/src/js/core/base-gui.js index 94c4f94..71da635 100644 --- a/src/js/core/base-gui.js +++ b/src/js/core/base-gui.js @@ -110,14 +110,6 @@ class Base_gui_class { else{ config.SNAP = Boolean(snap_cookie); } - if(config.SNAP == false){ - //turn "select > snap" off - for(var i in config.TOOLS){ - if(config.TOOLS[i].name == 'select'){ - config.TOOLS[i].attributes.auto_snap = false; - } - } - } } render_main_gui() { diff --git a/src/js/core/base-tools.js b/src/js/core/base-tools.js index 73b397d..542f34f 100644 --- a/src/js/core/base-tools.js +++ b/src/js/core/base-tools.js @@ -392,14 +392,28 @@ class Base_tools_class { if (mouse.valid == false || mouse.click_valid == false) return; + var x_pos = mouse.x; + var y_pos = mouse.y; + + //apply snap + var snap_info = this.calc_snap_initial(e, x_pos, y_pos); + if(snap_info != null){ + if(snap_info.x != null) { + x_pos = snap_info.x; + } + if(snap_info.y != null) { + y_pos = snap_info.y; + } + } + //register new object - current layer is not ours or params changed this.layer = { type: this.name, params: this.clone(this.getParams()), status: 'draft', render_function: [this.name, 'render'], - x: Math.round(mouse.x), - y: Math.round(mouse.y), + x: Math.round(x_pos), + y: Math.round(y_pos), color: null, is_vector: true }; @@ -449,6 +463,18 @@ class Base_tools_class { config.layer.y = y; config.layer.width = width; config.layer.height = height; + + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + config.layer.width = snap_info.width; + } + if(snap_info.height != null) { + config.layer.height = snap_info.height; + } + } + this.Base_layers.render(); } @@ -491,6 +517,18 @@ class Base_tools_class { return; } + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + width = snap_info.width; + } + if(snap_info.height != null) { + height = snap_info.height; + } + } + this.snap_line_info = {x: null, y: null}; + //more data app.State.do_action( new app.Actions.Update_layer_action(config.layer.id, { @@ -504,5 +542,260 @@ class Base_tools_class { ); } + render_overlay_parent(ctx){ + //x + if(this.snap_line_info.x !== null) { + this.Helper.draw_special_line( + ctx, + this.snap_line_info.x.start_x, + this.snap_line_info.x.start_y, + this.snap_line_info.x.end_x, + this.snap_line_info.x.end_y + ); + } + + //y + if(this.snap_line_info.y !== null) { + this.Helper.draw_special_line( + ctx, + this.snap_line_info.y.start_x, + this.snap_line_info.y.start_y, + this.snap_line_info.y.end_x, + this.snap_line_info.y.end_y + ); + } + } + + get_snap_positions(exclude_id) { + var snap_positions = { + x: [ + 0, + config.WIDTH/2, + config.WIDTH, + ], + y: [ + 0, + config.HEIGHT/2, + config.HEIGHT, + ], + }; + for(var i in config.layers){ + if(typeof exclude_id != "undefined" && exclude_id == config.layers[i].id){ + continue; + } + if(config.layers[i].visible == false + || config.layers[i].x === null || config.layers[i].y === null + || config.layers[i].width === null || config.layers[i].height === null){ + continue; + } + + //x + var x = config.layers[i].x; + if(x > 0 && x < config.WIDTH) + snap_positions.x.push(x); + + var x = config.layers[i].x + config.layers[i].width/2; + if(x > 0 && x < config.WIDTH) + snap_positions.x.push(x); + + var x = config.layers[i].x + config.layers[i].width; + if(x > 0 && x < config.WIDTH) + snap_positions.x.push(x); + + //y + var y = config.layers[i].y; + if(y > 0 && y < config.HEIGHT) + snap_positions.y.push(y); + + var y = config.layers[i].y + config.layers[i].height/2; + if(y > 0 && y < config.HEIGHT) + snap_positions.y.push(y); + + var y = config.layers[i].y + config.layers[i].height; + if(y > 0 && y < config.HEIGHT) + snap_positions.y.push(y); + } + + return snap_positions; + } + + /** + * calculates initial object snap coordinates (x, y) and returns it. One of coordinates can be null. + * + * @param event + * @param pos_x + * @param pos_y + * @returns object|null + */ + calc_snap_initial(event, pos_x, pos_y) { + var snap_position = { x: null, y: null, width: null, height: null }; + var params = this.getParams(); + + if(config.SNAP === false || event.shiftKey == true || (event.ctrlKey == true || event.metaKey == true)){ + this.snap_line_info = {x: null, y: null}; + return null; + } + + //settings + var sensitivity = 0.01; + var max_distance = (config.WIDTH + config.HEIGHT) / 2 * sensitivity / config.ZOOM; + + //collect snap positions + var snap_positions = this.get_snap_positions(); + + //find closest snap positions + var min_value = { + x: null, + y: null, + }; + var min_distance = { + x: null, + y: null, + }; + //x + for(var i in snap_positions.x){ + var distance = Math.abs(pos_x - snap_positions.x[i]); + if(distance < max_distance && (distance < min_distance.x || min_distance.x === null)){ + min_distance.x = distance; + min_value.x = snap_positions.x[i]; + } + } + //y + for(var i in snap_positions.y){ + var distance = Math.abs(pos_y - snap_positions.y[i]); + if(distance < max_distance && (distance < min_distance.y || min_distance.y === null)){ + min_distance.y = distance; + min_value.y = snap_positions.y[i]; + } + } + + //apply snap + var success = false; + + //x + if(min_value.x != null) { + snap_position.x = Math.round(min_value.x); + success = true; + this.snap_line_info.x = { + start_x: min_value.x, + start_y: 0, + end_x: min_value.x, + end_y: config.HEIGHT + }; + } + else{ + this.snap_line_info.x = null; + } + //y + if(min_value.y != null) { + snap_position.y = Math.round(min_value.y); + success = true; + this.snap_line_info.y = { + start_x: 0, + start_y: min_value.y, + end_x: config.WIDTH, + end_y: min_value.y, + }; + } + else{ + this.snap_line_info.y = null; + } + + if(success) { + return snap_position; + } + + return null; + } + + /** + * calculates last object snap coordinates (width, height) and returns it. One of coordinates can be null. + * + * @param event + * @param pos_x + * @param pos_y + * @returns object|null + */ + calc_snap_end(event) { + var snap_position = { x: null, y: null, width: null, height: null }; + var params = this.getParams(); + + if(config.SNAP === false || event.shiftKey == true || (event.ctrlKey == true || event.metaKey == true)){ + this.snap_line_info = {x: null, y: null}; + return null; + } + + //settings + var sensitivity = 0.01; + var max_distance = (config.WIDTH + config.HEIGHT) / 2 * sensitivity / config.ZOOM; + + //collect snap positions + var snap_positions = this.get_snap_positions(config.layer.id); + + //find closest snap positions + var min_value = { + x: null, + y: null, + }; + var min_distance = { + x: null, + y: null, + }; + //x + for(var i in snap_positions.x){ + var distance = Math.abs(config.layer.x + config.layer.width - snap_positions.x[i]); + if(distance < max_distance && (distance < min_distance.x || min_distance.x === null)){ + min_distance.x = distance; + min_value.x = snap_positions.x[i]; + } + } + //y + for(var i in snap_positions.y){ + var distance = Math.abs(config.layer.y + config.layer.height - snap_positions.y[i]); + if(distance < max_distance && (distance < min_distance.y || min_distance.y === null)){ + min_distance.y = distance; + min_value.y = snap_positions.y[i]; + } + } + + //apply snap + var success = false; + + //x + if(min_value.x != null) { + snap_position.width = Math.round(min_value.x - config.layer.x); + success = true; + this.snap_line_info.x = { + start_x: min_value.x, + start_y: 0, + end_x: min_value.x, + end_y: config.HEIGHT + }; + } + else{ + this.snap_line_info.x = null; + } + //y + if(min_value.y != null) { + snap_position.height = Math.round(min_value.y - config.layer.y); + success = true; + this.snap_line_info.y = { + start_x: 0, + start_y: min_value.y, + end_x: config.WIDTH, + end_y: min_value.y, + }; + } + else{ + this.snap_line_info.y = null; + } + + if(success) { + return snap_position; + } + + return null; + } + } export default Base_tools_class; diff --git a/src/js/tools/media.js b/src/js/tools/media.js index 5f48c56..d56ee9a 100644 --- a/src/js/tools/media.js +++ b/src/js/tools/media.js @@ -54,7 +54,7 @@ class Media_class extends Base_tools_class { var settings = { title: 'Search', - comment: 'Source: pixabay.com.', + //comment: 'Source: pixabay.com.', className: 'wide', params: [ {name: "query", title: "Keyword:", value: query}, diff --git a/src/js/tools/select.js b/src/js/tools/select.js index 96736ef..8140130 100644 --- a/src/js/tools/select.js +++ b/src/js/tools/select.js @@ -21,7 +21,6 @@ class Select_tool_class extends Base_tools_class { this.keyboard_move_start_position = null; this.moving = false; this.resizing = false; - this.ctrl_pressed = false; this.snap_line_info = {x: null, y: null}; var sel_config = { @@ -36,13 +35,6 @@ class Select_tool_class extends Base_tools_class { this.Base_selection = new Base_selection_class(ctx, sel_config, this.name); } - on_params_update() { - var params = this.getParams(); - if (params.auto_snap == true && config.SNAP == false) { - alertify.error('Snap is disabled on settings.'); - } - } - load() { var _this = this; @@ -264,27 +256,7 @@ class Select_tool_class extends Base_tools_class { if (mouse.is_drag == false) return; - //x - if(this.snap_line_info.x !== null) { - this.Helper.draw_special_line( - ctx, - this.snap_line_info.x.start_x, - this.snap_line_info.x.start_y, - this.snap_line_info.x.end_x, - this.snap_line_info.x.end_y - ); - } - - //y - if(this.snap_line_info.y !== null) { - this.Helper.draw_special_line( - ctx, - this.snap_line_info.y.start_x, - this.snap_line_info.y.start_y, - this.snap_line_info.y.end_x, - this.snap_line_info.y.end_y - ); - } + this.render_overlay_parent(ctx); } /** @@ -299,7 +271,7 @@ class Select_tool_class extends Base_tools_class { var snap_position = { x: null, y: null }; var params = this.getParams(); - if(config.SNAP === false || params.auto_snap !== true || event.ctrlKey == true || event.metaKey == true){ + if(config.SNAP === false || event.shiftKey == true){ this.snap_line_info = {x: null, y: null}; return null; } @@ -309,51 +281,7 @@ class Select_tool_class extends Base_tools_class { var max_distance = (config.WIDTH + config.HEIGHT) / 2 * sensitivity / config.ZOOM; //collect snap positions - var snap_positions = { - x: [ - 0, - config.WIDTH/2, - config.WIDTH, - ], - y: [ - 0, - config.HEIGHT/2, - config.HEIGHT, - ], - }; - for(var i in config.layers){ - if(config.layer.id == config.layers[i].id || config.layers[i].visible == false - || config.layers[i].x === null || config.layers[i].y === null - || config.layers[i].width === null || config.layers[i].height === null){ - continue; - } - - //x - var x = config.layers[i].x; - if(x > 0 && x < config.WIDTH) - snap_positions.x.push(x); - - var x = config.layers[i].x + config.layers[i].width/2; - if(x > 0 && x < config.WIDTH) - snap_positions.x.push(x); - - var x = config.layers[i].x + config.layers[i].width; - if(x > 0 && x < config.WIDTH) - snap_positions.x.push(x); - - //y - var y = config.layers[i].y; - if(y > 0 && y < config.HEIGHT) - snap_positions.y.push(y); - - var y = config.layers[i].y + config.layers[i].height/2; - if(y > 0 && y < config.HEIGHT) - snap_positions.y.push(y); - - var y = config.layers[i].y + config.layers[i].height; - if(y > 0 && y < config.HEIGHT) - snap_positions.y.push(y); - } + var snap_positions = this.get_snap_positions(config.layer.id); //find closest snap positions var min_group = { diff --git a/src/js/tools/shapes/arrow.js b/src/js/tools/shapes/arrow.js index 28b247a..881cb05 100644 --- a/src/js/tools/shapes/arrow.js +++ b/src/js/tools/shapes/arrow.js @@ -11,6 +11,8 @@ class Arrow_class extends Base_tools_class { this.ctx = ctx; this.name = 'arrow'; this.layer = {}; + this.best_ratio = 1; + this.snap_line_info = {x: null, y: null}; } load() { @@ -22,14 +24,28 @@ class Arrow_class extends Base_tools_class { if (mouse.valid == false || mouse.click_valid == false) return; + var x_pos = mouse.x; + var y_pos = mouse.y; + + //apply snap + var snap_info = this.calc_snap_initial(e, x_pos, y_pos); + if(snap_info != null){ + if(snap_info.x != null) { + x_pos = snap_info.x; + } + if(snap_info.y != null) { + y_pos = snap_info.y; + } + } + //register new object - current layer is not ours or params changed this.layer = { type: this.name, params: this.clone(this.getParams()), status: 'draft', render_function: [this.name, 'render'], - x: mouse.x, - y: mouse.y, + x: x_pos, + y: y_pos, rotate: null, is_vector: true, color: config.COLOR @@ -62,6 +78,18 @@ class Arrow_class extends Base_tools_class { //more data config.layer.width = width; config.layer.height = height; + + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + config.layer.width = snap_info.width; + } + if(snap_info.height != null) { + config.layer.height = snap_info.height; + } + } + this.Base_layers.render(); } @@ -89,6 +117,17 @@ class Arrow_class extends Base_tools_class { height = 0; } + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + width = snap_info.width; + } + if(snap_info.height != null) { + height = snap_info.height; + } + } + //more data app.State.do_action( new app.Actions.Update_layer_action(config.layer.id, { @@ -100,6 +139,11 @@ class Arrow_class extends Base_tools_class { ); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { ctx.fillStyle = '#aaa'; ctx.strokeStyle = '#555'; diff --git a/src/js/tools/shapes/cylinder.js b/src/js/tools/shapes/cylinder.js index 4e5163c..a87cfc9 100644 --- a/src/js/tools/shapes/cylinder.js +++ b/src/js/tools/shapes/cylinder.js @@ -12,6 +12,7 @@ class Cylinder_class extends Base_tools_class { this.name = 'cylinder'; this.layer = {}; this.best_ratio = 0.7; + this.snap_line_info = {x: null, y: null}; } load() { @@ -30,6 +31,11 @@ class Cylinder_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { ctx.fillStyle = '#aaa'; ctx.strokeStyle = '#555'; diff --git a/src/js/tools/shapes/ellipse.js b/src/js/tools/shapes/ellipse.js index 58df8d5..57c058d 100644 --- a/src/js/tools/shapes/ellipse.js +++ b/src/js/tools/shapes/ellipse.js @@ -11,6 +11,8 @@ class Ellipse_class extends Base_tools_class { this.ctx = ctx; this.name = 'ellipse'; this.layer = {}; + this.best_ratio = 1; + this.snap_line_info = {x: null, y: null}; } load() { @@ -23,14 +25,28 @@ class Ellipse_class extends Base_tools_class { if (mouse.valid == false || mouse.click_valid == false) return; + var x_pos = mouse.x; + var y_pos = mouse.y; + + //apply snap + var snap_info = this.calc_snap_initial(e, x_pos, y_pos); + if(snap_info != null){ + if(snap_info.x != null) { + x_pos = snap_info.x; + } + if(snap_info.y != null) { + y_pos = snap_info.y; + } + } + //register new object - current layer is not ours or params changed this.layer = { type: this.name, params: this.clone(this.getParams()), render_function: [this.name, 'render'], status: 'draft', - x: mouse.x, - y: mouse.y, + x: x_pos, + y: y_pos, is_vector: true, color: null, data: { @@ -76,6 +92,18 @@ class Ellipse_class extends Base_tools_class { config.layer.y = this.layer.data.center_y - height; config.layer.width = width * 2; config.layer.height = height * 2; + + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + config.layer.width = snap_info.width; + } + if(snap_info.height != null) { + config.layer.height = snap_info.height; + } + } + this.Base_layers.render(); } @@ -106,19 +134,42 @@ class Ellipse_class extends Base_tools_class { return; } + var new_x = Math.round(this.layer.data.center_x - width); + var new_y = Math.round(this.layer.data.center_y - height); + + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + width = snap_info.width / 2; + } + if(snap_info.height != null) { + height = snap_info.height / 2; + } + } + this.snap_line_info = {x: null, y: null}; + + width = width * 2; + height = height * 2; + //more data app.State.do_action( new app.Actions.Update_layer_action(config.layer.id, { - x: this.layer.data.center_x - width, - y: this.layer.data.center_y - height, - width: width * 2, - height: height * 2, + x: new_x, + y: new_y, + width: width, + height: height, status: null }), { merge_with_history: 'new_ellipse_layer' } ); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { x = parseInt(x); y = parseInt(y); diff --git a/src/js/tools/shapes/heart.js b/src/js/tools/shapes/heart.js index 2ec5069..bfb744d 100644 --- a/src/js/tools/shapes/heart.js +++ b/src/js/tools/shapes/heart.js @@ -12,6 +12,7 @@ class Heart_class extends Base_tools_class { this.name = 'heart'; this.layer = {}; this.best_ratio = 1.2; + this.snap_line_info = {x: null, y: null}; } load() { @@ -30,6 +31,11 @@ class Heart_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { ctx.fillStyle = '#aaa'; ctx.strokeStyle = '#555'; diff --git a/src/js/tools/shapes/hexagon.js b/src/js/tools/shapes/hexagon.js index 3437949..ead2442 100644 --- a/src/js/tools/shapes/hexagon.js +++ b/src/js/tools/shapes/hexagon.js @@ -12,6 +12,7 @@ class Hexagon_class extends Base_tools_class { this.name = 'hexagon'; this.layer = {}; this.best_ratio = 1.1547005; + this.snap_line_info = {x: null, y: null}; this.coords = [ [75, 6.698729810778069], [100, 50], @@ -40,6 +41,11 @@ class Hexagon_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { ctx.fillStyle = '#aaa'; ctx.strokeStyle = '#555'; diff --git a/src/js/tools/shapes/human.js b/src/js/tools/shapes/human.js index 49f83ed..07a2653 100644 --- a/src/js/tools/shapes/human.js +++ b/src/js/tools/shapes/human.js @@ -12,6 +12,7 @@ class Human_class extends Base_tools_class { this.name = 'human'; this.layer = {}; this.best_ratio = 0.35; + this.snap_line_info = {x: null, y: null}; } load() { @@ -30,6 +31,11 @@ class Human_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { ctx.fillStyle = '#aaa'; ctx.strokeStyle = '#555'; diff --git a/src/js/tools/shapes/line.js b/src/js/tools/shapes/line.js index a8909e2..f8dc7c2 100644 --- a/src/js/tools/shapes/line.js +++ b/src/js/tools/shapes/line.js @@ -11,6 +11,8 @@ class Line_class extends Base_tools_class { this.ctx = ctx; this.name = 'line'; this.layer = {}; + this.best_ratio = 1; + this.snap_line_info = {x: null, y: null}; } load() { @@ -22,14 +24,28 @@ class Line_class extends Base_tools_class { if (mouse.valid == false || mouse.click_valid == false) return; + var x_pos = mouse.x; + var y_pos = mouse.y; + + //apply snap + var snap_info = this.calc_snap_initial(e, x_pos, y_pos); + if(snap_info != null){ + if(snap_info.x != null) { + x_pos = snap_info.x; + } + if(snap_info.y != null) { + y_pos = snap_info.y; + } + } + //register new object - current layer is not ours or params changed this.layer = { type: this.name, params: this.clone(this.getParams()), status: 'draft', render_function: [this.name, 'render'], - x: mouse.x, - y: mouse.y, + x: x_pos, + y: y_pos, rotate: null, is_vector: true, color: config.COLOR @@ -62,6 +78,18 @@ class Line_class extends Base_tools_class { //more data config.layer.width = width; config.layer.height = height; + + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + config.layer.width = snap_info.width; + } + if(snap_info.height != null) { + config.layer.height = snap_info.height; + } + } + this.Base_layers.render(); } @@ -89,6 +117,18 @@ class Line_class extends Base_tools_class { height = 0; } + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null){ + if(snap_info.width != null) { + width = snap_info.width; + } + if(snap_info.height != null) { + height = snap_info.height; + } + } + this.snap_line_info = {x: null, y: null}; + //more data app.State.do_action( new app.Actions.Update_layer_action(config.layer.id, { @@ -100,6 +140,11 @@ class Line_class extends Base_tools_class { ); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { var coords = [ [0, 0], diff --git a/src/js/tools/shapes/parallelogram.js b/src/js/tools/shapes/parallelogram.js index 4cd1c72..5ab9258 100644 --- a/src/js/tools/shapes/parallelogram.js +++ b/src/js/tools/shapes/parallelogram.js @@ -12,6 +12,7 @@ class Parallelogram_class extends Base_tools_class { this.name = 'parallelogram'; this.layer = {}; this.best_ratio = 2; + this.snap_line_info = {x: null, y: null}; this.coords = [ [25, 0], [100, 0], @@ -37,6 +38,11 @@ class Parallelogram_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { this.draw_shape(ctx, x, y, width, height, this.coords); } diff --git a/src/js/tools/shapes/pentagon.js b/src/js/tools/shapes/pentagon.js index 91df395..56e8047 100644 --- a/src/js/tools/shapes/pentagon.js +++ b/src/js/tools/shapes/pentagon.js @@ -12,6 +12,7 @@ class Pentagon_class extends Base_tools_class { this.name = 'pentagon'; this.layer = {}; this.best_ratio = 1.051; + this.snap_line_info = {x: null, y: null}; this.coords = [ [100.40599536364314, 38.90073974812779], [81.15261837150108, 98.1565411518722], @@ -39,6 +40,11 @@ class Pentagon_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { ctx.fillStyle = '#aaa'; ctx.strokeStyle = '#555'; diff --git a/src/js/tools/shapes/plus.js b/src/js/tools/shapes/plus.js index a6753d7..e238ee4 100644 --- a/src/js/tools/shapes/plus.js +++ b/src/js/tools/shapes/plus.js @@ -14,6 +14,7 @@ class Plus_class extends Base_tools_class { this.name = 'plus'; this.layer = {}; this.best_ratio = 1; + this.snap_line_info = {x: null, y: null}; this.coords = [ [35, 0], [65, 0], @@ -47,6 +48,11 @@ class Plus_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { this.draw_shape(ctx, x, y, width, height, this.coords); } diff --git a/src/js/tools/shapes/rectangle.js b/src/js/tools/shapes/rectangle.js index 72d01d8..e0ee06f 100644 --- a/src/js/tools/shapes/rectangle.js +++ b/src/js/tools/shapes/rectangle.js @@ -11,6 +11,8 @@ class Rectangle_class extends Base_tools_class { this.ctx = ctx; this.name = 'rectangle'; this.layer = {}; + this.best_ratio = 1; + this.snap_line_info = {x: null, y: null}; } load() { @@ -22,14 +24,28 @@ class Rectangle_class extends Base_tools_class { if (mouse.valid == false || mouse.click_valid == false) return; + var x_pos = mouse.x; + var y_pos = mouse.y; + + //apply snap + var snap_info = this.calc_snap_initial(e, x_pos, y_pos); + if(snap_info != null){ + if(snap_info.x != null) { + x_pos = snap_info.x; + } + if(snap_info.y != null) { + y_pos = snap_info.y; + } + } + //register new object - current layer is not ours or params changed this.layer = { type: this.name, params: this.clone(this.getParams()), status: 'draft', render_function: [this.name, 'render'], - x: Math.round(mouse.x), - y: Math.round(mouse.y), + x: Math.round(x_pos), + y: Math.round(y_pos), color: null, is_vector: true }; @@ -62,7 +78,8 @@ class Rectangle_class extends Base_tools_class { if (params.square == true || e.ctrlKey == true || e.metaKey) { if (width < height) { width = height; - } else { + } + else { height = width; } if (mouse_x < click_x) { @@ -78,6 +95,21 @@ class Rectangle_class extends Base_tools_class { config.layer.y = y; config.layer.width = width; config.layer.height = height; + + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null && params.square == false){ + if(snap_info.width != null) { + config.layer.width = snap_info.width; + } + if(snap_info.height != null) { + config.layer.height = snap_info.height; + } + } + else{ + this.snap_line_info = {x: null, y: null}; + } + this.Base_layers.render(); } @@ -102,7 +134,8 @@ class Rectangle_class extends Base_tools_class { if (params.square == true || e.ctrlKey == true || e.metaKey) { if (width < height) { width = height; - } else { + } + else { height = width; } if (mouse_x < click_x) { @@ -119,6 +152,18 @@ class Rectangle_class extends Base_tools_class { return; } + //apply snap + var snap_info = this.calc_snap_end(e); + if(snap_info != null && params.square == false){ + if(snap_info.width != null) { + width = snap_info.width; + } + if(snap_info.height != null) { + height = snap_info.height; + } + } + this.snap_line_info = {x: null, y: null}; + //more data app.State.do_action( new app.Actions.Update_layer_action(config.layer.id, { @@ -132,6 +177,11 @@ class Rectangle_class extends Base_tools_class { ); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { var coords = [ [0, 0], @@ -213,15 +263,15 @@ class Rectangle_class extends Base_tools_class { radius = Math.floor(radius); // Odd dimensions must draw offset half a pixel - if (width % 2 == 1) { + if (width % 2 == 1 && config.layer.status != 'draft') { x -= 0.5; } - if (height % 2 == 1) { + if (height % 2 == 1 && config.layer.status != 'draft') { y -= 0.5; } var stroke_offset = !fill && ctx.lineWidth % 2 == 1 && width > 1 && height > 1 ? 0.5 : 0; - + if (smaller_dimension < 2) fill = true; radius = {tl: radius, tr: radius, br: radius, bl: radius}; diff --git a/src/js/tools/shapes/right_triangle.js b/src/js/tools/shapes/right_triangle.js index 7e49280..de85a81 100644 --- a/src/js/tools/shapes/right_triangle.js +++ b/src/js/tools/shapes/right_triangle.js @@ -12,6 +12,7 @@ class Right_Triangle_class extends Base_tools_class { this.name = 'right_triangle'; this.layer = {}; this.best_ratio = 1; + this.snap_line_info = {x: null, y: null}; this.coords = [ [0, 0], [100, 100], @@ -36,6 +37,11 @@ class Right_Triangle_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { this.draw_shape(ctx, x, y, width, height, this.coords); } diff --git a/src/js/tools/shapes/romb.js b/src/js/tools/shapes/romb.js index 5a9bc4b..7b92e9d 100644 --- a/src/js/tools/shapes/romb.js +++ b/src/js/tools/shapes/romb.js @@ -12,6 +12,7 @@ class Romb_class extends Base_tools_class { this.name = 'romb'; this.layer = {}; this.best_ratio = 0.8; + this.snap_line_info = {x: null, y: null}; this.coords_demo = [ [50, 0], [80, 50], @@ -44,6 +45,11 @@ class Romb_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { this.draw_shape(ctx, x, y, width, height, this.coords_demo); } diff --git a/src/js/tools/shapes/star.js b/src/js/tools/shapes/star.js index 84927d3..9adbdbe 100644 --- a/src/js/tools/shapes/star.js +++ b/src/js/tools/shapes/star.js @@ -13,6 +13,7 @@ class Star_class extends Base_tools_class { this.layer = {}; this.best_ratio = 1.051; this.coords = []; + this.snap_line_info = {x: null, y: null}; } load() { @@ -32,6 +33,11 @@ class Star_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + generate_coords() { //settings var spikes = 5; diff --git a/src/js/tools/shapes/star24.js b/src/js/tools/shapes/star24.js index 3c2b63b..53a57fd 100644 --- a/src/js/tools/shapes/star24.js +++ b/src/js/tools/shapes/star24.js @@ -13,6 +13,7 @@ class Star24_class extends Base_tools_class { this.layer = {}; this.best_ratio = 1; this.coords = []; + this.snap_line_info = {x: null, y: null}; } load() { @@ -32,6 +33,11 @@ class Star24_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + generate_coords() { //settings var spikes = 24; diff --git a/src/js/tools/shapes/trapezoid.js b/src/js/tools/shapes/trapezoid.js index e01e8fc..cbb04e8 100644 --- a/src/js/tools/shapes/trapezoid.js +++ b/src/js/tools/shapes/trapezoid.js @@ -12,6 +12,7 @@ class Trapezoid_class extends Base_tools_class { this.name = 'trapezoid'; this.layer = {}; this.best_ratio = 2; + this.snap_line_info = {x: null, y: null}; this.coords = [ [20, 0], [80, 0], @@ -37,6 +38,11 @@ class Trapezoid_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { this.draw_shape(ctx, x, y, width, height, this.coords); } diff --git a/src/js/tools/shapes/triangle.js b/src/js/tools/shapes/triangle.js index ac16a7b..deef4ca 100644 --- a/src/js/tools/shapes/triangle.js +++ b/src/js/tools/shapes/triangle.js @@ -12,6 +12,7 @@ class Triangle_class extends Base_tools_class { this.name = 'triangle'; this.layer = {}; this.best_ratio = 2 / Math.sqrt(3); + this.snap_line_info = {x: null, y: null}; this.coords = [ [50, 0], [100, 100], @@ -36,6 +37,11 @@ class Triangle_class extends Base_tools_class { this.shape_mouseup(e); } + render_overlay(ctx){ + var ctx = this.Base_layers.ctx; + this.render_overlay_parent(ctx); + } + demo(ctx, x, y, width, height) { this.draw_shape(ctx, x, y, width, height, this.coords); }