LineView.js 8.8 KB
Newer Older
1 2
// TODO Area
// TODO Null data
L
lang 已提交
3 4 5 6
define(function(require) {

    'use strict';

L
lang 已提交
7
    var zrUtil = require('zrender/core/util');
L
lang 已提交
8
    var vector = require('zrender/core/vector');
L
lang 已提交
9
    var DataSymbol = require('../helper/DataSymbol');
10
    var lineAnimationDiff = require('./lineAnimationDiff');
11
    var graphic = require('../../util/graphic');
12 13 14 15 16 17 18 19 20 21 22 23 24 25

    function isPointsSame(points1, points2) {
        if (points1.length !== points2.length) {
            return;
        }
        for (var i = 0; i < points1.length; i++) {
            var p1 = points1[i].point;
            var p2 = points2[i].point;
            if (p1[0] !== p2[0] || p1[1] !== p2[1]) {
                return;
            }
        }
        return true;
    }
L
lang 已提交
26

L
lang 已提交
27 28 29 30 31 32 33 34 35 36 37 38
    function getAxisExtentWithGap(axis) {
        var extent = axis.getExtent();
        if (axis.onBand) {
            // Remove extra 1px to avoid line miter in clipped edge
            var halfBandWidth = axis.getBandWidth() / 2 - 1;
            var dir = extent[1] > extent[0] ? 1 : -1;
            extent[0] += dir * halfBandWidth;
            extent[1] -= dir * halfBandWidth;
        }
        return extent;
    }

L
lang 已提交
39 40 41 42
    return require('../../echarts').extendChartView({

        type: 'line',

L
lang 已提交
43 44 45
        init: function () {
            this._dataSymbol = new DataSymbol();
        },
L
lang 已提交
46

47
        render: function (seriesModel, ecModel) {
L
lang 已提交
48
            var group = this.group;
L
lang 已提交
49 50 51
            var data = seriesModel.getData();
            var lineStyleNormalModel = seriesModel.getModel('itemStyle.normal.lineStyle');

L
lang 已提交
52
            var points = data.map(data.getItemLayout, true);
L
lang 已提交
53
            var plainDataList = data.map(['x', 'y'], function (x, y, idx) {
54
                return {
L
lang 已提交
55 56 57 58 59 60
                    x: x,
                    y: y,
                    point: points[idx],
                    name: data.getName(idx),
                    idx: idx,
                    rawIdx: data.getRawIndex(idx)
61 62 63
                };
            });

64
            var prevCoordSys = this._coordSys;
L
lang 已提交
65 66
            var coordSys = seriesModel.coordinateSystem;
            var isCoordSysPolar = coordSys.type === 'polar';
L
lang 已提交
67

L
lang 已提交
68
            // FIXME Update after animation
L
lang 已提交
69 70 71 72 73 74 75 76
            // if (
            //     isCoordSysPolar
            //     && points.length > 2
            //     && coordinateSystem.getAngleAxis().type === 'category'
            // ) {
            //     // Close polyline
            //     points.push(Array.prototype.slice.call(points[0]));
            // }
L
lang 已提交
77

L
lang 已提交
78 79
            // Draw symbols, enable animation on the first draw
            var dataSymbol = this._dataSymbol;
L
lang 已提交
80 81 82
            var polyline = this._polyline;
            var enableAnimation = ecModel.get('animation');

L
lang 已提交
83
            // Initialization animation or coordinate system changed
L
lang 已提交
84 85 86 87 88
            if (
                !(polyline
                && prevCoordSys.type === coordSys.type
                && enableAnimation)
            ) {
L
lang 已提交
89 90
                dataSymbol.updateData(data, false);

91
                polyline = new graphic.Polyline({
L
lang 已提交
92 93 94
                    shape: {
                        points: points
                    },
L
tweak  
lang 已提交
95
                    style: zrUtil.extend(
L
lang 已提交
96 97
                        lineStyleNormalModel.getLineStyle(),
                        {
L
lang 已提交
98
                            stroke: data.getVisual('color'),
L
lang 已提交
99
                            lineJoin: 'bevel'
L
tweak  
lang 已提交
100
                        }
L
lang 已提交
101
                    )
L
lang 已提交
102
                });
L
lang 已提交
103

L
lang 已提交
104
                // var removeClipPath = zrUtil.bind(polyline.removeClipPath, polyline);
L
lang 已提交
105
                var categoryAxis = coordSys.getAxesByScale('ordinal')[0];
L
lang 已提交
106
                var clipPath = isCoordSysPolar
107 108
                    ? this._createPolarClipShape(coordSys, enableAnimation, categoryAxis)
                    : this._createGridClipShape(coordSys, enableAnimation, categoryAxis);
109 110 111

                polyline.setClipPath(clipPath);

L
lang 已提交
112
                group.add(polyline);
L
lang 已提交
113 114 115 116

                this._polyline = polyline;
            }
            else {
L
lang 已提交
117 118
                // Update clipPath
                var clipPath = isCoordSysPolar
119 120
                    ? this._createPolarClipShape(coordSys)
                    : this._createGridClipShape(coordSys);
L
lang 已提交
121 122
                polyline.setClipPath(clipPath);

L
lang 已提交
123
                dataSymbol.updateData(data, false);
124 125
                // In the case data zoom triggerred refreshing frequently
                // Data may not change if line has a category axis. So it should animate nothing
L
lang 已提交
126 127 128 129
                if (!isPointsSame(this._plainDataList, plainDataList)) {
                    this._updateAnimation(
                        data, plainDataList, coordSys
                    );
130
                }
L
lang 已提交
131
                // Add back
L
lang 已提交
132
                group.add(polyline);
L
lang 已提交
133 134
            }

135 136 137 138
            // Make sure symbols is on top of line
            group.remove(dataSymbol.group);
            group.add(dataSymbol.group);

L
lang 已提交
139
            this._data = data;
140

L
lang 已提交
141
            // Save the coordinate system and data for transition animation when data changed
L
lang 已提交
142 143
            this._plainDataList = plainDataList;
            this._coordSys = coordSys;
144 145
        },

L
lang 已提交
146
        _updateAnimation: function (data, plainDataList, coordSys) {
L
lang 已提交
147
            var polyline = this._polyline;
L
lang 已提交
148 149 150
            var diff = lineAnimationDiff(
                this._plainDataList, plainDataList, this._coordSys, coordSys
            );
L
lang 已提交
151 152 153 154 155 156 157
            polyline.shape.points = diff.current;
            polyline.animateTo({
                shape: {
                    points: diff.next
                }
            }, 300, 'cubicOut');

L
lang 已提交
158 159
            var updatedDataInfo = [];
            var addedDataIndices = [];
L
lang 已提交
160 161 162
            var diffStatus = diff.status;

            for (var i = 0; i < diffStatus.length; i++) {
L
lang 已提交
163 164 165 166 167 168 169 170 171
                var cmd = diffStatus[i].cmd;
                if (cmd === '=') {
                    updatedDataInfo.push({
                        el: data.getItemGraphicEl(diffStatus[i].idx1),
                        ptIdx: i    // Index of points
                    });
                }
                else if (cmd === '+') {
                    addedDataIndices.push(diffStatus[i].idx);
L
lang 已提交
172 173 174 175
                }
            }

            if (polyline.animators) {
L
lang 已提交
176 177 178 179 180 181 182 183
                for (var i = 0; i < addedDataIndices.length; i++) {
                    var el = data.getItemGraphicEl(addedDataIndices[i]);
                    var oldScale = el.scale;
                    el.scale = [1, 1];
                    el.animateTo({
                        scale: oldScale
                    }, 300, 300, 'cubicOut');
                }
L
lang 已提交
184
                polyline.animators[0].during(function () {
L
lang 已提交
185 186
                    for (var i = 0; i < updatedDataInfo.length; i++) {
                        var el = updatedDataInfo[i].el;
L
lang 已提交
187
                        vector.copy(
L
lang 已提交
188 189
                            el.position,
                            // synchronizing with the point on line
L
lang 已提交
190
                            polyline.shape.points[updatedDataInfo[i].ptIdx]
L
lang 已提交
191
                        );
L
lang 已提交
192
                        el.dirty();
L
lang 已提交
193 194 195
                    }
                });
            }
L
lang 已提交
196 197
        },

198
        _createGridClipShape: function (cartesian, animation, categoryAxis) {
L
lang 已提交
199 200
            var xExtent = getAxisExtentWithGap(cartesian.getAxis('x'));
            var yExtent = getAxisExtentWithGap(cartesian.getAxis('y'));
L
lang 已提交
201

202
            var clipPath = new graphic.Rect({
L
lang 已提交
203 204 205
                shape: {
                    x: xExtent[0],
                    y: yExtent[0],
L
lang 已提交
206
                    width: xExtent[1] - xExtent[0],
L
lang 已提交
207 208 209 210
                    height: yExtent[1] - yExtent[0]
                }
            });

L
lang 已提交
211
            if (animation) {
212
                clipPath.shape[categoryAxis.isHorizontal() ? 'width' : 'height'] = 0;
L
lang 已提交
213 214 215 216 217 218 219
                clipPath.animateTo({
                    shape: {
                        width: xExtent[1] - xExtent[0],
                        height: yExtent[1] - yExtent[0]
                    }
                }, 1500, animation);
            }
L
lang 已提交
220 221 222 223

            return clipPath;
        },

224
        _createPolarClipShape: function (polar, animation) {
L
lang 已提交
225 226 227 228 229
            // var angleAxis = polar.getAngleAxis();
            var radiusAxis = polar.getRadiusAxis();

            var radiusExtent = radiusAxis.getExtent();

230
            var clipPath = new graphic.Sector({
L
lang 已提交
231 232 233 234 235 236
                shape: {
                    cx: polar.cx,
                    cy: polar.cy,
                    r0: radiusExtent[0],
                    r: radiusExtent[1],
                    startAngle: 0,
237
                    endAngle: Math.PI * 2
L
lang 已提交
238 239 240
                }
            });

241 242 243 244 245 246 247 248
            if (animation) {
                clipPath.shape.endAngle = 0;
                clipPath.animateTo({
                    shape: {
                        endAngle: Math.PI * 2
                    }
                }, 1500, animation);
            }
L
lang 已提交
249 250

            return clipPath;
L
lang 已提交
251 252 253 254
        },

        remove: function () {
            this.group.remove(this._polyline);
L
lang 已提交
255
            this._dataSymbol.remove(true);
L
lang 已提交
256 257 258
        }
    });
});