]>
git.proxmox.com Git - sencha-touch.git/blob - src/src/chart/series/sprite/Line.js
2 * @class Ext.chart.series.sprite.Line
3 * @extends Ext.chart.series.sprite.Aggregative
7 Ext
.define('Ext.chart.series.sprite.Line', {
8 alias
: 'sprite.lineSeries',
9 extend
: 'Ext.chart.series.sprite.Aggregative',
22 * @cfg {Boolean} smooth 'true' if the sprite uses line smoothing.
27 * @cfg {Boolean} fillArea 'true' if the sprite paints the area underneath the line.
32 * @cfg {Boolean} step 'true' if the line uses steps instead of straight lines to connect the dots.
33 * It is ignored if `smooth` is true.
38 * @cfg {Boolean} preciseStroke 'true' if the line uses precise stroke.
44 dataX
: 'dataX,bbox,smooth',
45 dataY
: 'dataY,bbox,smooth',
50 smooth: function (attr
) {
51 if (attr
.smooth
&& attr
.dataX
&& attr
.dataY
&& attr
.dataX
.length
> 2 && attr
.dataY
.length
> 2) {
52 this.smoothX
= Ext
.draw
.Draw
.spline(attr
.dataX
);
53 this.smoothY
= Ext
.draw
.Draw
.spline(attr
.dataY
);
65 updatePlainBBox: function (plain
) {
67 ymin
= Math
.min(0, attr
.dataMinY
),
68 ymax
= Math
.max(0, attr
.dataMaxY
);
69 plain
.x
= attr
.dataMinX
;
71 plain
.width
= attr
.dataMaxX
- attr
.dataMinX
;
72 plain
.height
= ymax
- ymin
;
75 drawStroke: function (surface
, ctx
, start
, end
, list
, xAxis
) {
84 scale
= Math
.pow(2, power(attr
.dataX
.length
, end
)),
85 smoothX
= this.smoothX
,
86 smoothY
= this.smoothY
,
87 i
, j
, lineConfig
, changes
,
88 cx1
, cy1
, cx2
, cy2
, x
, y
, x0
, y0
, saveOpacity
;
90 function power(count
, end
) {
93 while (n
> 0 && n
< end
) {
97 return power
> 0 ? power
- 1 : power
;
101 if (smooth
&& smoothX
&& smoothY
) {
102 ctx
.moveTo(smoothX
[start
* 3] * xx
+ dx
, smoothY
[start
* 3] * yy
+ dy
);
103 for (i
= 0, j
= start
* 3 + 1; i
< list
.length
- 3; i
+= 3, j
+= 3 * scale
) {
104 cx1
= smoothX
[j
] * xx
+ dx
;
105 cy1
= smoothY
[j
] * yy
+ dy
;
106 cx2
= smoothX
[j
+ 1] * xx
+ dx
;
107 cy2
= smoothY
[j
+ 1] * yy
+ dy
;
126 changes
= attr
.renderer
.call(this, this, lineConfig
, {store
:this.getStore()}, (i
/3 + 1));
128 Ext
.apply(ctx
, changes
);
129 // Fill the area if we need to, using the fill color and transparent strokes.
131 saveOpacity
= ctx
.strokeOpacity
;
133 ctx
.strokeOpacity
= 0;
135 ctx
.bezierCurveTo(cx1
, cy1
, cx2
, cy2
, x
, y
);
136 ctx
.lineTo(x
, xAxis
);
137 ctx
.lineTo(x0
, xAxis
);
140 ctx
.fillStroke(attr
, true);
142 ctx
.strokeOpacity
= saveOpacity
;
145 // Draw the line on top of the filled area.
147 ctx
.bezierCurveTo(cx1
, cy1
, cx2
, cy2
, x
, y
);
155 ctx
.bezierCurveTo(cx1
, cy1
, cx2
, cy2
, x
, y
);
159 ctx
.moveTo(list
[0], list
[1]);
160 for (i
= 3; i
< list
.length
; i
+= 3) {
175 changes
= attr
.renderer
.call(this, this, lineConfig
, {store
:this.getStore()}, i
/3);
177 Ext
.apply(ctx
, changes
);
178 // Fill the area if we need to, using the fill color and transparent strokes.
180 saveOpacity
= ctx
.strokeOpacity
;
182 ctx
.strokeOpacity
= 0;
188 ctx
.lineTo(x
, xAxis
);
189 ctx
.lineTo(x0
, xAxis
);
192 ctx
.fillStroke(attr
, true);
194 ctx
.strokeOpacity
= saveOpacity
;
197 // Draw the line (or the 2 lines if 'step') on top of the filled area.
222 drawLabel: function (text
, dataX
, dataY
, labelId
, region
) {
225 label
= me
.getBoundMarker('labels')[0],
226 labelTpl
= label
.getTemplate(),
227 labelCfg
= me
.labelCfg
|| (me
.labelCfg
= {}),
228 surfaceMatrix
= me
.surfaceMatrix
,
230 labelOverflowPadding
= attr
.labelOverflowPadding
,
231 halfWidth
, halfHeight
,
235 labelCfg
.text
= text
;
237 labelBox
= this.getMarkerBBox('labels', labelId
, true);
239 me
.putMarker('labels', labelCfg
, labelId
);
240 labelBox
= this.getMarkerBBox('labels', labelId
, true);
244 labelCfg
.rotationRads
= Math
.PI
* 0.5;
246 labelCfg
.rotationRads
= 0;
249 halfWidth
= labelBox
.width
/ 2;
250 halfHeight
= labelBox
.height
/ 2;
253 if (labelTpl
.attr
.display
=== 'over') {
254 labelY
= dataY
+ halfHeight
+ labelOverflowPadding
;
256 labelY
= dataY
- halfHeight
- labelOverflowPadding
;
259 if (labelX
<= region
[0] + halfWidth
) {
260 labelX
= region
[0] + halfWidth
;
261 } else if (labelX
>= region
[2] - halfWidth
) {
262 labelX
= region
[2] - halfWidth
;
265 if (labelY
<= region
[1] + halfHeight
) {
266 labelY
= region
[1] + halfHeight
;
267 } else if (labelY
>= region
[3] - halfHeight
) {
268 labelY
= region
[3] - halfHeight
;
271 labelCfg
.x
= surfaceMatrix
.x(labelX
, labelY
);
272 labelCfg
.y
= surfaceMatrix
.y(labelX
, labelY
);
274 if (labelTpl
.attr
.renderer
) {
275 changes
= labelTpl
.attr
.renderer
.call(this, text
, label
, labelCfg
, {store
: this.getStore()}, labelId
);
276 if (typeof changes
=== 'string') {
277 labelCfg
.text
= changes
;
279 Ext
.apply(labelCfg
, changes
);
283 me
.putMarker('labels', labelCfg
, labelId
);
286 renderAggregates: function (aggregates
, start
, end
, surface
, ctx
, clip
, region
) {
291 labels
= attr
.labels
,
292 drawLabels
= labels
&& !!me
.getBoundMarker('labels'),
293 matrix
= attr
.matrix
,
294 surfaceMatrix
= surface
.matrix
,
295 pixel
= surface
.devicePixelRatio
,
301 list
= this.list
|| (this.list
= []),
303 minXs
= aggregates
.minX
,
304 maxXs
= aggregates
.maxX
,
305 minYs
= aggregates
.minY
,
306 maxYs
= aggregates
.maxY
,
307 idx
= aggregates
.startIdx
;
310 for (i
= start
; i
< end
; i
++) {
317 list
.push(minX
* xx
+ dx
, minY
* yy
+ dy
, idx
[i
]);
318 list
.push(maxX
* xx
+ dx
, maxY
* yy
+ dy
, idx
[i
]);
319 } else if (minX
> maxX
) {
320 list
.push(maxX
* xx
+ dx
, maxY
* yy
+ dy
, idx
[i
]);
321 list
.push(minX
* xx
+ dx
, minY
* yy
+ dy
, idx
[i
]);
323 list
.push(maxX
* xx
+ dx
, maxY
* yy
+ dy
, idx
[i
]);
328 for (i
= 0; i
< list
.length
; i
+= 3) {
338 markerCfg
= attr
.renderer
.call(this, this, markerCfg
, {store
:this.getStore()}, i
/3) || {};
340 markerCfg
.translationX
= surfaceMatrix
.x(x
, y
);
341 markerCfg
.translationY
= surfaceMatrix
.y(x
, y
);
342 me
.putMarker('markers', markerCfg
, index
, !attr
.renderer
);
344 if (drawLabels
&& labels
[index
]) {
345 me
.drawLabel(labels
[index
], x
, y
, index
, region
);
348 me
.drawStroke(surface
, ctx
, start
, end
, list
, region
[1] - pixel
);
349 if (!attr
.renderer
) {
350 var lastPointX
= dataX
[dataX
.length
- 1] * xx
+ dx
+ pixel
,
351 lastPointY
= dataY
[dataY
.length
- 1] * yy
+ dy
,
352 bottomY
= region
[1] - pixel
,
353 firstPointX
= dataX
[0] * xx
+ dx
- pixel
,
354 firstPointY
= dataY
[0] * yy
+ dy
;
355 ctx
.lineTo(lastPointX
, lastPointY
);
356 ctx
.lineTo(lastPointX
, bottomY
);
357 ctx
.lineTo(firstPointX
, bottomY
);
358 ctx
.lineTo(firstPointX
, firstPointY
);
362 if (attr
.transformFillStroke
) {
363 attr
.matrix
.toContext(ctx
);
365 if (attr
.preciseStroke
) {
369 if (attr
.transformFillStroke
) {
370 attr
.inverseMatrix
.toContext(ctx
);
372 me
.drawStroke(surface
, ctx
, start
, end
, list
, region
[1] - pixel
);
373 if (attr
.transformFillStroke
) {
374 attr
.matrix
.toContext(ctx
);
378 // Prevent the reverse transform to fix floating point err.
380 ctx
.fillStroke(attr
, true);