UNPKG

20.1 kBJavaScriptView Raw
1(function webpackUniversalModuleDefinition(root, factory) {
2 if(typeof exports === 'object' && typeof module === 'object')
3 module.exports = factory();
4 else if(typeof define === 'function' && define.amd)
5 define([], factory);
6 else if(typeof exports === 'object')
7 exports["Brush"] = factory();
8 else
9 root["Brush"] = factory();
10})(this, function() {
11return /******/ (function(modules) { // webpackBootstrap
12/******/ // The module cache
13/******/ var installedModules = {};
14/******/
15/******/ // The require function
16/******/ function __webpack_require__(moduleId) {
17/******/
18/******/ // Check if module is in cache
19/******/ if(installedModules[moduleId]) {
20/******/ return installedModules[moduleId].exports;
21/******/ }
22/******/ // Create a new module (and put it into the cache)
23/******/ var module = installedModules[moduleId] = {
24/******/ i: moduleId,
25/******/ l: false,
26/******/ exports: {}
27/******/ };
28/******/
29/******/ // Execute the module function
30/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31/******/
32/******/ // Flag the module as loaded
33/******/ module.l = true;
34/******/
35/******/ // Return the exports of the module
36/******/ return module.exports;
37/******/ }
38/******/
39/******/
40/******/ // expose the modules object (__webpack_modules__)
41/******/ __webpack_require__.m = modules;
42/******/
43/******/ // expose the module cache
44/******/ __webpack_require__.c = installedModules;
45/******/
46/******/ // define getter function for harmony exports
47/******/ __webpack_require__.d = function(exports, name, getter) {
48/******/ if(!__webpack_require__.o(exports, name)) {
49/******/ Object.defineProperty(exports, name, {
50/******/ configurable: false,
51/******/ enumerable: true,
52/******/ get: getter
53/******/ });
54/******/ }
55/******/ };
56/******/
57/******/ // getDefaultExport function for compatibility with non-harmony modules
58/******/ __webpack_require__.n = function(module) {
59/******/ var getter = module && module.__esModule ?
60/******/ function getDefault() { return module['default']; } :
61/******/ function getModuleExports() { return module; };
62/******/ __webpack_require__.d(getter, 'a', getter);
63/******/ return getter;
64/******/ };
65/******/
66/******/ // Object.prototype.hasOwnProperty.call
67/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
68/******/
69/******/ // __webpack_public_path__
70/******/ __webpack_require__.p = "";
71/******/
72/******/ // Load entry module and return exports
73/******/ return __webpack_require__(__webpack_require__.s = 0);
74/******/ })
75/************************************************************************/
76/******/ ([
77/* 0 */
78/***/ (function(module, exports, __webpack_require__) {
79
80/**
81 * g2-brush
82 * @author sima.zhang1990@gmail.com
83 */
84var Brush = __webpack_require__(1);
85module.exports = Brush;
86
87/***/ }),
88/* 1 */
89/***/ (function(module, exports, __webpack_require__) {
90
91function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
92
93/**
94 * g2-brush
95 * @author sima.zhang1990@gmail.com
96 */
97var Util = __webpack_require__(2);
98var BRUSH_TYPES = ['X', 'Y', 'XY', 'POLYGON'];
99
100var Brush = function () {
101 function Brush(cfg) {
102 _classCallCheck(this, Brush);
103
104 /**
105 * keep the first mousedown point
106 * @type {object}
107 */
108 this.startPoint = null;
109 /**
110 * keep the brush state
111 * @type {Boolean}
112 */
113 this.brushing = false;
114 /**
115 * keep the drag state
116 * @type {Boolean}
117 */
118 this.dragging = false;
119 /**
120 * the brush shape
121 * @type {G.Shape}
122 */
123 this.brushShape = null;
124 /**
125 * the brush container
126 * @type {G.Group}
127 */
128 this.container = null;
129 /**
130 * keep polygon path
131 * @type {String}
132 */
133 this.polygonPath = null;
134 /**
135 * brush style
136 * @type {Object}
137 */
138 this.style = {
139 fill: '#C5D4EB',
140 opacity: 0.3,
141 lineWidth: 1,
142 stroke: '#82A6DD'
143 };
144 /**
145 * brush type
146 * @type {string}
147 */
148 this.type = 'XY';
149 /**
150 * is brushShape can be dragable, default is false
151 * @type {Boolean}
152 */
153 this.dragable = false;
154 this.dragoffX = 0;
155 this.dragoffY = 0;
156 /**
157 * is limited in plot, default value is true
158 * @type {Boolean}
159 */
160 this.inPlot = true;
161 /**
162 * xField
163 * @type {string}
164 */
165 this.xField = null;
166 /**
167 * yFiels
168 * @type {string}
169 */
170 this.yField = null;
171 /**
172 * Whether to filter the data,default is true
173 * @type {Boolean}
174 */
175 this.filter = !cfg.dragable;
176 this.onBrushstart = null;
177 this.onBrushmove = null;
178 this.onBrushend = null;
179 this.onDragstart = null;
180 this.onDragmove = null;
181 this.onDragend = null;
182
183 this._init(cfg);
184 }
185
186 Brush.prototype._init = function _init(cfg) {
187 Util.mix(this, cfg);
188 this.type = this.type.toUpperCase();
189 if (BRUSH_TYPES.indexOf(this.type) === -1) {
190 this.type = 'XY';
191 }
192 var canvas = this.canvas;
193 if (canvas) {
194 var plotRange = void 0;
195 canvas.get('children').map(function (child) {
196 if (child.get('type') === 'plotBack') {
197 plotRange = child.get('plotRange');
198 return false;
199 }
200 return child;
201 });
202 this.plot = {
203 start: plotRange.bl,
204 end: plotRange.tr
205 };
206
207 this.bindCanvasEvent();
208 }
209
210 if (this.chart) {
211 var chart = this.chart;
212 var coord = chart.get('coord');
213 this.plot = {
214 start: coord.start,
215 end: coord.end
216 };
217 var xScales = chart._getScales('x');
218 var yScales = chart._getScales('y');
219 this.xScale = this.xField ? xScales[this.xField] : chart.getXScale();
220 this.yScale = this.yField ? yScales[this.yField] : chart.getYScales()[0];
221 }
222 };
223
224 Brush.prototype.clearEvents = function clearEvents() {
225 this.onMouseDownListener && this.onMouseDownListener.remove();
226 this.onMouseMoveListener && this.onMouseMoveListener.remove();
227 this.onMouseupListener && this.onMouseupListener.remove();
228 };
229
230 Brush.prototype.bindCanvasEvent = function bindCanvasEvent() {
231 var canvas = this.canvas;
232
233 var canvasDOM = canvas.get('canvasDOM');
234 this.clearEvents();
235 this.onMouseDownListener = Util.addEventListener(canvasDOM, 'mousedown', Util.wrapBehavior(this, '_onCanvasMouseDown'));
236 this.onMouseMoveListener = Util.addEventListener(canvasDOM, 'mousemove', Util.wrapBehavior(this, '_onCanvasMouseMove'));
237 this.onMouseUpListener = Util.addEventListener(canvasDOM, 'mouseup', Util.wrapBehavior(this, '_onCanvasMouseUp'));
238 };
239
240 Brush.prototype._onCanvasMouseDown = function _onCanvasMouseDown(ev) {
241 var me = this;
242 var canvas = me.canvas,
243 type = me.type,
244 brushShape = me.brushShape;
245
246
247 if (!type) {
248 return;
249 }
250
251 var startPoint = { x: ev.offsetX, y: ev.offsetY };
252 var isInPlot = me.plot && me.inPlot;
253 var canvasDOM = canvas.get('canvasDOM');
254 var pixelRatio = canvas.get('pixelRatio');
255
256 if (me.selection) {
257 me.selection = null;
258 }
259
260 if (me.dragable && brushShape && !brushShape.get('destroyed')) {
261 // allow drag the brushShape
262 if (brushShape.isHit(startPoint.x * pixelRatio, startPoint.y * pixelRatio)) {
263 canvasDOM.style.cursor = 'move';
264 me.selection = brushShape;
265 me.dragging = true;
266 if (type === 'X') {
267 me.dragoffX = startPoint.x - brushShape.attr('x');
268 me.dragoffY = 0;
269 } else if (type === 'Y') {
270 me.dragoffX = 0;
271 me.dragoffY = startPoint.y - brushShape.attr('y');
272 } else if (type === 'XY') {
273 me.dragoffX = startPoint.x - brushShape.attr('x');
274 me.dragoffY = startPoint.y - brushShape.attr('y');
275 } else if (type === 'POLYGON') {
276 var box = brushShape.getBBox();
277 me.dragoffX = startPoint.x - box.minX;
278 me.dragoffY = startPoint.y - box.minY;
279 }
280
281 if (isInPlot) {
282 me.selection.attr('clip', canvas.addShape('rect', {
283 attrs: {
284 x: this.plot.start.x,
285 y: this.plot.end.y,
286 width: this.plot.end.x - this.plot.start.x,
287 height: this.plot.start.y - this.plot.end.y,
288 fill: '#fff',
289 fillOpacity: 0
290 }
291 }));
292 }
293 me.onDragstart && me.onDragstart(ev);
294 }
295 me.prePoint = startPoint;
296 }
297
298 if (!me.dragging) {
299 // brush start
300 me.onBrushstart && me.onBrushstart(startPoint);
301 var container = me.container;
302 if (isInPlot) {
303 var _me$plot = me.plot,
304 start = _me$plot.start,
305 end = _me$plot.end;
306
307 if (startPoint.x < start.x || startPoint.x > end.x || startPoint.y < end.y || startPoint.y > start.y) {
308 return;
309 }
310 }
311 canvasDOM.style.cursor = 'crosshair';
312 me.startPoint = startPoint;
313 me.brushShape = null;
314 me.brushing = true;
315
316 if (!container) {
317 container = canvas.addGroup({
318 zIndex: 5 // upper
319 });
320 container.initTransform();
321 } else {
322 container.clear();
323 }
324 me.container = container;
325
326 if (type === 'POLYGON') {
327 me.polygonPath = 'M ' + startPoint.x + ' ' + startPoint.y;
328 }
329 }
330 };
331
332 Brush.prototype._onCanvasMouseMove = function _onCanvasMouseMove(ev) {
333 var me = this;
334 var brushing = me.brushing,
335 dragging = me.dragging,
336 type = me.type,
337 plot = me.plot,
338 startPoint = me.startPoint,
339 xScale = me.xScale,
340 yScale = me.yScale,
341 canvas = me.canvas;
342
343
344 if (!brushing && !dragging) {
345 return;
346 }
347 var currentPoint = {
348 x: ev.offsetX,
349 y: ev.offsetY
350 };
351 var canvasDOM = canvas.get('canvasDOM');
352
353 if (brushing) {
354 canvasDOM.style.cursor = 'crosshair';
355 var start = plot.start,
356 end = plot.end;
357
358 var polygonPath = me.polygonPath;
359 var brushShape = me.brushShape;
360 var container = me.container;
361 if (me.plot && me.inPlot) {
362 currentPoint = me._limitCoordScope(currentPoint);
363 }
364
365 var rectStartX = void 0;
366 var rectStartY = void 0;
367 var rectWidth = void 0;
368 var rectHeight = void 0;
369
370 if (type === 'Y') {
371 rectStartX = start.x;
372 rectStartY = currentPoint.y >= startPoint.y ? startPoint.y : currentPoint.y;
373 rectWidth = Math.abs(start.x - end.x);
374 rectHeight = Math.abs(startPoint.y - currentPoint.y);
375 } else if (type === 'X') {
376 rectStartX = currentPoint.x >= startPoint.x ? startPoint.x : currentPoint.x;
377 rectStartY = end.y;
378 rectWidth = Math.abs(startPoint.x - currentPoint.x);
379 rectHeight = Math.abs(end.y - start.y);
380 } else if (type === 'XY') {
381 if (currentPoint.x >= startPoint.x) {
382 rectStartX = startPoint.x;
383 rectStartY = currentPoint.y >= startPoint.y ? startPoint.y : currentPoint.y;
384 } else {
385 rectStartX = currentPoint.x;
386 rectStartY = currentPoint.y >= startPoint.y ? startPoint.y : currentPoint.y;
387 }
388 rectWidth = Math.abs(startPoint.x - currentPoint.x);
389 rectHeight = Math.abs(startPoint.y - currentPoint.y);
390 } else if (type === 'POLYGON') {
391 polygonPath += 'L ' + currentPoint.x + ' ' + currentPoint.y;
392 me.polygonPath = polygonPath;
393 if (!brushShape) {
394 brushShape = container.addShape('path', {
395 attrs: Util.mix(me.style, {
396 path: polygonPath
397 })
398 });
399 } else {
400 !brushShape.get('destroyed') && brushShape.attr(Util.mix({}, brushShape.__attrs, {
401 path: polygonPath
402 }));
403 }
404 }
405 if (type !== 'POLYGON') {
406 if (!brushShape) {
407 brushShape = container.addShape('rect', {
408 attrs: Util.mix(me.style, {
409 x: rectStartX,
410 y: rectStartY,
411 width: rectWidth,
412 height: rectHeight
413 })
414 });
415 } else {
416 !brushShape.get('destroyed') && brushShape.attr(Util.mix({}, brushShape.__attrs, {
417 x: rectStartX,
418 y: rectStartY,
419 width: rectWidth,
420 height: rectHeight
421 }));
422 }
423 }
424
425 me.brushShape = brushShape;
426 } else if (dragging) {
427 canvasDOM.style.cursor = 'move';
428 var selection = me.selection;
429 if (selection && !selection.get('destroyed')) {
430 if (type === 'POLYGON') {
431 var prePoint = me.prePoint;
432 me.selection.translate(currentPoint.x - prePoint.x, currentPoint.y - prePoint.y);
433 } else {
434 me.dragoffX && selection.attr('x', currentPoint.x - me.dragoffX);
435 me.dragoffY && selection.attr('y', currentPoint.y - me.dragoffY);
436 }
437 }
438 }
439
440 me.prePoint = currentPoint;
441 canvas.draw();
442
443 var _me$_getSelected = me._getSelected(),
444 data = _me$_getSelected.data,
445 shapes = _me$_getSelected.shapes,
446 xValues = _me$_getSelected.xValues,
447 yValues = _me$_getSelected.yValues;
448
449 var eventObj = {
450 data: data,
451 shapes: shapes,
452 x: currentPoint.x,
453 y: currentPoint.y
454 };
455
456 if (xScale) {
457 eventObj[xScale.field] = xValues;
458 }
459 if (yScale) {
460 eventObj[yScale.field] = yValues;
461 }
462 me.onDragmove && me.onDragmove(eventObj);
463 me.onBrushmove && me.onBrushmove(eventObj);
464 };
465
466 Brush.prototype._onCanvasMouseUp = function _onCanvasMouseUp(ev) {
467 var me = this;
468 var data = me.data,
469 shapes = me.shapes,
470 xValues = me.xValues,
471 yValues = me.yValues,
472 canvas = me.canvas,
473 type = me.type,
474 startPoint = me.startPoint,
475 chart = me.chart,
476 container = me.container,
477 xScale = me.xScale,
478 yScale = me.yScale;
479 var offsetX = ev.offsetX,
480 offsetY = ev.offsetY;
481
482 var canvasDOM = canvas.get('canvasDOM');
483 canvasDOM.style.cursor = 'default';
484
485 if (Math.abs(startPoint.x - offsetX) <= 1 && Math.abs(startPoint.y - offsetY) <= 1) {
486 // 防止点击事件
487 me.brushing = false;
488 me.dragging = false;
489 return;
490 }
491
492 var eventObj = {
493 data: data,
494 shapes: shapes,
495 x: offsetX,
496 y: offsetY
497 };
498 if (xScale) {
499 eventObj[xScale.field] = xValues;
500 }
501 if (yScale) {
502 eventObj[yScale.field] = yValues;
503 }
504
505 if (me.dragging) {
506 me.dragging = false;
507 me.onDragend && me.onDragend(eventObj);
508 } else if (me.brushing) {
509 me.brushing = false;
510 var brushShape = me.brushShape;
511 var polygonPath = me.polygonPath;
512
513 if (type === 'POLYGON') {
514 polygonPath += 'z';
515
516 brushShape && !brushShape.get('destroyed') && brushShape.attr(Util.mix({}, brushShape.__attrs, {
517 path: polygonPath
518 }));
519 me.polygonPath = polygonPath;
520 canvas.draw();
521 }
522
523 if (me.onBrushend) {
524 me.onBrushend(eventObj);
525 } else if (chart && me.filter) {
526 container.clear(); // clear the brush
527 // filter data
528 if (type === 'X') {
529 xScale && chart.filter(xScale.field, function (val) {
530 return xValues.indexOf(val) > -1;
531 });
532 } else if (type === 'Y') {
533 yScale && chart.filter(yScale.field, function (val) {
534 return yValues.indexOf(val) > -1;
535 });
536 } else {
537 xScale && chart.filter(xScale.field, function (val) {
538 return xValues.indexOf(val) > -1;
539 });
540 yScale && chart.filter(yScale.field, function (val) {
541 return yValues.indexOf(val) > -1;
542 });
543 }
544 chart.repaint();
545 }
546 }
547 };
548
549 Brush.prototype.setType = function setType(type) {
550 if (!type) {
551 return;
552 }
553
554 this.type = type.toUpperCase();
555 };
556
557 Brush.prototype.destroy = function destroy() {
558 this.clearEvents();
559 };
560
561 Brush.prototype._limitCoordScope = function _limitCoordScope(point) {
562 var plot = this.plot;
563 var start = plot.start,
564 end = plot.end;
565
566
567 if (point.x < start.x) {
568 point.x = start.x;
569 }
570 if (point.x > end.x) {
571 point.x = end.x;
572 }
573 if (point.y < end.y) {
574 point.y = end.y;
575 }
576 if (point.y > start.y) {
577 point.y = start.y;
578 }
579 return point;
580 };
581
582 Brush.prototype._getSelected = function _getSelected() {
583 var chart = this.chart,
584 xScale = this.xScale,
585 yScale = this.yScale,
586 brushShape = this.brushShape,
587 canvas = this.canvas;
588
589 var pixelRatio = canvas.get('pixelRatio');
590 var selectedShapes = [];
591 var xValues = [];
592 var yValues = [];
593 var selectedData = [];
594 if (chart) {
595 var geoms = chart.get('geoms');
596 geoms.map(function (geom) {
597 var shapes = geom.getShapes();
598 shapes.map(function (shape) {
599 var shapeData = shape.get('origin');
600 if (!Array.isArray(shapeData)) {
601 // 线图、区域图等
602 shapeData = [shapeData];
603 }
604
605 shapeData.map(function (each) {
606 if (brushShape.isHit(each.x * pixelRatio, each.y * pixelRatio)) {
607 selectedShapes.push(shape);
608 var origin = each._origin;
609 selectedData.push(origin);
610 xScale && xValues.push(origin[xScale.field]);
611 yScale && yValues.push(origin[yScale.field]);
612 }
613 return each;
614 });
615
616 return shape;
617 });
618 return geom;
619 });
620 }
621 this.shapes = selectedShapes;
622 this.xValues = xValues;
623 this.yValues = yValues;
624 this.data = selectedData;
625 return {
626 data: selectedData,
627 xValues: xValues,
628 yValues: yValues,
629 shapes: selectedShapes
630 };
631 };
632
633 return Brush;
634}();
635
636module.exports = Brush;
637
638/***/ }),
639/* 2 */
640/***/ (function(module, exports) {
641
642function _mix(dist, obj) {
643 for (var k in obj) {
644 if (obj.hasOwnProperty(k) && k !== 'constructor' && obj[k] !== undefined) {
645 dist[k] = obj[k];
646 }
647 }
648}
649
650var Util = {
651 mix: function mix(dist, obj1, obj2, obj3) {
652 if (obj1) {
653 _mix(dist, obj1);
654 }
655
656 if (obj2) {
657 _mix(dist, obj2);
658 }
659
660 if (obj3) {
661 _mix(dist, obj3);
662 }
663 return dist;
664 },
665
666 /**
667 * 添加事件监听器
668 * @param {Object} target DOM对象
669 * @param {String} eventType 事件名
670 * @param {Funtion} callback 回调函数
671 * @return {Object} 返回对象
672 */
673 addEventListener: function addEventListener(target, eventType, callback) {
674 if (target.addEventListener) {
675 target.addEventListener(eventType, callback, false);
676 return {
677 remove: function remove() {
678 target.removeEventListener(eventType, callback, false);
679 }
680 };
681 } else if (target.attachEvent) {
682 target.attachEvent('on' + eventType, callback);
683 return {
684 remove: function remove() {
685 target.detachEvent('on' + eventType, callback);
686 }
687 };
688 }
689 },
690
691 /**
692 * 封装事件,便于使用上下文this,和便于解除事件时使用
693 * @protected
694 * @param {Object} obj 对象
695 * @param {String} action 事件名称
696 * @return {Function} 返回事件处理函数
697 */
698 wrapBehavior: function wrapBehavior(obj, action) {
699 if (obj['_wrap_' + action]) {
700 return obj['_wrap_' + action];
701 }
702 var method = function method(e) {
703 obj[action](e);
704 };
705 obj['_wrap_' + action] = method;
706 return method;
707 },
708
709 /**
710 * 获取封装的事件
711 * @protected
712 * @param {Object} obj 对象
713 * @param {String} action 事件名称
714 * @return {Function} 返回事件处理函数
715 */
716 getWrapBehavior: function getWrapBehavior(obj, action) {
717 return obj['_wrap_' + action];
718 }
719};
720
721module.exports = Util;
722
723/***/ })
724/******/ ]);
725});
\No newline at end of file