1 madrona.graphics = (function(){
  2     
  3     var ScaleBar = function(opts){
  4         // var s = "M"+opts.origin[0]+' '+opts.origin[1]+'L'+opts.origin[0] + opts.width+' '+opts.origin[1];
  5         // opts.paper.path(s);
  6         this.opts = opts;
  7         // Setup major ticks
  8         this.tics = [];
  9         var baseline = opts.origin[1] - 16;
 10         var position = opts.origin[0];
 11         var end = position + opts.width;
 12         var value = 0;
 13         // major tics
 14         while(value <= opts.maxValue){
 15             this.tics.push(
 16                 new Tic(value, position, opts.paper, opts.ticHeight, baseline, opts.color, true)
 17             );
 18             var value = value + opts.majorInterval;
 19             var position = this.calculateXPosition(value, opts.width, opts.maxValue, opts.origin[0]);
 20         }
 21         
 22         // Setup minor ticks
 23         var position = opts.origin[0];
 24         var end = position + opts.width;
 25         var value = 0;
 26         var height = opts.ticHeight / 2;
 27         var b = baseline - (height / 2);
 28         while(value <= opts.maxValue){
 29             if(value % opts.majorInterval !== 0){
 30                 this.tics.push(
 31                     new Tic(value, position, opts.paper, height, b, opts.color, false)
 32                 );
 33             }
 34             var value = value + opts.minorInterval;
 35             var position = this.calculateXPosition(value, opts.width, opts.maxValue, opts.origin[0])
 36         }
 37         this.maxValue = opts.maxValue;
 38         if(opts.initialMaxValue){
 39             this.update(opts.initialMaxValue, false);
 40         }
 41         if(opts.label){
 42             this.label = opts.paper.text(opts.origin[0] + (opts.width / 2), opts.origin[1] + 15, opts.label);
 43         }
 44     };
 45     
 46     ScaleBar.prototype.calculateXPosition = function(value, width, maxValue, originX){
 47         return Math.round(((value / maxValue) * width) + originX);
 48     };
 49     
 50     ScaleBar.prototype.update = function(maxValue, animate){
 51         var ticZero = this.tics[0];
 52         var x = this.calculateXPosition(ticZero.value, this.opts.width, maxValue, this.opts.origin[0]);
 53         if(animate){
 54             ticZero.changePosition(x, true, this.opts.animationEasing, this.opts.animationDuration);
 55         }else{
 56             ticZero.changePosition(x, false);
 57         }
 58         for(var i=1;i<this.tics.length;i++){
 59             var tic = this.tics[i];
 60             var x = this.calculateXPosition(tic.value, this.opts.width, maxValue, this.opts.origin[0]);
 61             if(animate){
 62                 tic.changePosition(x, true, this.opts.animationEasing, this.opts.animationDuration, ticZero);
 63             }else{
 64                 tic.changePosition(x, false);
 65             }
 66         }
 67         this.maxValue = maxValue;
 68         // returns an animation target for additional animateWith calls
 69         return ticZero.path;
 70     };
 71     
 72     ScaleBar.prototype.changeY = function(y, target, easing, duration){
 73         for(var i=0; i<this.tics.length;i++){
 74             var el = this.tics[i].changeY(y, easing, duration, target);
 75             if(!target){
 76                 target = el;
 77             }
 78         }
 79         if(this.label){
 80             this.label.anim({
 81                 attrs: {y: this.label.attr('y') + y},
 82                 easing: easing,
 83                 ms: duration,
 84                 target: target
 85             });
 86         }
 87     }
 88     
 89     var Tic = function(value, initial_position, paper, ticHeight, origin, color, showValue){
 90         this.y1 = (origin);
 91         this.y2 = ((origin-ticHeight));
 92         this.x = initial_position;
 93         this.path = paper.path(
 94             "M"+this.x+' '+this.y1+'L'+this.x+' '+this.y2
 95         );
 96         this.path.attr({'stroke': color});
 97         if(showValue){
 98             this.tx = initial_position;
 99             this.ty = origin + 10;
100             this.t = paper.text(this.tx, this.ty, String(value));
101             this.t.attr({'fill': color});
102         }
103         this.initial_position = initial_position;
104         this.value = value;
105         this.paper = paper;
106     };
107     
108     Tic.prototype.changePosition = function(x, animate, animationEasing, animationDuration, animationTarget){
109         this.x = x;
110         var new_path = 'M'+ this.x + ' ' + this.y1 + 'L' + this.x + ' ' + this.y2;
111         if(!animate){
112             this.path.attr('path', new_path);
113         }else{
114             this.path.anim({
115                 attrs: {path: new_path},
116                 ms: animationDuration,
117                 easing: animationEasing,
118                 target: animationTarget
119             });
120         }
121         if(this.t){
122             this.tx = x;
123             if(!animate){
124                 this.t.attr('x', this.tx);
125             }else{
126                 this.t.anim({
127                     attrs: {x: this.tx, y: this.ty},
128                     ms: animationDuration,
129                     easing: animationEasing,
130                     target: animationTarget
131                 });
132             }
133         }
134     };
135     
136     Tic.prototype.changeY = function(y, easing, duration, target){
137         this.y1 = this.y1 + y;
138         this.y2 = this.y2 + y;
139         var new_path = 'M'+ this.x + ' ' + this.y1  + 'L' + this.x + ' ' + this.y2;
140         this.path.anim({
141             attrs: {path: new_path},
142             ms: duration,
143             easing: easing,
144             target: target
145         });
146         if(!target){
147             target = this.path;
148         }
149         if(this.t){
150             this.ty = this.ty + y;
151             this.t.anim({
152                 attrs: {y: this.ty},
153                 ms: duration,
154                 easing: easing,
155                 target: target           
156             });
157         }
158         return target;
159     }
160     
161     var that = {};
162     
163     that.ScaleBar = ScaleBar;
164 
165     return that;
166 })();