source: Dev/trunk/src/client/dojox/charting/plot2d/OHLC.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.3 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        //      Candlesticks are based on the Bars plot type; we expect the following passed
8        //      as values in a series:
9        //      { x?, open, close, high, low }
10        //      if x is not provided, the array index is used.
11        //      failing to provide the OHLC values will throw an error.
12        return declare("dojox.charting.plot2d.OHLC", [CartesianBase, _PlotEvents], {
13                // summary:
14                //              A plot that represents typical open/high/low/close (financial reporting, primarily).
15                //              Unlike most charts, the Candlestick expects data points to be represented by
16                //              an object of the form { x?, open, close, high, low, mid? }, where both
17                //              x and mid are optional parameters.  If x is not provided, the index of the
18                //              data array is used.
19                defaultParams: {
20                        gap:    2,              // gap between columns in pixels
21                        animate: null   // animate chart to place
22                },
23                optionalParams: {
24                        minBarSize: 1,  // minimal bar size in pixels
25                        maxBarSize: 1,  // maximal bar size in pixels
26                        // theme component
27                        stroke:         {},
28                        outline:        {},
29                        shadow:         {},
30                        fill:           {},
31                        font:           "",
32                        fontColor:      ""
33                },
34
35                constructor: function(chart, kwArgs){
36                        // summary:
37                        //              The constructor for a candlestick chart.
38                        // chart: dojox/charting/Chart
39                        //              The chart this plot belongs to.
40                        // kwArgs: dojox.charting.plot2d.__BarCtorArgs?
41                        //              An optional keyword arguments object to help define the plot.
42                        this.opt = lang.clone(this.defaultParams);
43                        du.updateWithObject(this.opt, kwArgs);
44                        du.updateWithPattern(this.opt, kwArgs, this.optionalParams);
45                        this.animate = this.opt.animate;
46                },
47
48                collectStats: function(series){
49                        // summary:
50                        //              Collect all statistics for drawing this chart.  Since the common
51                        //              functionality only assumes x and y, OHLC must create it's own
52                        //              stats (since data has no y value, but open/close/high/low instead).
53                        // series: dojox/charting/Series[]
54                        //              The data series array to be drawn on this plot.
55                        // returns: Object
56                        //              Returns an object in the form of { hmin, hmax, vmin, vmax }.
57
58                        //      we have to roll our own, since we need to use all four passed
59                        //      values to figure out our stats, and common only assumes x and y.
60                        var stats = lang.delegate(dc.defaultStats);
61                        for(var i=0; i<series.length; i++){
62                                var run = series[i];
63                                if(!run.data.length){ continue; }
64                                var old_vmin = stats.vmin, old_vmax = stats.vmax;
65                                if(!("ymin" in run) || !("ymax" in run)){
66                                        arr.forEach(run.data, function(val, idx){
67                                                if(val !== null){
68                                                        var x = val.x || idx + 1;
69                                                        stats.hmin = Math.min(stats.hmin, x);
70                                                        stats.hmax = Math.max(stats.hmax, x);
71                                                        stats.vmin = Math.min(stats.vmin, val.open, val.close, val.high, val.low);
72                                                        stats.vmax = Math.max(stats.vmax, val.open, val.close, val.high, val.low);
73                                                }
74                                        });
75                                }
76                                if("ymin" in run){ stats.vmin = Math.min(old_vmin, run.ymin); }
77                                if("ymax" in run){ stats.vmax = Math.max(old_vmax, run.ymax); }
78                        }
79                        return stats; // Object
80                },
81
82                getSeriesStats: function(){
83                        // summary:
84                        //              Calculate the min/max on all attached series in both directions.
85                        // returns: Object
86                        //              {hmin, hmax, vmin, vmax} min/max in both directions.
87                        var stats = this.collectStats(this.series);
88                        stats.hmin -= 0.5;
89                        stats.hmax += 0.5;
90                        return stats; // Object
91                },
92
93                render: function(dim, offsets){
94                        // summary:
95                        //              Run the calculations for any axes for this plot.
96                        // dim: Object
97                        //              An object in the form of { width, height }
98                        // offsets: Object
99                        //              An object of the form { l, r, t, b}.
100                        // returns: dojox/charting/plot2d/OHLC
101                        //              A reference to this plot for functional chaining.
102                        if(this.zoom && !this.isDataDirty()){
103                                return this.performZoom(dim, offsets);
104                        }
105                        this.resetEvents();
106                        this.dirty = this.isDirty();
107                        if(this.dirty){
108                                arr.forEach(this.series, purgeGroup);
109                                this._eventSeries = {};
110                                this.cleanGroup();
111                                var s = this.getGroup();
112                                df.forEachRev(this.series, function(item){ item.cleanGroup(s); });
113                        }
114                        var t = this.chart.theme, f, gap, width,
115                                ht = this._hScaler.scaler.getTransformerFromModel(this._hScaler),
116                                vt = this._vScaler.scaler.getTransformerFromModel(this._vScaler),
117                                events = this.events();
118                        f = dc.calculateBarSize(this._hScaler.bounds.scale, this.opt);
119                        gap = f.gap;
120                        width = f.size;
121                        for(var i = this.series.length - 1; i >= 0; --i){
122                                var run = this.series[i];
123                                if(!this.dirty && !run.dirty){
124                                        t.skip();
125                                        this._reconnectEvents(run.name);
126                                        continue;
127                                }
128                                run.cleanGroup();
129                                var theme = t.next("candlestick", [this.opt, run]), s = run.group,
130                                        eventSeries = new Array(run.data.length);
131                                for(var j = 0; j < run.data.length; ++j){
132                                        var v = run.data[j];
133                                        if(v !== null){
134                                                var finalTheme = t.addMixin(theme, "candlestick", v, true);
135
136                                                //      calculate the points we need for OHLC
137                                                var x = ht(v.x || (j+0.5)) + offsets.l + gap,
138                                                        y = dim.height - offsets.b,
139                                                        open = vt(v.open),
140                                                        close = vt(v.close),
141                                                        high = vt(v.high),
142                                                        low = vt(v.low);
143                                                if(low > high){
144                                                        var tmp = high;
145                                                        high = low;
146                                                        low = tmp;
147                                                }
148
149                                                if(width >= 1){
150                                                        var hl = {x1: width/2, x2: width/2, y1: y - high, y2: y - low},
151                                                                op = {x1: 0, x2: ((width/2) + ((finalTheme.series.stroke.width||1)/2)), y1: y-open, y2: y-open},
152                                                                cl = {x1: ((width/2) - ((finalTheme.series.stroke.width||1)/2)), x2: width, y1: y-close, y2: y-close};
153                                                        var shape = s.createGroup();
154                                                        shape.setTransform({dx: x, dy: 0});
155                                                        var inner = shape.createGroup();
156                                                        inner.createLine(hl).setStroke(finalTheme.series.stroke);
157                                                        inner.createLine(op).setStroke(finalTheme.series.stroke);
158                                                        inner.createLine(cl).setStroke(finalTheme.series.stroke);
159
160                                                        // TODO: double check this.
161                                                        run.dyn.stroke = finalTheme.series.stroke;
162                                                        if(events){
163                                                                var o = {
164                                                                        element: "candlestick",
165                                                                        index:   j,
166                                                                        run:     run,
167                                                                        shape:   inner,
168                                                                        x:       x,
169                                                                        y:       y-Math.max(open, close),
170                                                                        cx:              width/2,
171                                                                        cy:              (y-Math.max(open, close)) + (Math.max(open > close ? open-close : close-open, 1)/2),
172                                                                        width:   width,
173                                                                        height:  Math.max(open > close ? open-close : close-open, 1),
174                                                                        data:    v
175                                                                };
176                                                                this._connectEvents(o);
177                                                                eventSeries[j] = o;
178                                                        }
179                                                }
180                                                if(this.animate){
181                                                        this._animateOHLC(shape, y - low, high - low);
182                                                }
183                                        }
184                                }
185                                this._eventSeries[run.name] = eventSeries;
186                                run.dirty = false;
187                        }
188                        this.dirty = false;
189                        // chart mirroring starts
190                        if(has("dojo-bidi")){
191                                this._checkOrientation(this.group, dim, offsets);
192                        }
193                        // chart mirroring ends
194                        return this;    //      dojox/charting/plot2d/OHLC
195                },
196                _animateOHLC: function(shape, voffset, vsize){
197                        fx.animateTransform(lang.delegate({
198                                shape: shape,
199                                duration: 1200,
200                                transform: [
201                                        {name: "translate", start: [0, voffset - (voffset/vsize)], end: [0, 0]},
202                                        {name: "scale", start: [1, 1/vsize], end: [1, 1]},
203                                        {name: "original"}
204                                ]
205                        }, this.animate)).play();
206                }
207        });
208});
Note: See TracBrowser for help on using the repository browser.