1 | package elements.axis {
|
---|
2 | import flash.display.Sprite;
|
---|
3 | import string.Utils;
|
---|
4 |
|
---|
5 | public class YAxisBase extends Sprite {
|
---|
6 |
|
---|
7 | protected var stroke:Number;
|
---|
8 | protected var tick_length:Number;
|
---|
9 | protected var colour:Number;
|
---|
10 | protected var grid_colour:Number;
|
---|
11 |
|
---|
12 | public var style:Object;
|
---|
13 |
|
---|
14 | protected var labels:YAxisLabelsBase;
|
---|
15 | private var user_labels:Array;
|
---|
16 | private var user_ticks:Boolean;
|
---|
17 |
|
---|
18 | function YAxisBase() {}
|
---|
19 |
|
---|
20 | public function init(json:Object): void {}
|
---|
21 |
|
---|
22 | // called once the sprite has been added to the stage
|
---|
23 | // so now it has access to the stage
|
---|
24 | protected function _init(json:Object, name:String, style:Object): void {
|
---|
25 |
|
---|
26 | this.style = style;
|
---|
27 |
|
---|
28 | if( json[name] )
|
---|
29 | object_helper.merge_2( json[name], this.style );
|
---|
30 |
|
---|
31 |
|
---|
32 | this.colour = Utils.get_colour( style.colour );
|
---|
33 | this.grid_colour = Utils.get_colour( style['grid-colour'] );
|
---|
34 | this.stroke = style.stroke;
|
---|
35 | this.tick_length = style['tick-length'];
|
---|
36 |
|
---|
37 | tr.aces('YAxisBase auto', this.auto_range( 50001 ));
|
---|
38 | tr.aces('YAxisBase min, max', this.style.min, this.style.max);
|
---|
39 |
|
---|
40 |
|
---|
41 | if ( this.style.max == null ) {
|
---|
42 | // we have labels, so use the number of
|
---|
43 | // labels as Y MAX
|
---|
44 | this.style.max = this.labels.y_max;
|
---|
45 | }
|
---|
46 | // make sure we don't have 1,000,000 steps
|
---|
47 | var min:Number = Math.min(this.style.min, this.style.max);
|
---|
48 | var max:Number = Math.max(this.style.min, this.style.max);
|
---|
49 | this.style.steps = this.get_steps(min, max, this.stage.stageHeight);
|
---|
50 |
|
---|
51 | if ( this.labels.i_need_labels )
|
---|
52 | this.labels.make_labels(min, max, this.style.steps);
|
---|
53 |
|
---|
54 | //
|
---|
55 | // colour the grid lines
|
---|
56 | //
|
---|
57 | // TODO: remove this and
|
---|
58 | // this.user_ticks
|
---|
59 | // this.user_labels
|
---|
60 | //
|
---|
61 | if ((this.style.labels != null) &&
|
---|
62 | (this.style.labels.labels != null) &&
|
---|
63 | (this.style.labels.labels is Array) &&
|
---|
64 | (this.style.labels.labels.length > 0))
|
---|
65 | {
|
---|
66 | this.user_labels = new Array();
|
---|
67 | for each( var lbl:Object in this.style.labels.labels )
|
---|
68 | {
|
---|
69 | if (!(lbl is String)) {
|
---|
70 | if (lbl.y != null)
|
---|
71 | {
|
---|
72 | var tmpObj:Object = { y: lbl.y };
|
---|
73 | if (lbl["grid-colour"])
|
---|
74 | {
|
---|
75 | tmpObj["grid-colour"] = Utils.get_colour(lbl["grid-colour"]);
|
---|
76 | }
|
---|
77 | else
|
---|
78 | {
|
---|
79 | tmpObj["grid-colour"] = this.grid_colour;
|
---|
80 | }
|
---|
81 |
|
---|
82 | this.user_ticks = true;
|
---|
83 | this.user_labels.push(tmpObj);
|
---|
84 | }
|
---|
85 | }
|
---|
86 | }
|
---|
87 | }
|
---|
88 | }
|
---|
89 |
|
---|
90 | public function auto_range(max:Number): Number {
|
---|
91 |
|
---|
92 | var maxValue:Number = Math.max(max) * 1.07;
|
---|
93 | var l:Number = Math.round(Math.log(maxValue)/Math.log(10));
|
---|
94 | var p:Number = Math.pow(10, l) / 2;
|
---|
95 | maxValue = Math.round((maxValue * 1.1) / p) * p;
|
---|
96 | return maxValue;
|
---|
97 |
|
---|
98 |
|
---|
99 | /*
|
---|
100 | var maxValue:Number = Math.max($bar_1->data) * 1.07;
|
---|
101 | $l = round(log($maxValue)/log(10));
|
---|
102 | $p = pow(10, $l) / 2;
|
---|
103 | $maxValue = round($maxValue * 1.1 / $p) * $p;
|
---|
104 | */
|
---|
105 |
|
---|
106 | /*
|
---|
107 | * http://forums.openflashchart.com/viewtopic.php?f=5&t=617&start=0
|
---|
108 | * cdcarson
|
---|
109 | // y axis data...
|
---|
110 | $counts = array_values($data);
|
---|
111 | $ymax = max($counts);
|
---|
112 | // add a bit of padding to the top, not strictly necessary...
|
---|
113 | $ymax += ceil(.1 * $ymax);
|
---|
114 | //$max_steps could be anything,depending on the height of the chart, font-size, etc..
|
---|
115 | $max_steps = 10;
|
---|
116 | /**
|
---|
117 | * The step sizes to test are created using an
|
---|
118 | * array of multipliers and a power of 10, starting at 0.
|
---|
119 | * $step_size = $multiplier * pow(10, $exponent);
|
---|
120 | * Assuming $multipliers = array(1, 2, 5) this would give us...
|
---|
121 | * 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000,...
|
---|
122 | * /
|
---|
123 | $n = 0;
|
---|
124 | $multipliers = array(1, 2, 5);
|
---|
125 | $num_multipliers = count($multipliers);
|
---|
126 | $exponent = floor($n / $num_multipliers);
|
---|
127 | $multiplier = $multipliers[$n % $num_multipliers];
|
---|
128 | $step_size = $multiplier * pow(10, $exponent);
|
---|
129 | $num_steps = ceil($ymax/$step_size);
|
---|
130 | //keep testing until we have the right step_size...
|
---|
131 | while ($num_steps >= $max_steps){
|
---|
132 | $n ++;
|
---|
133 | $exponent = floor($n / $num_multipliers);
|
---|
134 | $multiplier = $multipliers[$n % $num_multipliers];
|
---|
135 | $step_size = $multiplier * pow(10, $exponent);
|
---|
136 | $num_steps = ceil($ymax/$step_size);
|
---|
137 | }
|
---|
138 | $yaxis = new y_axis();
|
---|
139 | $yaxis->set_range(0, $ymax, $step_size);
|
---|
140 |
|
---|
141 | */
|
---|
142 |
|
---|
143 | }
|
---|
144 |
|
---|
145 | public function get_style():Object { return null; }
|
---|
146 |
|
---|
147 | //
|
---|
148 | // may be called by the labels
|
---|
149 | //
|
---|
150 | public function set_y_max( m:Number ):void {
|
---|
151 | this.style.max = m;
|
---|
152 | }
|
---|
153 |
|
---|
154 | public function get_range():Range {
|
---|
155 | return new Range( this.style.min, this.style.max, this.style.steps, this.style.offset );
|
---|
156 | }
|
---|
157 |
|
---|
158 | public function get_width():Number {
|
---|
159 | return this.stroke + this.tick_length + this.labels.width;
|
---|
160 | }
|
---|
161 |
|
---|
162 | public function die(): void {
|
---|
163 |
|
---|
164 | //this.offset = null;
|
---|
165 | this.style = null;
|
---|
166 | if (this.labels != null) this.labels.die();
|
---|
167 | this.labels = null;
|
---|
168 |
|
---|
169 | this.graphics.clear();
|
---|
170 | while ( this.numChildren > 0 )
|
---|
171 | this.removeChildAt(0);
|
---|
172 | }
|
---|
173 |
|
---|
174 | private function get_steps(min:Number, max:Number, height:Number):Number {
|
---|
175 | // try to avoid infinite loops...
|
---|
176 | if ( this.style.steps == 0 )
|
---|
177 | this.style.steps = 1;
|
---|
178 |
|
---|
179 | if ( this.style.steps < 0 )
|
---|
180 | this.style.steps *= -1;
|
---|
181 |
|
---|
182 | // how many steps (grid lines) do we have?
|
---|
183 | var s:Number = (max - min) / this.style.steps;
|
---|
184 |
|
---|
185 | if ( s > (height/2) ) {
|
---|
186 | // either no steps are set, or they are wrong and
|
---|
187 | // we have more grid lines than pixels to show them.
|
---|
188 | // E.g:
|
---|
189 | // max = 1,001,000
|
---|
190 | // min = 1,000
|
---|
191 | // s = 200,000
|
---|
192 | return (max - min) / 5;
|
---|
193 | }
|
---|
194 |
|
---|
195 | return this.style.steps;
|
---|
196 | }
|
---|
197 |
|
---|
198 | public function resize(label_pos:Number, sc:ScreenCoords):void { }
|
---|
199 |
|
---|
200 | protected function resize_helper(label_pos:Number, sc:ScreenCoords, right:Boolean):void {
|
---|
201 |
|
---|
202 | // Set opacity for the first line to 0 (otherwise it overlaps the x-axel line)
|
---|
203 | //
|
---|
204 | // Bug? Does this work on graphs with minus values?
|
---|
205 | //
|
---|
206 | var i2:Number = 0;
|
---|
207 | var i:Number;
|
---|
208 | var y:Number;
|
---|
209 | var lbl:Object;
|
---|
210 |
|
---|
211 | var min:Number = Math.min(this.style.min, this.style.max);
|
---|
212 | var max:Number = Math.max(this.style.min, this.style.max);
|
---|
213 |
|
---|
214 | if( !right )
|
---|
215 | this.labels.resize( label_pos, sc );
|
---|
216 | else
|
---|
217 | this.labels.resize( sc.right + this.stroke + this.tick_length, sc );
|
---|
218 |
|
---|
219 | if ( !this.style.visible )
|
---|
220 | return;
|
---|
221 |
|
---|
222 | this.graphics.clear();
|
---|
223 | this.graphics.lineStyle( 0, 0, 0 );
|
---|
224 |
|
---|
225 | if ( this.style['grid-visible'] )
|
---|
226 | this.draw_grid_lines(this.style.steps, min, max, right, sc);
|
---|
227 |
|
---|
228 | var pos:Number;
|
---|
229 |
|
---|
230 | if (!right)
|
---|
231 | pos = sc.left - this.stroke;
|
---|
232 | else
|
---|
233 | pos = sc.right;
|
---|
234 |
|
---|
235 | // Axis line:
|
---|
236 | this.graphics.beginFill( this.colour, 1 );
|
---|
237 | this.graphics.drawRect(
|
---|
238 | int(pos), // <-- pixel align
|
---|
239 | sc.top,
|
---|
240 | this.stroke,
|
---|
241 | sc.height );
|
---|
242 | this.graphics.endFill();
|
---|
243 |
|
---|
244 | // ticks..
|
---|
245 | var width:Number;
|
---|
246 | if (this.user_ticks)
|
---|
247 | {
|
---|
248 | for each( lbl in this.user_labels )
|
---|
249 | {
|
---|
250 | y = sc.get_y_from_val(lbl.y, right);
|
---|
251 |
|
---|
252 | if ( !right )
|
---|
253 | tick_pos = sc.left - this.stroke - this.tick_length;
|
---|
254 | else
|
---|
255 | tick_pos = sc.right + this.stroke;
|
---|
256 |
|
---|
257 | this.graphics.beginFill( this.colour, 1 );
|
---|
258 | this.graphics.drawRect( tick_pos, y - (this.stroke / 2), this.tick_length, this.stroke );
|
---|
259 | this.graphics.endFill();
|
---|
260 | }
|
---|
261 | }
|
---|
262 | else
|
---|
263 | {
|
---|
264 | for(i=min; i<=max; i+=this.style.steps) {
|
---|
265 |
|
---|
266 | // start at the bottom and work up:
|
---|
267 | y = sc.get_y_from_val(i, right);
|
---|
268 |
|
---|
269 | var tick_pos:Number;
|
---|
270 | if ( !right )
|
---|
271 | tick_pos = sc.left - this.stroke - this.tick_length;
|
---|
272 | else
|
---|
273 | tick_pos = sc.right + this.stroke;
|
---|
274 |
|
---|
275 | this.graphics.beginFill( this.colour, 1 );
|
---|
276 | this.graphics.drawRect( tick_pos, y - (this.stroke / 2), this.tick_length, this.stroke );
|
---|
277 | this.graphics.endFill();
|
---|
278 | }
|
---|
279 | }
|
---|
280 | }
|
---|
281 |
|
---|
282 | private function draw_grid_lines(steps:Number, min:Number, max:Number, right:Boolean, sc:ScreenCoords): void {
|
---|
283 |
|
---|
284 | var y:Number;
|
---|
285 | var lbl:Object;
|
---|
286 | //
|
---|
287 | // draw GRID lines
|
---|
288 | //
|
---|
289 | if (this.user_ticks)
|
---|
290 | {
|
---|
291 | for each(lbl in this.user_labels )
|
---|
292 | {
|
---|
293 | y = sc.get_y_from_val(lbl.y, right);
|
---|
294 | this.graphics.beginFill(lbl["grid-colour"], 1);
|
---|
295 | this.graphics.drawRect( sc.left, y, sc.width, 1 );
|
---|
296 | this.graphics.endFill();
|
---|
297 | }
|
---|
298 | }
|
---|
299 | else
|
---|
300 | {
|
---|
301 | //
|
---|
302 | // hack: http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_13989&sliceId=1
|
---|
303 | //
|
---|
304 | max += 0.000004;
|
---|
305 |
|
---|
306 | for( var i:Number = min; i<=max; i+=steps ) {
|
---|
307 |
|
---|
308 | y = sc.get_y_from_val(i, right);
|
---|
309 | this.graphics.beginFill( this.grid_colour, 1 );
|
---|
310 | this.graphics.drawRect(
|
---|
311 | int(sc.left),
|
---|
312 | int(y), // <-- make sure they are pixel aligned (2.5 - 3.5 == fuzzy lines)
|
---|
313 | sc.width,
|
---|
314 | 1 );
|
---|
315 | this.graphics.endFill();
|
---|
316 | }
|
---|
317 | }
|
---|
318 | }
|
---|
319 | }
|
---|
320 | }
|
---|