BrushController.js 25.2 KB
Newer Older
P
pah100 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/**
 * Box selection tool.
 *
 * @module echarts/component/helper/BrushController
 */

define(function (require) {

    var Eventful = require('zrender/mixin/Eventful');
    var zrUtil = require('zrender/core/util');
    var graphic = require('../../util/graphic');
    var interactionMutex = require('./interactionMutex');
    var DataDiffer = require('../../data/DataDiffer');

P
pah100 已提交
15
    var curry = zrUtil.curry;
P
pah100 已提交
16 17 18 19 20 21 22
    var each = zrUtil.each;
    var map = zrUtil.map;
    var mathMin = Math.min;
    var mathMax = Math.max;
    var mathPow = Math.pow;

    var COVER_Z = 10000;
P
pah100 已提交
23
    var UNSELECT_THRESHOLD = 6;
P
pah100 已提交
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
    var MIN_RESIZE_LINE_WIDTH = 6;
    var MUTEX_RESOURCE_KEY = 'globalPan';

    var DIRECTION_MAP = {
        w: [0, 0],
        e: [0, 1],
        n: [1, 0],
        s: [1, 1]
    };
    var CURSOR_MAP = {
        w: 'ew',
        e: 'ew',
        n: 'ns',
        s: 'ns',
        ne: 'nesw',
        sw: 'nesw',
        nw: 'nwse',
        se: 'nwse'
    };
    var DEFAULT_BRUSH_OPT = {
        brushStyle: {
            lineWidth: 2,
            stroke: 'rgba(0,0,0,0.3)',
            fill: 'rgba(0,0,0,0.15)'
        },
        transformable: true,
P
pah100 已提交
50 51
        brushMode: 'single',
        removeOnClick: false
P
pah100 已提交
52 53 54 55 56 57 58 59
    };

    var baseUID = 0;

    /**
     * @alias module:echarts/component/helper/BrushController
     * @constructor
     * @mixin {module:zrender/mixin/Eventful}
60
     * @event module:echarts/component/helper/BrushController#brush
P
pah100 已提交
61 62 63 64 65 66 67
     *        params:
     *            brushRanges: Array.<Array>, coord relates to container group,
     *                                    If no container specified, to global.
     *            opt {
     *                isEnd: boolean,
     *                removeOnClick: boolean
     *            }
P
pah100 已提交
68 69 70 71 72
     *
     * @param {module:zrender/zrender~ZRender} zr
     */
    function BrushController(zr) {

P
pah100 已提交
73 74 75 76
        if (__DEV__) {
            zrUtil.assert(zr);
        }

P
pah100 已提交
77 78 79
        Eventful.call(this);

        /**
P
pah100 已提交
80
         * @type {module:zrender/zrender~ZRender}
P
pah100 已提交
81
         * @private
P
pah100 已提交
82
         */
P
pah100 已提交
83
        this._zr = zr;
P
pah100 已提交
84 85

        /**
P
pah100 已提交
86
         * @type {module:zrender/container/Group}
P
pah100 已提交
87 88
         * @readOnly
         */
P
pah100 已提交
89
        this.group = new graphic.Group();
P
pah100 已提交
90 91

        /**
P
pah100 已提交
92 93 94
         * Only for drawing (after enabledBrush).
         * @private
         * @type {string}
P
pah100 已提交
95
         */
P
pah100 已提交
96
        this._brushType;
P
pah100 已提交
97 98

        /**
P
pah100 已提交
99 100 101
         * Only for drawing (after enabledBrush).
         * @private
         * @type {Object}
P
pah100 已提交
102
         */
P
pah100 已提交
103
        this._brushOption;
P
pah100 已提交
104 105

        /**
P
pah100 已提交
106
         * @private
P
pah100 已提交
107
         * @type {Object}
P
pah100 已提交
108
         */
P
pah100 已提交
109 110 111 112 113 114 115
        this._panels;

        /**
         * @private
         * @type {module:zrender/mixin/Transformable}
         */
        this._container;
P
pah100 已提交
116 117 118

        /**
         * @private
P
pah100 已提交
119
         * @type {Array.<nubmer>}
P
pah100 已提交
120 121 122 123 124
         */
        this._track = [];

        /**
         * @private
P
pah100 已提交
125
         * @type {boolean}
P
pah100 已提交
126 127 128 129 130
         */
        this._dragging;

        /**
         * @private
P
pah100 已提交
131
         * @type {Array}
P
pah100 已提交
132 133 134 135 136
         */
        this._covers = [];

        /**
         * @private
P
pah100 已提交
137
         * @type {moudule:zrender/container/Group}
P
pah100 已提交
138 139 140 141 142
         */
        this._creatingCover;

        /**
         * @private
P
pah100 已提交
143
         * @type {boolean}
P
pah100 已提交
144
         */
P
pah100 已提交
145 146 147
        if (__DEV__) {
            this._mounted;
        }
P
pah100 已提交
148 149

        /**
P
pah100 已提交
150
         * @private
P
pah100 已提交
151 152 153 154 155 156
         * @type {string}
         */
        this._uid = 'brushController_' + baseUID++;

        /**
         * @private
P
pah100 已提交
157
         * @type {Object}
P
pah100 已提交
158 159 160
         */
        this._handlers = {};
        each(mouseHandlers, function (handler, eventName) {
P
pah100 已提交
161
            this._handlers[eventName] = zrUtil.bind(handler, this);
P
pah100 已提交
162 163 164 165 166 167 168 169 170 171 172 173 174 175
        }, this);
    }

    BrushController.prototype = {

        constructor: BrushController,

        /**
         * If set to null/undefined/false, select disabled.
         * @param {Object} brushOption
         * @param {string|boolean} brushOption.brushType 'line', 'rect', 'polygon' or false
         *                          If pass false/null/undefined, disable brush.
         * @param {number} [brushOption.brushMode='single'] 'single' or 'multiple'
         * @param {boolean} [brushOption.transformable=true]
P
pah100 已提交
176
         * @param {boolean} [brushOption.removeOnClick=false]
P
pah100 已提交
177 178 179 180 181 182 183 184
         * @param {boolean} [brushOption.onRelease]
         * @param {Object} [brushOption.brushStyle]
         * @param {number} [brushOption.brushStyle.width]
         * @param {number} [brushOption.brushStyle.lineWidth]
         * @param {string} [brushOption.brushStyle.stroke]
         * @param {string} [brushOption.brushStyle.fill]
         */
        enableBrush: function (brushOption) {
P
pah100 已提交
185 186
            if (__DEV__) {
                zrUtil.assert(this._mounted);
P
pah100 已提交
187 188
            }

P
pah100 已提交
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
            this._brushType && doDisableBrush(this);
            brushOption.brushType && doEnableBrush(this, brushOption);

            return this;
        },

        /**
         * @param {Array.<Object>} panelOpts If not pass, it is global brush.
         *        Each items: {panelId, points}
         */
        setPanels: function (panelOpts) {
            var oldPanels = this._panels || {};
            var newPanels = this._panels = panelOpts && panelOpts.length && {};
            var thisGroup = this.group;

            newPanels && each(panelOpts, function (panelOpt) {
                var panelId = panelOpt.panelId;
                var panel = oldPanels[panelId];
                if (!panel) {
                    panel = new graphic.Polygon({
                        // FIXME
                        // 这样靠谱么?
                        // silent: true,
                        // invisible: true,
                        style: {
                            fill: 'rgba(0,0,0,0)'
                        },
                        cursor: 'crosshair'
                    });
                    // FIXME
                    // cursor
                    // boundingRect will change when dragging, so we have
                    // to keep initial boundingRect.
                    thisGroup.add(panel);
                }
                // FIXME
                // only support rect panel now.
                panel.attr('shape', {points: panelOpt.points});
                panel.__brushPanelId = panelId;
                newPanels[panelId] = panel;
                oldPanels[panelId] = null;
            });

            each(oldPanels, function (panel) {
                panel && thisGroup.remove(panel);
            });
P
pah100 已提交
235 236 237 238 239

            return this;
        },

        /**
P
pah100 已提交
240 241 242 243
         * @param {Object} opt
         * @param {module:zrender/mixin/Transformable} [opt.container]
         * @param {boolean} [opt.localCoord=false] Whether input and output with global coord,
         *                                          ohterwise coord is according to panel.
P
pah100 已提交
244
         */
P
pah100 已提交
245 246
        mount: function (opt) {
            opt = opt || {};
P
pah100 已提交
247

P
pah100 已提交
248 249 250
            if (__DEV__) {
                this._mounted = true; // should be at first.
            }
P
pah100 已提交
251

P
pah100 已提交
252 253 254 255 256 257 258 259 260 261 262 263
            var container = opt.container;

            // Reset container.
            if (!this._container || container !== this._container) {
                unmountContainer(this);

                if (!container) {
                    container = new graphic.Group();
                    this._zr.add(container);
                    container.__createdByBrush = true;
                }
                this._container = container;
P
pah100 已提交
264

P
pah100 已提交
265 266 267
                // Add to new container.
                container.add(this.group);
            }
P
pah100 已提交
268 269 270 271 272 273 274 275 276 277 278 279 280

            return this;
        },

        /**
         * @param
         */
        eachCover: function (cb, context) {
            each(this._covers, cb, context);
        },

        /**
         * Update covers.
P
pah100 已提交
281
         * @param {Array.<Object>} brushOptionList Like:
P
pah100 已提交
282
         *        [
P
pah100 已提交
283 284
         *            {id: 'xx', brushType: 'line', range: [23, 44], brushStyle, transformable},
         *            {id: 'yy', brushType: 'rect', range: [[23, 44], [23, 54]]},
P
pah100 已提交
285 286
         *            ...
         *        ]
P
pah100 已提交
287
         *        `brushType` is required in each cover info.
P
pah100 已提交
288
         *        `id` is not mandatory.
P
pah100 已提交
289 290
         *        `brushStyle`, `transformable` is not mandatory, use DEFAULT_BRUSH_OPT by default.
         *        If brushOptionList is null/undefined, all covers removed.
P
pah100 已提交
291
         */
P
pah100 已提交
292
        updateCovers: function (brushOptionList) {
P
pah100 已提交
293 294
            if (__DEV__) {
                zrUtil.assert(this._mounted);
P
pah100 已提交
295 296
            }

P
pah100 已提交
297 298 299 300
            brushOptionList = zrUtil.map(brushOptionList, function (brushOption) {
                return zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);
            });

P
pah100 已提交
301 302 303 304 305
            var tmpIdPrefix = '\0-brush-index-';
            var oldCovers = this._covers;
            var newCovers = this._covers = [];
            var controller = this;

P
pah100 已提交
306 307 308
            (new DataDiffer(oldCovers, brushOptionList, oldGetKey, getKey))
                .add(addOrUpdate)
                .update(addOrUpdate)
P
pah100 已提交
309 310 311 312 313
                .remove(remove)
                .execute();

            return this;

P
pah100 已提交
314 315 316
            function getKey(brushOption, index) {
                return (brushOption.id != null ? brushOption.id : tmpIdPrefix + index)
                    + '-' + brushOption.brushType;
P
pah100 已提交
317 318
            }

P
pah100 已提交
319 320
            function oldGetKey(cover, index) {
                return getKey(cover.__brushOption, index);
P
pah100 已提交
321 322
            }

P
pah100 已提交
323
            function addOrUpdate(newIndex, oldIndex) {
P
pah100 已提交
324
                var newBrushOption = brushOptionList[newIndex];
P
pah100 已提交
325 326 327 328
                var cover = newCovers[newIndex] = oldIndex != null
                    ? (oldCovers[oldIndex].__brushOption = newBrushOption, oldCovers[oldIndex])
                    : endCreating(controller, createCover(controller, newBrushOption));
                updateCoverAfterCreation(controller, cover);
P
pah100 已提交
329 330 331 332 333
            }

            function remove(oldIndex) {
                controller.group.remove(oldCovers[oldIndex]);
            }
P
pah100 已提交
334

P
pah100 已提交
335 336 337 338 339
        },

        unmount: function () {
            this.enableBrush(false);

P
pah100 已提交
340 341 342 343 344
            unmountContainer(this);

            if (__DEV__) {
                this._mounted = false; // should be at last.
            }
P
pah100 已提交
345 346 347 348 349 350 351 352 353 354 355 356 357

            return this;
        },

        dispose: function () {
            this.unmount();
            this.off();
        }
    };

    zrUtil.mixin(BrushController, Eventful);


P
pah100 已提交
358 359
    function doEnableBrush(controller, brushOption) {
        var zr = controller._zr;
P
pah100 已提交
360

P
pah100 已提交
361 362 363 364
        var onRelease = zrUtil.bind(function (userOnRelease) {
            controller.enableBrush(false);
            userOnRelease && userOnRelease();
        }, controller, brushOption.onRelease);
P
pah100 已提交
365

P
pah100 已提交
366 367 368
        // Consider roam, which takes globalPan too.
        interactionMutex.take(zr, MUTEX_RESOURCE_KEY, controller._uid, onRelease);
        zr.setDefaultCursorStyle('crosshair');
P
pah100 已提交
369

P
pah100 已提交
370
        each(controller._handlers, function (handler, eventName) {
P
pah100 已提交
371 372 373
            zr.on(eventName, handler);
        });

P
pah100 已提交
374 375
        controller._brushType = brushOption.brushType;
        controller._brushOption = zrUtil.merge(zrUtil.clone(DEFAULT_BRUSH_OPT), brushOption, true);
P
pah100 已提交
376 377
    }

P
pah100 已提交
378 379
    function doDisableBrush(controller) {
        var zr = controller._zr;
P
pah100 已提交
380

P
pah100 已提交
381
        interactionMutex.release(zr, MUTEX_RESOURCE_KEY, controller._uid);
P
pah100 已提交
382 383
        zr.setDefaultCursorStyle('default');

P
pah100 已提交
384
        each(controller._handlers, function (handler, eventName) {
P
pah100 已提交
385 386 387
            zr.off(eventName, handler);
        });

P
pah100 已提交
388
        controller._brushType = controller._brushOption = null;
P
pah100 已提交
389 390
    }

P
pah100 已提交
391 392
    function createCover(controller, brushOption) {
        var cover = coverRenderers[brushOption.brushType].createCover(controller, brushOption);
P
pah100 已提交
393
        updateZ(cover);
P
pah100 已提交
394
        cover.__brushOption = brushOption;
P
pah100 已提交
395
        controller.group.add(cover);
P
pah100 已提交
396 397 398
        return cover;
    }

P
pah100 已提交
399 400
    function endCreating(controller, creatingCover) {
        var coverRenderer = getCoverRenderer(creatingCover);
P
pah100 已提交
401
        if (coverRenderer.endCreating) {
P
pah100 已提交
402
            coverRenderer.endCreating(controller, creatingCover);
P
pah100 已提交
403 404
            updateZ(creatingCover);
        }
P
pah100 已提交
405 406 407 408 409 410
        return creatingCover;
    }

    function updateCoverShape(controller, cover) {
        var brushOption = cover.__brushOption;
        getCoverRenderer(cover).updateCoverShape(controller, cover, brushOption.range, brushOption);
P
pah100 已提交
411 412
    }

P
pah100 已提交
413 414 415 416 417 418
    function updateZ(group) {
        group.traverse(function (el) {
            el.z = COVER_Z;
        });
    }

P
pah100 已提交
419 420 421
    function updateCoverAfterCreation(controller, cover) {
        getCoverRenderer(cover).updateCommon(controller, cover);
        updateCoverShape(controller, cover);
P
pah100 已提交
422 423
    }

P
pah100 已提交
424 425
    function getCoverRenderer(cover) {
        return coverRenderers[cover.__brushOption.brushType];
P
pah100 已提交
426 427
    }

P
pah100 已提交
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
    function getPanelByPoint(controller, x, y) {
        if (isGlobalBrush(controller)) {
            return {};
        }
        var panel;
        each(controller._panels, function (pn) {
            pn.contain(x, y) && (panel = pn);
        });
        return panel;
    }

    function clearCovers(controller) {
        each(controller._covers, function (cover) {
            controller.group.remove(cover);
        }, controller);
        controller._covers.length = 0;
P
pah100 已提交
444 445
    }

P
pah100 已提交
446 447
    function trigger(controller, opt) {
        var brushRanges = map(controller._covers, function (cover) {
P
pah100 已提交
448
            var brushOption = cover.__brushOption;
P
pah100 已提交
449 450
            var range = zrUtil.clone(brushOption.range);

P
pah100 已提交
451 452
            return {
                brushType: brushOption.brushType,
P
pah100 已提交
453 454
                panelId: brushOption.panelId,
                range: range
P
pah100 已提交
455
            };
P
pah100 已提交
456
        });
P
pah100 已提交
457 458

        controller.trigger('brush', brushRanges, {
459 460 461
            isEnd: !!opt.isEnd,
            removeOnClick: !!opt.removeOnClick
        });
P
pah100 已提交
462 463
    }

P
pah100 已提交
464 465
    function shouldShowCover(controller) {
        var track = controller._track;
P
pah100 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478 479

        if (!track.length) {
            return false;
        }

        var p2 = track[track.length - 1];
        var p1 = track[0];
        var dx = p2[0] - p1[0];
        var dy = p2[1] - p1[1];
        var dist = mathPow(dx * dx + dy * dy, 0.5);

        return dist > UNSELECT_THRESHOLD;
    }

P
pah100 已提交
480
    function unmountContainer(controller) {
P
pah100 已提交
481
        // container may 'removeAll' outside.
P
pah100 已提交
482 483 484 485 486
        clearCovers(controller);

        var group = controller.group;
        var container = controller._container;

P
pah100 已提交
487
        if (container) {
P
pah100 已提交
488 489 490 491 492
            group && container.remove(group);
            if (container.__createdByBrush) {
                controller._zr.remove(controller._container);
            }
            controller._container = null;
P
pah100 已提交
493 494 495 496
        }
    }

    function isGlobalBrush(controller) {
P
pah100 已提交
497
        return !controller._panels;
P
pah100 已提交
498 499
    }

P
pah100 已提交
500 501
    function getTrackEnds(track) {
        var tail = track.length - 1;
P
pah100 已提交
502
        tail < 0 && (tail = 0);
P
pah100 已提交
503
        return [track[0], track[tail]];
P
pah100 已提交
504 505
    }

P
pah100 已提交
506
    function createBaseRect(controller, cover, brushOption) {
P
pah100 已提交
507
        cover.add(new graphic.Rect({
P
pah100 已提交
508
            name: 'rect',
P
pah100 已提交
509
            style: makeStyle(brushOption),
P
pah100 已提交
510 511 512
            silent: true,
            draggable: true,
            cursor: 'move',
P
pah100 已提交
513 514
            drift: curry(driftRect, controller, cover, 'nswe'),
            ondragend: curry(trigger, controller, {isEnd: true})
P
pah100 已提交
515 516
        }));
    }
P
pah100 已提交
517

P
pah100 已提交
518
    function updateCommon(controller, cover) {
P
pah100 已提交
519
        var brushOption = cover.__brushOption;
P
pah100 已提交
520
        cover.childAt(0).useStyle(makeStyle(brushOption));
P
pah100 已提交
521 522 523 524 525
        var transformable = brushOption.transformable;
        cover.childAt(0).attr({
            silent: !transformable,
            cursor: transformable ? 'move' : 'default'
        });
P
pah100 已提交
526 527 528 529 530 531
    }

    function updateRectShape(cover, name, x, y, w, h) {
        cover.childOfName(name).setShape({x: x, y: y, width: w, height: h});
    }

P
pah100 已提交
532 533 534 535
    function makeStyle(brushOption) {
        return zrUtil.defaults({strokeNoScale: true}, brushOption.brushStyle);
    }

P
pah100 已提交
536 537 538 539 540 541 542 543 544 545
    function formatRectRange(x, y, x2, y2) {
        var min = [mathMin(x, x2), mathMin(y, y2)];
        var max = [mathMax(x, x2), mathMax(y, y2)];

        return [
            [min[0], max[0]], // x range
            [min[1], max[1]] // y range
        ];
    }

P
pah100 已提交
546
    function driftRect(controller, cover, name, dx, dy) {
P
pah100 已提交
547 548
        var brushOption = cover.__brushOption;
        var rectRange = brushOption.range;
P
pah100 已提交
549 550 551 552 553 554 555
        var delta = [dx, dy];

        each(name.split(''), function (namePart) {
            var ind = DIRECTION_MAP[namePart];
            rectRange[ind[0]][ind[1]] += delta[ind[0]];
        });

P
pah100 已提交
556
        brushOption.range = formatRectRange(
P
pah100 已提交
557 558 559
            rectRange[0][0], rectRange[1][0], rectRange[0][1], rectRange[1][1]
        );

P
pah100 已提交
560 561
        updateCoverAfterCreation(controller, cover);
        trigger(controller, {isEnd: false});
P
pah100 已提交
562 563
    }

P
pah100 已提交
564
    function driftPolygon(controller, cover, dx, dy) {
P
pah100 已提交
565
        var range = cover.__brushOption.range;
P
pah100 已提交
566 567 568 569 570 571

        each(range, function (point) {
            point[0] += dx;
            point[1] += dy;
        });

P
pah100 已提交
572 573
        updateCoverAfterCreation(controller, cover);
        trigger(controller, {isEnd: false});
P
pah100 已提交
574 575 576 577 578 579 580
    }

    function preventDefault(e) {
        var rawE = e.event;
        rawE.preventDefault && rawE.preventDefault();
    }

P
pah100 已提交
581
    function updateCoverByMouse(controller, e, isEnd) {
P
pah100 已提交
582 583
        var x = e.offsetX;
        var y = e.offsetY;
P
pah100 已提交
584 585 586
        var creatingCover = controller._creatingCover;
        var thisBrushOption = controller._brushOption;
        var panel = getPanelByPoint(controller, x, y);
P
pah100 已提交
587

P
pah100 已提交
588
        if (panel || isEnd) { // Outside panel but isEnd, cover creating ends.
P
pah100 已提交
589

P
pah100 已提交
590
            panel && controller._track.push([x, y]);
P
pah100 已提交
591

P
pah100 已提交
592 593 594 595 596 597 598 599
            if (shouldShowCover(controller)) {

                if (!creatingCover && panel) {
                    thisBrushOption.brushMode === 'single' && clearCovers(controller);
                    var brushOption = zrUtil.clone(thisBrushOption);
                    brushOption.panelId = panel.__brushPanelId;
                    creatingCover = controller._creatingCover = createCover(controller, brushOption);
                    controller._covers.push(creatingCover);
P
pah100 已提交
600 601
                }

P
pah100 已提交
602 603 604
                if (creatingCover) {
                    var coverRenderer = coverRenderers[controller._brushType];
                    var coverBrushOption = creatingCover.__brushOption;
P
pah100 已提交
605

P
pah100 已提交
606 607 608
                    coverBrushOption.range = coverRenderer.getCreatingRange(
                        zrUtil.clone(controller._track)
                    );
P
pah100 已提交
609

P
pah100 已提交
610 611 612 613
                    if (isEnd) {
                        endCreating(controller, creatingCover);
                        coverRenderer.updateCommon(controller, creatingCover);
                    }
P
pah100 已提交
614

P
pah100 已提交
615 616
                    updateCoverShape(controller, creatingCover);
                }
P
pah100 已提交
617

P
pah100 已提交
618
                trigger(controller, {isEnd: isEnd});
P
pah100 已提交
619
            }
P
pah100 已提交
620 621 622 623 624 625 626 627 628 629
            else if (
                isEnd
                && !creatingCover
                && thisBrushOption.brushMode === 'single'
                && thisBrushOption.removeOnClick
            ) {
                // Help user to remove covers easily, only by a tiny drag, in 'single' mode.
                // But a single click do not clear covers, because user may have casual
                // clicks (for example, click on other component and do not expect covers
                // disappear).
P
pah100 已提交
630 631
                clearCovers(controller);
                trigger(controller, {isEnd: isEnd, removeOnClick: true});
P
pah100 已提交
632
            }
P
pah100 已提交
633 634 635 636 637 638 639 640 641 642 643 644 645 646

        }
    }

    var mouseHandlers = {

        mousedown: function (e) {
            if (!e.target || !e.target.draggable) {

                preventDefault(e);

                var x = e.offsetX;
                var y = e.offsetY;

P
pah100 已提交
647 648
                this._creatingCover = null;

P
pah100 已提交
649
                if (getPanelByPoint(this, x, y)) {
P
pah100 已提交
650 651 652 653 654 655 656 657 658 659 660
                    this._dragging = true;
                    this._track = [[x, y]];
                }
            }
        },

        mousemove: function (e) {
            if (this._dragging) {

                preventDefault(e);

P
pah100 已提交
661
                updateCoverByMouse(this, e, false);
P
pah100 已提交
662 663 664 665 666 667 668 669
            }
        },

        mouseup: function (e) {
            if (this._dragging) {

                preventDefault(e);

P
pah100 已提交
670
                updateCoverByMouse(this, e, true);
P
pah100 已提交
671 672 673 674 675 676 677 678 679 680 681 682 683 684

                this._dragging = false;
                this._track = [];
            }
        }
    };

    /**
     * key: brushType
     * @type {Object}
     */
    var coverRenderers = {

        line: {
P
pah100 已提交
685
            createCover: function (controller, brushOption) {
P
pah100 已提交
686
                var cover = new graphic.Group();
P
pah100 已提交
687

P
pah100 已提交
688
                createBaseRect(controller, cover, brushOption);
P
pah100 已提交
689

P
pah100 已提交
690 691
                return cover;
            },
P
pah100 已提交
692 693
            getCreatingRange: function (track) {
                var ends = getTrackEnds(track);
P
pah100 已提交
694 695 696 697 698
                var min = mathMin(ends[0][0], ends[1][0]);
                var max = mathMax(ends[0][0], ends[1][0]);

                return [min, max];
            },
P
pah100 已提交
699 700
            updateCoverShape: function (controller, cover, localRange, brushOption) {
                var width = brushOption.brushStyle.width;
P
pah100 已提交
701
                cover.childOfName('rect').setShape({
P
pah100 已提交
702
                    x: localRange[0],
P
pah100 已提交
703
                    y: -width / 2,
P
pah100 已提交
704
                    width: localRange[1] - localRange[0],
P
pah100 已提交
705 706
                    height: width
                });
P
pah100 已提交
707 708
            },
            updateCommon: updateCommon
P
pah100 已提交
709 710 711
        },

        rect: {
P
pah100 已提交
712
            createCover: function (controller, brushOption) {
P
pah100 已提交
713 714
                var cover = new graphic.Group();

P
pah100 已提交
715
                createBaseRect(controller, cover, brushOption);
P
pah100 已提交
716

P
pah100 已提交
717
                each(
P
pah100 已提交
718 719 720 721
                    ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'],
                    function (name) {
                        cover.add(new graphic.Rect({
                            name: name,
P
pah100 已提交
722
                            __cursor: CURSOR_MAP[name] + '-resize',
P
pah100 已提交
723 724
                            style: {opacity: 0},
                            draggable: true,
P
pah100 已提交
725 726
                            drift: curry(driftRect, controller, cover, name),
                            ondragend: curry(trigger, controller, {isEnd: true})
P
pah100 已提交
727
                        }));
P
pah100 已提交
728
                    }
P
pah100 已提交
729 730 731 732
                );

                return cover;
            },
P
pah100 已提交
733 734
            getCreatingRange: function (track) {
                var ends = getTrackEnds(track);
P
pah100 已提交
735 736
                return formatRectRange(ends[1][0], ends[1][1], ends[0][0], ends[0][1]);
            },
P
pah100 已提交
737 738
            updateCoverShape: function (controller, cover, localRange, brushOption) {
                var lineWidth = brushOption.brushStyle.lineWidth || 0;
P
pah100 已提交
739
                var handleSize = mathMax(lineWidth, MIN_RESIZE_LINE_WIDTH);
P
pah100 已提交
740 741
                var x = localRange[0][0];
                var y = localRange[1][0];
P
pah100 已提交
742 743
                var xa = x - lineWidth / 2;
                var ya = y - lineWidth / 2;
P
pah100 已提交
744 745
                var x2 = localRange[0][1];
                var y2 = localRange[1][1];
P
pah100 已提交
746 747 748 749 750 751 752 753 754
                var x2a = x2 - handleSize + lineWidth / 2;
                var y2a = y2 - handleSize + lineWidth / 2;
                var width = x2 - x;
                var height = y2 - y;
                var widtha = width + lineWidth;
                var heighta = height + lineWidth;

                updateRectShape(cover, 'rect', x, y, width, height);

P
pah100 已提交
755
                if (brushOption.transformable) {
P
pah100 已提交
756 757 758 759 760 761 762 763 764 765
                    updateRectShape(cover, 'w', xa, ya, handleSize, heighta);
                    updateRectShape(cover, 'e', x2a, ya, handleSize, heighta);
                    updateRectShape(cover, 'n', xa, ya, widtha, handleSize);
                    updateRectShape(cover, 's', xa, y2a, widtha, handleSize);

                    updateRectShape(cover, 'nw', xa, ya, handleSize, handleSize);
                    updateRectShape(cover, 'ne', x2a, ya, handleSize, handleSize);
                    updateRectShape(cover, 'sw', xa, y2a, handleSize, handleSize);
                    updateRectShape(cover, 'se', x2a, y2a, handleSize, handleSize);
                }
P
pah100 已提交
766
            },
P
pah100 已提交
767 768
            updateCommon: function (controller, cover) {
                updateCommon(controller, cover);
P
pah100 已提交
769 770 771 772 773 774 775 776 777
                var transformable = cover.__brushOption.transformable;
                each(
                    ['w', 'e', 'n', 's', 'se', 'sw', 'ne', 'nw'],
                    function (name) {
                        var el = cover.childOfName(name);
                        el.attr({
                            silent: !transformable,
                            cursor: transformable ? el.__cursor : 'default'
                        });
P
pah100 已提交
778
                    }
P
pah100 已提交
779
                );
P
pah100 已提交
780 781 782 783
            }
        },

        polygon: {
P
pah100 已提交
784
            createCover: function (controller, brushOption) {
P
pah100 已提交
785 786 787 788
                var cover = new graphic.Group();

                // Do not use graphic.Polygon because graphic.Polyline do not close the
                // border of the shape when drawing, which is a better experience for user.
P
pah100 已提交
789
                cover.add(new graphic.Polyline({
P
pah100 已提交
790
                    style: makeStyle(brushOption),
P
pah100 已提交
791 792
                    silent: true
                }));
P
pah100 已提交
793 794 795

                return cover;
            },
P
pah100 已提交
796 797
            getCreatingRange: function (track) {
                return track;
P
pah100 已提交
798
            },
P
pah100 已提交
799
            endCreating: function (controller, cover) {
P
pah100 已提交
800
                cover.remove(cover.childAt(0));
P
pah100 已提交
801 802 803
                // Use graphic.Polygon close the shape.
                cover.add(new graphic.Polygon({
                    draggable: true,
P
pah100 已提交
804 805
                    drift: curry(driftPolygon, controller, cover),
                    ondragend: curry(trigger, controller, {isEnd: true})
P
pah100 已提交
806
                }));
P
pah100 已提交
807
            },
P
pah100 已提交
808 809
            updateCoverShape: function (controller, cover, localRange, brushOption) {
                cover.childAt(0).setShape({points: localRange});
P
pah100 已提交
810 811
            },
            updateCommon: updateCommon
P
pah100 已提交
812 813 814 815 816
        }
    };

    return BrushController;
});