source: Dev/trunk/src/client/dojox/charting/plot2d/Columns.js @ 485

Last change on this file since 485 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 7.6 KB
Line 
1define(["dojo/_base/lang", "dojo/_base/array", "dojo/_base/declare", "dojo/has", "./CartesianBase", "./_PlotEvents", "./common",
2                "dojox/lang/functional", "dojox/lang/functional/reversed", "dojox/lang/utils", "dojox/gfx/fx"],
3        function(lang, arr, declare, has, CartesianBase, _PlotEvents, dc, df, dfr, du, fx){
4
5        var purgeGroup = dfr.lambda("item.purgeGroup()");
6
7        return declare("dojox.charting.plot2d.Columns", [CartesianBase, _PlotEvents], {
8                // summary:
9                //              The plot object representing a column chart (vertical bars).
10                defaultParams: {
11                        gap:    0,              // gap between columns in pixels
12                        animate: null,  // animate bars into place
13                        enableCache: false
14                },
15                optionalParams: {
16                        minBarSize:     1,      // minimal column width in pixels
17                        maxBarSize:     1,      // maximal column width in pixels
18                        // theme component
19                        stroke:         {},
20                        outline:        {},
21                        shadow:         {},
22                        fill:           {},
23                        filter:     {},
24                        styleFunc:  null,
25                        font:           "",
26                        fontColor:      ""
27                },
28
29                constructor: function(chart, kwArgs){
30                        // summary:
31                        //              The constructor for a columns chart.
32                        // chart: dojox/charting/Chart
33                        //              The chart this plot belongs to.
34                        // kwArgs: dojox.charting.plot2d.__BarCtorArgs?
35                        //              An optional keyword arguments object to help define the plot.
36                        this.opt = lang.clone(lang.mixin(this.opt, this.defaultParams));
37                        du.updateWithObject(this.opt, kwArgs);
38                        du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
39                        this.animate = this.opt.animate;
40                },
41
42                getSeriesStats: function(){
43                        // summary:
44                        //              Calculate the min/max on all attached series in both directions.
45                        // returns: Object
46                        //              {hmin, hmax, vmin, vmax} min/max in both directions.
47                        var stats = dc.collectSimpleStats(this.series);
48                        stats.hmin -= 0.5;
49                        stats.hmax += 0.5;
50                        return stats; // Object
51                },
52               
53                createRect: function(run, creator, params){
54                        var rect;
55                        if(this.opt.enableCache && run._rectFreePool.length > 0){
56                                rect = run._rectFreePool.pop();
57                                rect.setShape(params);
58                                // was cleared, add it back
59                                creator.add(rect);
60                        }else{
61                                rect = creator.createRect(params);
62                        }
63                        if(this.opt.enableCache){
64                                run._rectUsePool.push(rect);
65                        }
66                        return rect;
67                },
68
69                render: function(dim, offsets){
70                        // summary:
71                        //              Run the calculations for any axes for this plot.
72                        // dim: Object
73                        //              An object in the form of { width, height }
74                        // offsets: Object
75                        //              An object of the form { l, r, t, b}.
76                        // returns: dojox/charting/plot2d/Columns
77                        //              A reference to this plot for functional chaining.
78                        if(this.zoom && !this.isDataDirty()){
79                                return this.performZoom(dim, offsets);
80                        }
81                        this.resetEvents();
82                        this.dirty = this.isDirty();
83                        var s;
84                        if(this.dirty){
85                                arr.forEach(this.series, purgeGroup);
86                                this._eventSeries = {};
87                                this.cleanGroup();
88                                s = this.getGroup();
89                                df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
90                        }
91                        var t = this.chart.theme,
92                                ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
93                                vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
94                                baseline = Math.max(0, this._vScaler.bounds.lower),
95                                baselineHeight = vt(baseline),
96                                events = this.events();
97                        var bar = this.getBarProperties();
98                       
99                        for(var i = this.series.length - 1; i >= 0; --i){
100                                var run = this.series[i];
101                                if(!this.dirty && !run.dirty){
102                                        t.skip();
103                                        this._reconnectEvents(run.name);
104                                        continue;
105                                }
106                                run.cleanGroup();
107                                if(this.opt.enableCache){
108                                        run._rectFreePool = (run._rectFreePool?run._rectFreePool:[]).concat(run._rectUsePool?run._rectUsePool:[]);
109                                        run._rectUsePool = [];
110                                }
111                                var theme = t.next("column", [this.opt, run]),
112                                        eventSeries = new Array(run.data.length);
113                                s = run.group;
114                                var indexed = arr.some(run.data, function(item){
115                                        return typeof item == "number" || (item && !item.hasOwnProperty("x"));
116                                });
117                                // on indexed charts we can easily just interate from the first visible to the last visible
118                                // data point to save time
119                                var min = indexed?Math.max(0, Math.floor(this._hScaler.bounds.from - 1)):0;
120                                var max = indexed?Math.min(run.data.length, Math.ceil(this._hScaler.bounds.to)):run.data.length;
121                                for(var j = min; j < max; ++j){
122                                        var value = run.data[j];
123                                        if(value != null){
124                                                var val = this.getValue(value, j, i, indexed),
125                                                        vv = vt(val.y),
126                                                        h = Math.abs(vv - baselineHeight),
127                                                        finalTheme,
128                                                        sshape;
129                                               
130                                                if(this.opt.styleFunc || typeof value != "number"){
131                                                        var tMixin = typeof value != "number" ? [value] : [];
132                                                        if(this.opt.styleFunc){
133                                                                tMixin.push(this.opt.styleFunc(value));
134                                                        }
135                                                        finalTheme = t.addMixin(theme, "column", tMixin, true);
136                                                }else{
137                                                        finalTheme = t.post(theme, "column");
138                                                }
139                                               
140                                                if(bar.width >= 1 && h >= 0){
141                                                        var rect = {
142                                                                x: offsets.l + ht(val.x + 0.5) + bar.gap + bar.thickness * i,
143                                                                y: dim.height - offsets.b - (val.y > baseline ? vv : baselineHeight),
144                                                                width: bar.width,
145                                                                height: h
146                                                        };
147                                                        if(finalTheme.series.shadow){
148                                                                var srect = lang.clone(rect);
149                                                                srect.x += finalTheme.series.shadow.dx;
150                                                                srect.y += finalTheme.series.shadow.dy;
151                                                                sshape = this.createRect(run, s, srect).setFill(finalTheme.series.shadow.color).setStroke(finalTheme.series.shadow);
152                                                                if(this.animate){
153                                                                        this._animateColumn(sshape, dim.height - offsets.b + baselineHeight, h);
154                                                                }
155                                                        }
156                                                       
157                                                        var specialFill = this._plotFill(finalTheme.series.fill, dim, offsets);
158                                                        specialFill = this._shapeFill(specialFill, rect);
159                                                        var shape = this.createRect(run, s, rect).setFill(specialFill).setStroke(finalTheme.series.stroke);
160                                                        if(shape.setFilter && finalTheme.series.filter){
161                                                                shape.setFilter(finalTheme.series.filter);
162                                                        }
163                                                        run.dyn.fill   = shape.getFill();
164                                                        run.dyn.stroke = shape.getStroke();
165                                                        if(events){
166                                                                var o = {
167                                                                        element: "column",
168                                                                        index:   j,
169                                                                        run:     run,
170                                                                        shape:   shape,
171                                                                        shadow:  sshape,
172                                                                        cx:      val.x + 0.5,
173                                                                        cy:      val.y,
174                                                                        x:           indexed?j:run.data[j].x,
175                                                                        y:               indexed?run.data[j]:run.data[j].y
176                                                                };
177                                                                this._connectEvents(o);
178                                                                eventSeries[j] = o;
179                                                        }
180                                                        // if val.py is here, this means we are stacking and we need to subtract previous
181                                                        // value to get the high in which we will lay out the label
182                                                        if(!isNaN(val.py) && val.py > baseline){
183                                                                rect.height = vv - vt(val.py);
184                                                        }
185                                                        this.createLabel(s, value, rect, finalTheme);
186                                                        if(this.animate){
187                                                                this._animateColumn(shape, dim.height - offsets.b - baselineHeight, h);
188                                                        }
189                                                }
190                                        }
191                                }
192                                this._eventSeries[run.name] = eventSeries;
193                                run.dirty = false;
194                        }
195                        this.dirty = false;
196                        // chart mirroring starts
197                        if(has("dojo-bidi")){
198                                this._checkOrientation(this.group, dim, offsets);
199                        }
200                        // chart mirroring ends
201                        return this;    //      dojox/charting/plot2d/Columns
202                },
203                getValue: function(value, j, seriesIndex, indexed){
204                        var y,x;
205                        if(indexed){
206                                if(typeof value == "number"){
207                                        y = value;
208                                }else{
209                                        y = value.y;
210                                }
211                                x = j;
212                        }else{
213                                y = value.y;
214                                x = value.x - 1;
215                        }
216                        return { x: x, y: y };
217                },
218                getBarProperties: function(){
219                        var f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
220                        return {gap: f.gap, width: f.size, thickness: 0};
221                },
222                _animateColumn: function(shape, voffset, vsize){
223                        if(vsize==0){
224                                vsize = 1;
225                        }
226                        fx.animateTransform(lang.delegate({
227                                shape: shape,
228                                duration: 1200,
229                                transform: [
230                                        {name: "translate", start: [0, voffset - (voffset/vsize)], end: [0, 0]},
231                                        {name: "scale", start: [1, 1/vsize], end: [1, 1]},
232                                        {name: "original"}
233                                ]
234                        }, this.animate)).play();
235                }
236               
237        });
238});
Note: See TracBrowser for help on using the repository browser.