I am creating a drawing-app. I want to have a toolbar populated with tools. Each tool is defined in a separate js file. Right now i have defined each tool as an object that contains functions and variables that dictate it's behavior, for example i have 'setDragBehaviour()' and setDrawBehaviour()'.
All these functions interact with variables in the global scope such as the Canvas and an Array containing all objects on the Canvas. This is very messy, as i have to reference 'this' in some of the functions to call other class functions\variables, but at the same time i bind these object functions to the canvas with events and such. It feels like a big Spaghetti.
Do you have any tips or general direction for a better more maintainable design, maybe a suggested pattern ? Here is my code :
var tool_rectangle = {
name : 'Rectangle',
setDragBehavior : function(element) {
var start = function() {
this.ox = this.attr("x");
this.oy = this.attr("y");
this.dx = 0
this.dy = 0
in_drag = true;
},
move = function(dx, dy) {
mx = (parseInt(dx) - parseInt(this.dx)),
my = (parseInt(dy) - parseInt(this.dy))
var att = {
x: mx,
y: my
}
this.attr(att);
},
stop = function(){
in_drag = false;
};
element.drag(move,start,stop)
},
creation : function(e,tags){
//NEW ELEMENT CREATED
if(tags==null)
{
x = e.offsetX
y = e.offsetY
size = 100
initial_element = s.rect(x-size/2,y-size/2,size,size).attr({fill:"#000",
"fill-opacity": 0.25, stroke:"#ff0000", strokeWidth:2});
}else{// LOAD EXISTING ELEMENT
initial_element = s.rect(tags);
}
return initial_element;
},
initial : function (e,tags){
initial_element = this.creation(e,tags);
initial_element.click(this.mount.bind(initial_element,this));
initial_element.drag(move.bind(initial_element), start.bind(initial_element));
elements.add(initial_element);
},
mount : function(tool){
React.unmountComponentAtNode(document.getElementById('options_mount_point'));
React.render(<tool.component svg={this}/>,
document.getElementById("options_mount_point"));
},
// RECTANGLE TAG TOOL > PROPERTIES PANEL
component : React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function(){
snap = this.props.svg
stroke = snap.attr('stroke')
fill = snap.attr('fill')
fill_opacity = snap.attr('fill-opacity')
strokeWidth = snap.attr('strokeWidth')
x = snap.attr('x')
y = snap.attr('y')
return {'x':x, 'y':y, 'stroke': stroke, 'fill':fill, 'fill-opacity':fill_opacity, 'strokeWidth':strokeWidth, 'svg':snap}
},
componentDidUpdate: function(prevProps, prevState){
//After changing the values in the properties we must update the SVG object itself.
//Updates Snap.svg component with new attrs
this.state.svg.attr(this.state);
},
render : function(){
return (
<div>
<b>Rectangle Properties</b><br/>
<label for="stroke_color">Stroke Color:</label>
<input type="text" id="stroke_color" valueLink={this.linkState("stroke")} placeholder="Stroke color"></input><br/>
<label for="fill_color">Fill Color:</label>
<input type="text" id="fill_color" valueLink={this.linkState("fill")} placeholder="Fill color"></input><br/>
<label for="fill_opacity">Fill Opacity:</label>
<input type="float" id="fill_opacity" valueLink={this.linkState("fill-opacity")} placeholder="Fill opacity"></input><br/>
<label for="stroke_width">Stroke width:</label>
<input type="text" id="stroke_width" valueLink={this.linkState("strokeWidth")} placeholder="Stroke width"></input><br/>
<label for="fill_opacity">X:</label><br/>
<input type="float" id="x" valueLink={this.linkState("x")} placeholder="X"></input><br/>
<label for="stroke_width">Y:</label><br/>
<input type="text" id="y" valueLink={this.linkState("y")} placeholder="Y"></input><br/>
</div>
);
},
})
}// END OF TOOL
Aucun commentaire:
Enregistrer un commentaire