PieView.js 10.8 KB
Newer Older
L
lang 已提交
1 2
define(function (require) {

L
Add pie  
lang 已提交
3 4
    var graphic = require('../../util/graphic');
    var zrUtil = require('zrender/core/util');
L
lang 已提交
5

6 7
    /**
     * @param {module:echarts/model/Series} seriesModel
L
lang 已提交
8
     * @param {boolean} hasAnimation
9 10
     * @inner
     */
L
lang 已提交
11
    function updateDataSelected(uid, seriesModel, hasAnimation, api) {
L
lang 已提交
12 13 14
        var data = seriesModel.getData();
        var dataIndex = this.dataIndex;
        var name = data.getName(dataIndex);
L
lang 已提交
15
        var selectedOffset = seriesModel.get('selectedOffset');
L
lang 已提交
16

L
lang 已提交
17 18 19 20 21 22
        api.dispatch({
            type: 'pieToggleSelect',
            from: uid,
            name: name,
            seriesName: seriesModel.name
        });
L
lang 已提交
23 24

        data.each(function (idx) {
25
            toggleItemSelected(
L
lang 已提交
26 27 28
                data.getItemGraphicEl(idx),
                data.getItemLayout(idx),
                seriesModel.isSelected(data.getName(idx)),
L
lang 已提交
29 30
                selectedOffset,
                hasAnimation
L
lang 已提交
31 32
            );
        });
L
lang 已提交
33 34
    }

L
lang 已提交
35 36 37 38 39 40 41 42 43
    function updateElementSelect(el, pos, hasAnimation) {
        hasAnimation
            // animateTo will stop revious animation like update transition
            ? el.animate()
                .when(200, {
                    position: pos
                })
                .start('bounceOut')
            : el.attr('position', pos);
L
lang 已提交
44
    }
45 46 47 48 49
    /**
     * @param {module:zrender/graphic/Sector} el
     * @param {Object} layout
     * @param {boolean} isSelected
     * @param {number} selectedOffset
L
lang 已提交
50
     * @param {boolean} hasAnimation
51 52
     * @inner
     */
L
lang 已提交
53
    function toggleItemSelected(el, layout, isSelected, selectedOffset, hasAnimation) {
L
lang 已提交
54
        var midAngle = (layout.startAngle + layout.endAngle) / 2;
L
lang 已提交
55 56

        var dx = Math.cos(midAngle);
L
lang 已提交
57
        var dy = Math.sin(midAngle);
L
lang 已提交
58

L
lang 已提交
59
        var offset = isSelected ? selectedOffset : 0;
L
lang 已提交
60
        var position = [dx * offset, dy * offset];
L
lang 已提交
61 62 63
        updateElementSelect(el, position, hasAnimation);
        updateElementSelect(el.__labelLine, position, hasAnimation);
        updateElementSelect(el.__labelText, position, hasAnimation);
L
lang 已提交
64 65
    }

66 67 68 69
    /**
     * Create sector, label, and label line for each data
     * @param {Object} layout
     * @param {string} text
L
lang 已提交
70
     * @param {boolean} hasAnimation
71 72
     * @return {module:zrender/graphic/Sector}
     */
L
lang 已提交
73
    function createSectorAndLabel(layout, text, hasAnimation, api) {
L
lang 已提交
74 75 76 77 78 79 80 81 82 83
        var shape = zrUtil.extend({}, layout);
        delete shape.label;

        var sector = new graphic.Sector({
            shape: shape
        });

        var labelLayout = layout.label;
        var labelLine = new graphic.Polyline({
            shape: {
L
lang 已提交
84 85 86
                points: labelLayout.linePoints || [
                    [layout.x, layout.y], [layout.x, layout.y], [layout.x, layout.y]
                ]
L
lang 已提交
87 88
            },
            silent: true
L
lang 已提交
89 90 91 92
        });

        var labelText = new graphic.Text({
            style: {
L
lang 已提交
93 94
                x: labelLayout.x,
                y: labelLayout.y,
L
lang 已提交
95 96 97
                text: text,
                textAlign: labelLayout.textAlign,
                textBaseline: labelLayout.textBaseline,
L
lang 已提交
98
                textFont: labelLayout.font
L
lang 已提交
99 100
            },
            rotation: labelLayout.rotation,
L
lang 已提交
101 102 103
            origin: [labelLayout.x, labelLayout.y],
            silent: true,
            z2: 10
L
lang 已提交
104 105 106 107 108 109 110
        });

        sector.__labelLine = labelLine;
        sector.__labelText = labelText;

        if (hasAnimation) {
            sector.shape.endAngle = layout.startAngle;
L
lang 已提交
111
            api.updateGraphicEl(sector, {
L
lang 已提交
112 113 114
                shape: {
                    endAngle: layout.endAngle
                }
L
lang 已提交
115
            });
L
lang 已提交
116 117 118 119 120
        }

        return sector;
    }

L
Add pie  
lang 已提交
121
    var Pie = require('../../view/Chart').extend({
L
lang 已提交
122

L
Add pie  
lang 已提交
123
        type: 'pie',
L
lang 已提交
124

L
lang 已提交
125 126 127 128 129
        init: function () {
            var sectorGroup = new graphic.Group();
            this._sectorGroup = sectorGroup;
        },

L
lang 已提交
130 131 132 133 134 135 136 137 138
        render: function (seriesModel, ecModel, api, payload) {
            if (
                payload && (payload.from === this.uid
                || (payload.type === 'pieToggleSelect'
                    && payload.seriesName !== seriesModel.name))
            ) {
                return;
            }

L
Add pie  
lang 已提交
139 140
            var data = seriesModel.getData();
            var oldData = this._data;
L
lang 已提交
141
            var sectorGroup = this._sectorGroup;
L
Add pie  
lang 已提交
142
            var group = this.group;
L
lang 已提交
143 144 145 146 147

            var hasAnimation = ecModel.get('animation');
            var isFirstRender = !oldData;

            var firstSector;
L
lang 已提交
148 149 150
            var onSectorClick = zrUtil.curry(
                updateDataSelected, this.uid, seriesModel, hasAnimation, api
            );
L
lang 已提交
151

L
lang 已提交
152 153
            var selectedMode = seriesModel.get('selectedMode');

L
Add pie  
lang 已提交
154 155
            data.diff(oldData)
                .add(function (idx) {
L
lang 已提交
156
                    var layout = data.getItemLayout(idx);
L
Add pie  
lang 已提交
157

L
lang 已提交
158
                    var sector = createSectorAndLabel(
L
lang 已提交
159
                        layout, '', !isFirstRender, api
L
lang 已提交
160
                    );
L
lang 已提交
161

L
lang 已提交
162
                    selectedMode && sector.on('click', onSectorClick);
L
lang 已提交
163 164

                    data.setItemGraphicEl(idx, sector);
L
lang 已提交
165 166 167 168 169

                    sectorGroup.add(sector);

                    group.add(sector.__labelLine);
                    group.add(sector.__labelText);
L
lang 已提交
170 171

                    firstSector = firstSector || sector;
L
Add pie  
lang 已提交
172 173 174
                })
                .update(function (newIdx, oldIdx) {
                    var sector = oldData.getItemGraphicEl(oldIdx);
L
lang 已提交
175

L
lang 已提交
176 177 178
                    var layout = data.getItemLayout(newIdx);
                    var labelLayout = layout.label;

L
lang 已提交
179 180 181 182 183 184
                    var labelLine = sector.__labelLine;
                    var labelText = sector.__labelText;

                    selectedMode
                        ? sector.on('click', onSectorClick)
                        : sector.off('click');
L
lang 已提交
185

L
lang 已提交
186 187 188
                    api.updateGraphicEl(sector, {
                        shape: layout
                    });
L
lang 已提交
189
                    api.updateGraphicEl(labelLine, {
L
lang 已提交
190
                        shape: {
L
lang 已提交
191 192 193 194 195
                            points: labelLayout.linePoints || [
                                [labelLayout.x, labelLayout.y],
                                [labelLayout.x, labelLayout.y],
                                [labelLayout.x, labelLayout.y]
                            ]
L
lang 已提交
196 197
                        }
                    });
L
lang 已提交
198 199 200 201 202 203 204 205 206 207 208 209
                    api.updateGraphicEl(labelText, {
                        style: {
                            x: labelLayout.x,
                            y: labelLayout.y
                        },
                        rotation: labelLayout.rotation
                    });

                    // Set none animating style
                    labelText.setStyle({
                        textAlign: labelLayout.textAlign,
                        textBaseline: labelLayout.textBaseline,
L
lang 已提交
210
                        textFont: labelLayout.font
L
lang 已提交
211
                    });
L
lang 已提交
212 213

                    sectorGroup.add(sector);
L
lang 已提交
214
                    data.setItemGraphicEl(newIdx, sector);
L
lang 已提交
215 216 217

                    group.add(labelLine);
                    group.add(labelText);
L
Add pie  
lang 已提交
218 219 220
                })
                .remove(function (idx) {
                    var sector = oldData.getItemGraphicEl(idx);
L
lang 已提交
221 222 223 224
                    sectorGroup.remove(sector);

                    group.remove(sector.__labelLine);
                    group.remove(sector.__labelText);
L
Add pie  
lang 已提交
225 226 227
                })
                .execute();

L
lang 已提交
228 229 230 231
            if (hasAnimation && isFirstRender && firstSector) {
                var shape = firstSector.shape;
                var r = Math.max(api.getWidth(), api.getHeight()) / 2;

L
lang 已提交
232 233
                var removeClipPath = zrUtil.bind(sectorGroup.removeClipPath, sectorGroup);
                sectorGroup.setClipPath(this._createClipPath(
L
lang 已提交
234
                    shape.cx, shape.cy, r, shape.startAngle, shape.clockwise, removeClipPath, api
L
lang 已提交
235 236 237
                ));
            }

L
lang 已提交
238 239 240 241
            // Make sure sectors is on top of labels
            group.remove(sectorGroup);
            group.add(sectorGroup);

L
lang 已提交
242 243 244 245 246
            this._updateAll(data, seriesModel);

            this._data = data;
        },

L
lang 已提交
247
        _updateAll: function (data, seriesModel, hasAnimation) {
L
lang 已提交
248
            var selectedOffset = seriesModel.get('selectedOffset');
L
Add pie  
lang 已提交
249 250
            data.eachItemGraphicEl(function (sector, idx) {
                var itemModel = data.getItemModel(idx);
L
lang 已提交
251
                var itemStyleModel = itemModel.getModel('itemStyle');
L
lang 已提交
252
                var visualColor = data.getItemVisual(idx, 'color');
L
lang 已提交
253

L
Add pie  
lang 已提交
254 255 256
                sector.setStyle(
                    zrUtil.extend(
                        {
L
lang 已提交
257
                            fill: visualColor
L
Add pie  
lang 已提交
258
                        },
L
lang 已提交
259
                        itemStyleModel.getModel('normal').getItemStyle()
L
Add pie  
lang 已提交
260 261 262 263
                    )
                );
                graphic.setHoverStyle(
                    sector,
L
lang 已提交
264
                    itemStyleModel.getModel('emphasis').getItemStyle()
L
Add pie  
lang 已提交
265
                );
L
lang 已提交
266

L
lang 已提交
267
                // Set label style
L
lang 已提交
268
                var labelText = sector.__labelText;
L
lang 已提交
269
                var labelLine = sector.__labelLine;
L
lang 已提交
270 271 272 273 274 275 276 277 278
                var labelModel = itemModel.getModel('label.normal');
                var textStyleModel = labelModel.getModel('textStyle');
                var labelPosition = labelModel.get('position');
                var isLabelInside = labelPosition === 'inside';
                labelText.setStyle({
                    fill: textStyleModel.get('color')
                        || isLabelInside ? '#fff' : visualColor,
                    text: seriesModel.getFormattedLabel(idx, 'normal')
                        || data.getName(idx),
L
lang 已提交
279
                    textFont: textStyleModel.getFont()
L
lang 已提交
280
                });
L
lang 已提交
281
                labelText.attr('ignore', !labelModel.get('show'));
L
lang 已提交
282 283 284 285 286 287
                // Default use item visual color
                labelLine.attr('ignore', !itemModel.get('labelLine.show'));
                labelLine.setStyle({
                    stroke: visualColor
                });
                labelLine.setStyle(itemModel.getModel('labelLine').getLineStyle());
L
lang 已提交
288

289
                toggleItemSelected(
L
lang 已提交
290 291 292
                    sector,
                    data.getItemLayout(idx),
                    itemModel.get('selected'),
L
lang 已提交
293 294
                    selectedOffset,
                    hasAnimation
L
lang 已提交
295
                );
L
lang 已提交
296 297 298
            });
        },

L
lang 已提交
299 300 301
        _createClipPath: function (
            cx, cy, r, startAngle, clockwise, cb, api
        ) {
L
lang 已提交
302 303 304 305 306 307 308 309 310 311
            var clipPath = new graphic.Sector({
                shape: {
                    cx: cx,
                    cy: cy,
                    r0: 0,
                    r: r,
                    startAngle: startAngle,
                    endAngle: startAngle,
                    clockwise: clockwise
                }
L
Add pie  
lang 已提交
312
            });
L
lang 已提交
313

L
lang 已提交
314
            api.initGraphicEl(clipPath, {
L
lang 已提交
315
                shape: {
L
lang 已提交
316
                    endAngle: startAngle + (clockwise ? 1 : -1) * Math.PI * 2
L
lang 已提交
317
                }
L
lang 已提交
318
            }, cb);
L
lang 已提交
319 320

            return clipPath;
L
lang 已提交
321 322 323 324 325 326 327
        },

        dispose: function () {}
    });

    return Pie;
});