UNPKG

chartx

Version:

Data Visualization Chart Library

1,267 lines (1,204 loc) 136 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray")); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn")); var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf")); var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits")); var _canvax = _interopRequireDefault(require("canvax")); var _tools = require("../../../utils/tools"); var _text = require("../../../utils/text"); var _index = _interopRequireDefault(require("../index")); var _zoom = _interopRequireDefault(require("../../../utils/zoom")); var _scroll = _interopRequireDefault(require("./scroll")); var _color = require("../../../utils/color"); var _popover2 = _interopRequireDefault(require("../../../components/popover")); var _tableDataFrame = _interopRequireDefault(require("../../../core/tableDataFrame")); var _format = _interopRequireDefault(require("../../../utils/format")); function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _callSuper(t, o, e) { return o = (0, _getPrototypeOf2.default)(o), (0, _possibleConstructorReturn2.default)(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], (0, _getPrototypeOf2.default)(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); } /** * 1, 虚拟滚动,目前测试数据量10000条,滚动流畅 * 2,canvax离屏渲染 * 3,Text文本的离屏渲染( 有效问题,提供是否开启 ) */ /** * 给到外部调用的方法 * refreshAllCellStyle 刷新所有单元格样式 * renderTable 渲染表格 * draw 重新计算布局然后重新绘制 */ var _ = _canvax.default._, event = _canvax.default.event; var animation = _canvax.default.animation; var Rect = _canvax.default.Shapes.Rect; var Line = _canvax.default.Shapes.Line; var BrokenLine = _canvax.default.Shapes.BrokenLine; function isParent(b, a) { var maxDepth = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1000; if (!a || !b) return false; var depth = 0; var current = a.parent; while (current && depth < maxDepth) { if (current === b) return true; current = current.parent; depth++; } return false; } var TableGraphs = /*#__PURE__*/function (_GraphsBase) { function TableGraphs(opt, app) { var _this; (0, _classCallCheck2.default)(this, TableGraphs); _this = _callSuper(this, TableGraphs, [opt, app]); _this.type = "table"; _.extend(true, _this, (0, _tools.getDefaultProps)(TableGraphs.defaultProps()), opt); _this.initOptHandle(); _this.init(); _this.initScroll(); window.d = performance.now(); window.table = _this; _this._activeCellPopover = new _popover2.default(_this.activeCellPopoverInfo, _this.app); return _this; } (0, _inherits2.default)(TableGraphs, _GraphsBase); return (0, _createClass2.default)(TableGraphs, [{ key: "initOptHandle", value: function initOptHandle(opt) { //外部调用的时候会有opt if (opt) { _.extend(true, this, opt); } if (!this.columns) { this.columns = [Object.keys(this.dataFrame.list[0] || {}).map(function (key) { return { field: key, content: key, width: 'auto' }; })]; } else { var _columns = this.columns; if (!Array.isArray(_columns[0])) { _columns = [_columns]; } var newColumns = []; _columns.forEach(function (columnsRowData, rowInd) { var rowColumns = columnsRowData.map(function (cellData) { return _objectSpread(_objectSpread({}, cellData), {}, { field: cellData.field, content: cellData.text || cellData.content || cellData.title || cellData.field, width: cellData.width || 'auto' }); }); newColumns.push(rowColumns); }); this.columns = newColumns; } if (this.showIndexCol) { this.columns[0].unshift({ field: '_index', title: '', rowspan: this.columns.length, width: 30 }); this.dataFrame.list.forEach(function (row, index) { row._index = index + 1; }); this.leftColSticky++; } } }, { key: "init", value: function init() { var me = this; var width = this.width, height = this.height; if (!width) { width = this.app.width; } if (!height) { height = this.app.height; } var borderLineWidth = this.style.border.width; var _width = width - borderLineWidth; var _height = height - borderLineWidth; var _x = 0; var _y = 0; this.induce = new Rect({ id: 'induce', context: { x: _x, y: _y, width: _width, height: _height, lineWidth: borderLineWidth, strokeStyle: this.style.border.color, radius: this.style.border.radius, fillStyle: 'rgba(0,0,0,0)' } }); this.sprite.addChild(this.induce); //监听事件, 不做任何处理,主要用来冒泡到sprite this.induce.on(event.types.get(), function (e) { var scrollState = me.scroll.getState(); var point = { x: e.point.x + scrollState.scrollLeft, y: e.point.y + scrollState.scrollTop }; var cell; e.preventDefault(); var _contextmenu = me.app.getComponent({ name: 'contextmenu' }); var eventIsInPopover = false; if (me.app.canvax.domView !== e.srcElement && me.app.canvax.domView.contains(e.srcElement)) { eventIsInPopover = true; } if (!(_contextmenu && _contextmenu.isShow || eventIsInPopover)) { cell = me._getTargetCell(point); if (e.type == 'mousedown') { if (!cell) { return; } //判断是否按住了command键或ctrl键,如果没有则清空选中 //cell = me._getTargetCell( point ) if (cell.type == 'th' && cell.col.colIndex == 0 && me.showIndexCol) { //如果之前有全选,就删除掉 checkedAll为true的选项,如果没有就加一个 checkedAll为true的选项 var checkedAll = me.selected.allrows.checkedAll; me.activeCellId = null; me.unselect(); if (!checkedAll) { me.select({ type: 'allrows', checkedAll: !checkedAll, excludeCellIds: [] }); } } else { var cellRowIsSelected = me.checkRowIsSelected(cell.row); me.induce.toFront(); if (me.activeCellId) { var activeCellId = me.activeCellId; me.activeCellId = null; if ((e.metaKey || e.ctrlKey) && cell.type == 'td' && cell.field != '_index') { me.select({ type: 'cell', cellIds: [activeCellId] }); } } if (cell) { if (cell.field == '_index') { if (cell.type == 'td') { if (!cellRowIsSelected) { var currRowInd = cell.row.cells.findIndex(function (_cell) { return _cell == cell; }); var nextCell = cell.row.cells[currRowInd + 1]; me.activeCellId = nextCell.id; me.select({ type: 'row', rowId: cell.row.id }); } else { me.activeCellId = null; me.unselect({ type: 'row', rowId: cell.row.id }); } } else { if (!(e.metaKey || e.ctrlKey)) { me.unselect(); } } } else { me.activeCellId = cell.id; if (!(e.metaKey || e.ctrlKey)) { me.unselect(); } } if (cell.field != '_index') { me._dragBeginPoint = point; me._dragBeginCell = cell; } if (cell.type == 'th') { me.select({ type: 'col', colCellId: cell.id }); } } me.refreshAllCellStyle(); } } if (e.type == 'mouseup') { var _me$_dragSelectedCell; me.induce.toBack(); if (me._dragBeginCell && me._dragBeginCell.type == 'th') { if (cell.col.colIndex >= me.leftColSticky) { var transposDirection = 'left'; //如果中心偏右,则把point的x坐标设置为cell的x坐标+cell的宽度 if (point.x > cell.position.x + cell.size.width / 2) { transposDirection = 'right'; } // let columns = me.layoutData.rowData.columns.rows.find( row => row.cells.find( cell => cell.field == me._dragBeginCell.field ) ) // if( columns ){ // // 找到目标cell在columns中的索引 // let targetIndex = columns.cells.findIndex(col => col.field == cell.field); // let transposIndex = columns.cells.findIndex(col => col.field == me._dragBeginCell.field); // if (targetIndex !== -1 && transposIndex !== -1 && targetIndex !== transposIndex) { // // 先移除要移动的列 // let [movedCol] = columns.cells.splice(transposIndex, 1); // // 计算插入位置 // let insertIndex = targetIndex; // if (transposDirection === 'right') { // // 如果是右侧插入,且原位置在目标前面,插入索引要+1 // insertIndex = targetIndex + (transposIndex < targetIndex ? 0 : 1); // } else { // // left,插入到目标前面 // insertIndex = targetIndex + (transposIndex < targetIndex ? -1 : 0); // } // columns.cells.splice(insertIndex, 0, movedCol); // // 更新每一个cell的colIndex // columns.cells.forEach((cell, idx) => { // cell.col.colIndex = idx; // }); // me.renderTable() // } // } // debugger //把 _transposCell 的字段插入到 columns 的 cell 的 transposDirection 位置 var _columns2 = me.columns.find(function (columnGroup) { return columnGroup.find(function (column) { return column.field == me._dragBeginCell.field; }); }); if (_columns2) { // 找到目标cell在columns中的索引 var targetIndex = _columns2.findIndex(function (col) { return col.field == cell.field; }); var transposIndex = _columns2.findIndex(function (col) { return col.field == me._dragBeginCell.field; }); if (targetIndex !== -1 && transposIndex !== -1 && targetIndex !== transposIndex) { // 先移除要移动的列 var _columns2$splice = _columns2.splice(transposIndex, 1), _columns2$splice2 = (0, _slicedToArray2.default)(_columns2$splice, 1), movedCol = _columns2$splice2[0]; // 计算插入位置 var insertIndex = targetIndex; if (transposDirection === 'right') { // 如果是右侧插入,且原位置在目标前面,插入索引要-1 insertIndex = targetIndex + (transposIndex < targetIndex ? 0 : 1); } else { // left,插入到目标前面 insertIndex = targetIndex + (transposIndex < targetIndex ? -1 : 0); } _columns2.splice(insertIndex, 0, movedCol); // 触发表格重绘或相关更新 me.draw(); me.action({ type: 'transposColumn', info: { column: cell.col, movedCol: movedCol, transposIndex: transposIndex, targetIndex: targetIndex, transposDirection: transposDirection, columns: _columns2 } }); } } } } me._dragBeginPoint = null; me._dragBeginCell = null; if ((_me$_dragSelectedCell = me._dragSelectedCells) !== null && _me$_dragSelectedCell !== void 0 && _me$_dragSelectedCell.length) { me.select({ type: 'cell', cellIds: me._dragSelectedCells.map(function (item) { return item.id; }) }); } me._dragSelectedCells = []; // me._rectCloneImg.destroy() // me._rectCloneImg = null var transposThRect_clone = me.graphsView.getChildById('transposThRect_clone'); if (transposThRect_clone) { transposThRect_clone.destroy(); } var dragSplitLine = me.graphsView.getChildById('dragSplitLine'); if (dragSplitLine) { dragSplitLine.destroy(); } } if (e.type == 'mouseout') { var _me$_dragSelectedCell2; me.induce.toBack(); me._dragBeginPoint = null; me._dragBeginCell = null; if ((_me$_dragSelectedCell2 = me._dragSelectedCells) !== null && _me$_dragSelectedCell2 !== void 0 && _me$_dragSelectedCell2.length) { me.select({ type: 'cell', cellIds: me._dragSelectedCells.map(function (item) { return item.id; }) }); } me._dragSelectedCells = []; // me._rectCloneImg.destroy() // me._rectCloneImg = null var _transposThRect_clone = me.graphsView.getChildById('transposThRect_clone'); if (_transposThRect_clone) { _transposThRect_clone.destroy(); } var _dragSplitLine = me.graphsView.getChildById('dragSplitLine'); if (_dragSplitLine) { _dragSplitLine.destroy(); } } if (e.type == 'mousemove') { //在表格中按下了,开始拖拽鼠标 if (me._dragBeginPoint) { if (me._dragBeginCell.type == 'td') { //首先把原来的hover行取消掉 var preHoverRow = me._hoverRow; me._hoverRow = null; if (preHoverRow) { preHoverRow.cells.forEach(function (cell) { me._setCellStyle(cell); }); } //把前面临时选中的 me._dragSelectedCells 取消选中 me.unselect(me._dragSelectedCells); me._dragSelectedCells = []; var _scrollState = me.scroll.getState(); // 获取拖拽的起始点和当前点坐标 var startX = Math.min(me._dragBeginPoint.x, point.x); var startY = Math.min(me._dragBeginPoint.y, point.y); var endX = Math.max(me._dragBeginPoint.x, point.x); var endY = Math.max(me._dragBeginPoint.y, point.y); var selectedCells = []; // 只检查渲染范围内的数据行,表头不需要处理 for (var i = _scrollState.renderedRange.start; i <= _scrollState.renderedRange.end; i++) { var row = me.layoutData.rowData.list.rows[i]; if (row) { row.cells.forEach(function (cell) { if (cell.position.x < endX && cell.position.x + cell.size.width > startX && cell.position.y < endY && cell.position.y + cell.size.height > startY) { if (me.showIndexCol && cell.col.colIndex == 0) { //索引单元格不能拖拽选中 } else { selectedCells.push(cell); } } }); } } me.select({ type: 'cell', cellIds: selectedCells.map(function (item) { return item.id; }) }); me._dragSelectedCells = selectedCells; } if (me._dragBeginCell.type == 'th') { //拖拽表头,移动切换位置 //要创建一个和表头列一样宽的矩形,高度和当前可见的矩形最下面的td保持一致 var rectClone = me.graphsView.getChildById('transposThRect_clone'); if (!rectClone) { rectClone = new Rect({ id: 'transposThRect_clone', context: {} }); me.graphsView.addChild(rectClone); } var h = Math.min(me.app.height, scrollState.scrollHeight - scrollState.scrollTop); Object.assign(rectClone.context, { x: me._dragBeginCell.position.x + (point.x - me._dragBeginPoint.x), y: me._dragBeginCell.position.y + scrollState.scrollTop, width: me._dragBeginCell.size.width, height: h, fillStyle: "#ccc", fillAlpha: 0.4 }); var _dragSplitLine2 = me.graphsView.getChildById('dragSplitLine'); if (!_dragSplitLine2) { _dragSplitLine2 = new BrokenLine({ id: 'dragSplitLine', context: { strokeStyle: me.style.transpos.splitLineStrokeStyle, lineWidth: me.style.transpos.splitLineWidth } }); me.graphsView.addChild(_dragSplitLine2); } //如果point在cell的中心偏左,则把point的x坐标设置为cell的x坐标 var splitX = cell.position.x; //如果中心偏右,则把point的x坐标设置为cell的x坐标+cell的宽度 if (point.x > cell.position.x + cell.size.width / 2) { splitX = cell.position.x + cell.size.width; } //如果是最后一个列,splitX 还要 -1 if (cell.col.colIndex == me.columns[0].length - 1) { splitX = splitX - 1; } Object.assign(_dragSplitLine2.context, { pointList: [[splitX, me._dragBeginCell.position.y + scrollState.scrollTop], [splitX, h]] }); //如果cell.col.colIndex 在左侧锁定列的范围内,则取消dragSplitLine的显示 if (cell.col.colIndex < me.leftColSticky) { _dragSplitLine2.destroy(); } // let rectCloneImg = me._rectCloneImg // if( !rectCloneImg ){ // rectCloneImg = new Canvax.Display.Image({ // id: 'dragThRect_clone_img', // context: { // scaleX: 1/2, // scaleY: 1/2, // sx: me._dragBeginCell.position.x*2 + 4, // sy: me._dragBeginCell.position.y + 2, // sWidth:me._dragBeginCell.size.width*2, // sHeight: me._dragBeginCell.size.height*2 + 2, // x: me._dragBeginCell.position.x + ( point.x - me._dragBeginPoint.x ) + 2 , // y: me._dragBeginCell.position.y, // width: me._dragBeginCell.size.width*2 , // height: me._dragBeginCell.size.height*2 + 2, // fillStyle: me.style.tdSelected.backgroundColor, // //globalAlpha: 0.5 // } // }, me.app.stage.canvas) // me._rectCloneImg = rectCloneImg // me.graphsView.addChild( rectCloneImg ) // } else { // Object.assign( rectCloneImg.context, { // x: me._dragBeginCell.position.x + ( point.x - me._dragBeginPoint.x ) , // }) // } //这个矩形跟随鼠标移动,然后判断这个矩形是否和其它的表头列有重叠,如果有重叠,则交换位置 } } else { //非拖拽的情况下,要执行hover行的逻辑了 //先用当前鼠标的位置,获取到当前鼠标所在的行 var _row2 = me.layoutData.rowData.list.rows.find(function (row) { return row.cells.some(function (cell) { return cell.position.y < point.y && cell.position.y + cell.size.height > point.y; }); }); if (_row2 == me._hoverRow) { return; } else { //首先把原来的hover行取消掉 var _preHoverRow = me._hoverRow; me._hoverRow = _row2; if (_preHoverRow) { _preHoverRow.cells.forEach(function (cell) { me._setCellStyle(cell); }); } if (_row2) { _row2.cells.forEach(function (cell) { me._setCellStyle(cell); }); } } } } //滚轮 if (e.type == "wheel") { // 添加时间间隔检查,避免过于频繁的更新 var now = Date.now(); if (now - _lastWheelTime < 16) { // 约60fps return; } _lastWheelTime = now; if (!_ticking) { requestAnimationFrame(function () { //滚动的时候先把所有的popover 隐藏 var popover = me.app.getComponent({ name: 'popover' }); if (popover) { popover.hide(e); } if (me._activeCellPopover) { me._activeCellPopover.hide(e); } var scrollState = me.scroll.getState(); var layoutHeight = scrollState.scrollHeight; var layoutWidth = me.layoutData.rowData.columns.size.width; // 控制最大滚动距离 var maxScrollStep = me.style.cell.minHeight * (scrollState.bufferSize || 1); // 比如限制为5行的高度 var deltaY = e.deltaY; var deltaX = e.deltaX; // 限制垂直滚动的最大距离 if (Math.abs(deltaY) > maxScrollStep) { deltaY = maxScrollStep * Math.sign(deltaY); } var offsetPoint = { x: -deltaX, y: -deltaY }; // 处理水平方向,如果向左滚动,则固定列需要保持在左侧 if (me.graphsView.context.x + offsetPoint.x > me.contentX) { offsetPoint.x = me.contentX - me.graphsView.context.x; } // 处理水平方向,如果向右滚动,则固定列需要保持在右侧 // 只有当内容宽度大于视口宽度时才进行右边界限制,避免内容宽度小于视口时被强制右对齐 if (layoutWidth > scrollState.viewportWidth) { if (me.graphsView.context.x + layoutWidth + offsetPoint.x < me.contentX + scrollState.viewportWidth) { offsetPoint.x = me.contentX + scrollState.viewportWidth - (me.graphsView.context.x + layoutWidth); } } else { // 当内容宽度小于等于视口宽度时,确保表格不会滚动到右边界之外 if (me.graphsView.context.x + offsetPoint.x < me.contentX) { offsetPoint.x = me.contentX - me.graphsView.context.x; } } // 处理垂直方向,如果向上滚动,则固定列需要保持在顶部 if (me.graphsView.context.y + offsetPoint.y > me.contentY) { offsetPoint.y = me.contentY - me.graphsView.context.y; } //首先判断数据的长度比viewHeight要大 if (layoutHeight > scrollState.viewportHeight) { //处理垂直方向,如果向下滚动,则最后一行需要保持在底部 if (me.graphsView.context.y + layoutHeight + offsetPoint.y < me.contentY + scrollState.viewportHeight) { offsetPoint.y = me.contentY + scrollState.viewportHeight - (me.graphsView.context.y + layoutHeight); } } if (layoutHeight < scrollState.viewportHeight) { offsetPoint.y = 0; } var _me$zoom$offset = me.zoom.offset(offsetPoint), x = _me$zoom$offset.x, y = _me$zoom$offset.y; me.graphsView.context.x = x; me.graphsView.context.y = y; // 处理固定列和表头的位置同步 me._syncStickyElements(cell); //这个x y 中包含了初始值的偏移量的 me.style.border.width me.scroll.scrollTo(-(x - me.style.border.width), -(y - me.style.border.width)); me.updateLayoutData(); _ticking = false; }); _ticking = true; } } ; if (cell) { //从滚动状态中获取可视范围 e.eventInfo = { trigger: me, iNode: -1, //TODO:这里设置了的话,会导致多graphs里获取不到别的graphs的nodes信息了 nodes: [cell] }; //触发root统一设置e.eventInfo.nodes,所以上面不需要设置 me.app.fire(e.type, e); } } }); this.graphsView = new _canvax.default.Display.Sprite({ context: { x: _x, y: _y } }); this.sprite.addChild(this.graphsView); //设置表格的裁剪区域 var clipRect = new Rect({ context: { x: _x, y: _y, width: _width, height: _height, fillStyle: 'green', radius: this.style.border.radius } }); this.graphsView.clipTo(clipRect); this.sprite.addChild(clipRect); //主表格 this.listSp = new _canvax.default.Display.Sprite({ id: 'listSp' }); this.graphsView.addChild(this.listSp); //左边锁定列区域(不包含表头) this.leftColStickySp = new _canvax.default.Display.Sprite({ id: 'leftColStickySp' }); this.graphsView.addChild(this.leftColStickySp); //普通列头 this.columnsSp = new _canvax.default.Display.Sprite({ id: 'columnsSp' }); this.graphsView.addChild(this.columnsSp); //创建固定列表头容器 this.fixedColHeaderSp = new _canvax.default.Display.Sprite({ id: 'fixedColHeaderSp' }); this.graphsView.addChild(this.fixedColHeaderSp); //设置主表格区域的选中层 this.selectedSp = new _canvax.default.Display.Sprite({ id: 'selectedSp' }); this.graphsView.addChild(this.selectedSp); //设置表格的裁剪区域 this.selectedSpClipRect = new Rect({ context: { x: _x, y: _y, width: _width, height: _height, fillStyle: 'red', alpha: 1 } }); this.selectedSp.clipTo(this.selectedSpClipRect); this.sprite.addChild(this.selectedSpClipRect); if (this.domContainer) { var _selectedDomContainer = document.createElement("div"); _selectedDomContainer.style.cssText = " ;position:absolute;width:left:-1000px;top:-1000px;color:" + itemData.fillStyle + ""; _selectedDomContainer.innerHTML = textTxt; me.domContainer.appendChild(_selectedDomContainer); } //设置 左侧固定 表格区域的选中层 this.leftSelectedSp = new _canvax.default.Display.Sprite({ id: 'leftSelectedSp' }); this.graphsView.addChild(this.leftSelectedSp); //设置表格的裁剪区域 this.leftSelectedSpClipRect = new Rect({ context: { x: _x, y: _y, width: _width, height: _height, fillStyle: 'red', alpha: 0.1 } }); this.leftSelectedSp.clipTo(this.leftSelectedSpClipRect); this.sprite.addChild(this.leftSelectedSpClipRect); //汇总区域 //汇总的普通列区域 var summaryTop = _height - this.summary.height; this.summaryColumnsSp = new _canvax.default.Display.Sprite({ id: 'summaryColumnsSp', context: { y: summaryTop } }); this.graphsView.addChild(this.summaryColumnsSp); //汇总的左边固定列区域 this.summaryLeftColStickySp = new _canvax.default.Display.Sprite({ id: 'summaryLeftColStickySp', context: { y: summaryTop } }); this.graphsView.addChild(this.summaryLeftColStickySp); this.contentX = _x; this.contentY = _y; this.layoutData = { rowData: { columns: [], list: [] }, colData: [], colDataMap: new Map() }; //滚轮缩放相关 var _ticking = false; var _lastWheelTime = 0; this.zoom = new _zoom.default(); //初始值为_x _y,所以要先同步到zoom里 me.zoom.offset({ x: _x, y: _y }); this.sprite.on(event.types.get(), function (e) { var _contextmenu = me.app.getComponent({ name: 'contextmenu' }); if (!_contextmenu || !_contextmenu.isShow) { e.preventDefault(); if (e.type == 'mouseover') { //进入表格 if (e.fromTarget && isParent(me.sprite, e.fromTarget)) { return; } me.scroll.showScrollBar(); } if (e.type == 'mouseout') { //移出表格 if (e.toTarget && isParent(me.sprite, e.toTarget)) { return; } me.scroll.hideScrollBar(); } } }); //设置滚动条的容器sprite this.scrollSp = new _canvax.default.Display.Sprite({ id: 'scrollSp', context: { x: _x, y: _y, width: _width, height: _height } }); this.sprite.addChild(this.scrollSp); } }, { key: "initScroll", value: function initScroll() { var me = this; this.scrollSp.removeAllChildren(); var _width = this.induce.context.width; var _height = this.induce.context.height; this.scroll = new _scroll.default(_objectSpread(_objectSpread({}, this.scroll), {}, { viewportHeight: _height, viewportWidth: _width, rowMinHeight: this.style.cell.minHeight, scrollLeft: 0, scrollTop: 0, dataLength: this.dataFrame.length, container: this.scrollSp, scrollHandle: function scrollHandle(offset) { var _me$zoom$offset2 = me.zoom.offset(offset), x = _me$zoom$offset2.x, y = _me$zoom$offset2.y; me.graphsView.context.x = x; me.graphsView.context.y = y; // 处理固定列和表头的位置同步 me._syncStickyElements(); me.updateLayoutData(); } })); } }, { key: "_syncStickyElements", value: function _syncStickyElements(cell) { var _this$summary; var scrollState = this.scroll.getState(); // 同步固定列的位置 if (this.leftColSticky > 0) { var leftOffset = 0; // 处理水平方向 if (this.graphsView.context.x < this.contentX) { leftOffset = -this.graphsView.context.x + this.contentX; // 同步固定列数据和表头的水平位置 this.leftColStickySp.context.x = leftOffset; this.leftSelectedSp.context.x = leftOffset; this.fixedColHeaderSp.context.x = leftOffset; this.summaryLeftColStickySp.context.x = leftOffset; } else { this.leftColStickySp.context.x = 0; this.leftSelectedSp.context.x = 0; this.fixedColHeaderSp.context.x = 0; this.summaryLeftColStickySp.context.x = 0; } // 处理垂直方向 if (this.graphsView.context.y < this.contentY) { // 固定列表头需要固定在顶部 if (this.theadSticky) { this.fixedColHeaderSp.context.y = -this.graphsView.context.y + this.contentY; } } else { this.fixedColHeaderSp.context.y = 0; } } // 同步普通表头位置 if (this.theadSticky) { if (this.graphsView.context.y < this.contentY) { this.columnsSp.context.y = -this.graphsView.context.y + this.contentY; } else { this.columnsSp.context.y = 0; } } //同步汇总区域的位置 if ((_this$summary = this.summary) !== null && _this$summary !== void 0 && _this$summary.enable) { var summaryTop = scrollState.viewportHeight - this.graphsView.context.y - this.summary.height; this.summaryColumnsSp.context.y = summaryTop; this.summaryLeftColStickySp.context.y = summaryTop; } if (cell) { if (cell.col.colIndex < this.leftColSticky) { //如果这个 } } var _currentCellHighlightRightPopover = this.graphsView.getChildById("_currentCellHighlightRightPopover"); if (_currentCellHighlightRightPopover) { //如果cell是左侧的固定列单元格,那么x要减去scrollLeft if (_currentCellHighlightRightPopover.cell.col.colIndex < this.leftColSticky) { _currentCellHighlightRightPopover.context.x = _currentCellHighlightRightPopover._pos.x + this.scroll.getState().scrollLeft; } } } }, { key: "resetData", value: function resetData(data) { //数据变化 var me = this; this.app.dataFrame = this.dataFrame = (0, _tableDataFrame.default)(data); me.graphsView.context.x = 0; me.graphsView.context.y = 0; this.initScroll(); // 处理固定列和表头的位置同步 me._syncStickyElements(); this.draw(); } }, { key: "draw", value: function draw() { var _this$summary2; //先更具内容区域的宽高,然后用最小行高,计算出至少要首屏渲染多少条数据,列数据全部都计算,列的数量一般可控, //首屏至少要渲染这么多条数据 this._layouted = false; debugger; this.layoutData = this.getLayoutData(); window.layoutData = this.layoutData; //第一次预估出来的layoutData会有一部分误差,可以更新一次 this.updateLayoutData(); this._layouted = true; debugger; this.renderTable(); var scrollState = this.scroll.getState(); var scrollHeight = (this.dataFrame.list.length - (scrollState.renderedRange.end - scrollState.renderedRange.start + 1)) * this.style.cell.minHeight + this.layoutData.rowData.list.size.height + this.layoutData.rowData.columns.size.height; if ((_this$summary2 = this.summary) !== null && _this$summary2 !== void 0 && _this$summary2.enable) { scrollHeight += this.summary.height + 2; } this.scroll.setState({ scrollHeight: scrollHeight, scrollWidth: this.layoutData.rowData.columns.size.width }); //渲染完后, 计算出来固定行的高 和 固定列的宽,用固定列的高作为top,固定列的width做为left,放一个sprite,用来渲染一些选中单元格的边框等元素 // 计算固定行的高(表头高度)和固定列的宽 var fixedHeaderHeight = this.layoutData.rowData.columns.size.height; var fixedColWidth = 0; if (this.leftColSticky > 0 && this.layoutData.rowData.columns.rows.length > 0) { // 计算固定列的总宽度(取第一行的前N列宽度之和) var firstHeaderRow = this.layoutData.rowData.columns.rows[0]; for (var i = 0; i < this.leftColSticky; i++) { var cell = firstHeaderRow.cells[i]; if (cell && cell.size && typeof cell.size.width === 'number') { fixedColWidth += cell.size.width; } } } var borderLineWidth = this.style.border.width; this.selectedSpClipRect.context.x = fixedColWidth + borderLineWidth - 1; this.selectedSpClipRect.context.y = fixedHeaderHeight + borderLineWidth - 1; this.selectedSpClipRect.context.width = this.layoutData.rowData.columns.size.width - fixedColWidth; this.selectedSpClipRect.context.height = scrollState.viewportHeight - fixedHeaderHeight + 1; //然后设置下左侧固定列的选中层的位置尺寸 this.leftSelectedSpClipRect.context.x = -1; this.leftSelectedSpClipRect.context.y = fixedHeaderHeight + borderLineWidth - 1; this.leftSelectedSpClipRect.context.width = fixedColWidth + borderLineWidth + 2; this.leftSelectedSpClipRect.context.height = scrollState.viewportHeight - fixedHeaderHeight + 1; this.scroll.hideScrollBar(); this.fire("complete"); } }, { key: "renderTable", value: function renderTable() { var _this2 = this; //先把几个容易的原来可能的单元格都清除掉 this.fixedColHeaderSp.removeAllChildren(); this.columnsSp.removeAllChildren(); this.leftColStickySp.removeAllChildren(); this.listSp.removeAllChildren(); this.selectedSp.removeAllChildren(); this.leftSelectedSp.removeAllChildren(); this.summaryColumnsSp.removeAllChildren(); this.summaryLeftColStickySp.removeAllChildren(); //先绘制columns this.layoutData.rowData.columns.rows.forEach(function (row, rowIndex) { row.cells.forEach(function (cell, colIndex) { if (cell.cellData.isEmpty) { return; } var cellSp = _this2._createCellSp(cell); if (colIndex < _this2.leftColSticky) { //先把固定列的colSticky设置为true cell.col.colSticky = true; // 固定列的表头放入专门的容器 _this2.fixedColHeaderSp.addChild(cellSp); } else { _this2.columnsSp.addChild(cellSp); } // 创建完单元格后,检查并应用正确的样式(包括选中状态) _this2._setCellStyle(cell); }); }); var scrollState = this.scroll.getState(); for (var i = scrollState.renderedRange.start; i <= scrollState.renderedRange.end; i++) { var row = this.layoutData.rowData.list.rows[i]; this.drawRow(row); } //绘制汇总区域 //循环layoutData.colData,如果有固定列, 固定列的合并渲染到summaryLeftColStickySp, 普通列的合并渲染到summaryColumnsSp this.layoutData.rowData.summary.rows.forEach(function (row, rowIndex) { row.cells.forEach(function (cell, colIndex) { if (cell.cellData.isEmpty) { return; } var cellSp = _this2._createCellSp(cell); if (colIndex < _this2.leftColSticky) { //先把固定列的colSticky设置为true cell.col.colSticky = true; // 固定列的表头放入专门的容器 _this2.summaryLeftColStickySp.addChild(cellSp); } else { _this2.summaryColumnsSp.addChild(cellSp); } // 创建完单元格后,检查并应用正确的样式(包括选中状态) _this2._setCellStyle(cell); }); }); } }, { key: "_getTargetCell", value: function _getTargetCell(point) { var me = this; var targetCell = null; var scrollState = me.scroll.getState(); //先查是不是点击了某个列头,如果是的话,则返回对应的列头 for (var i = 0; i < me.layoutData.rowData.columns.rows.length; i++) { var row = me.layoutData.rowData.columns.rows[i]; if (!row) continue; if (point.y - scrollState.scrollTop < row.position.y || point.y - scrollState.scrollTop > row.position.y + row.size.height) continue; //遍历行内的所有单元格 var _iterator = _createForOfIteratorHelper(row.cells), _step; try { for (_iterator.s(); !(_step = _iterator.n()).done;) { var cell = _step.value; var cellPosition = _objectSpread({}, cell.position); if (me.leftColSticky > 0 && cell.col.colIndex < me.leftColSticky) { cellPosition.x += scrollState.scrollLeft; } cellPosition.y += scrollState.scrollTop; //检查点是否在当前cell的矩形范围内 if (point.x >= cellPosition.x && point.x <= cellPosition.x + cell.size.width && point.y >= cellPosition.y && point.y <= cellPosition.y + cell.size.height) { targetCell = cell; break; } } } catch (err) { _iterator.e(err); } finally { _iterator.f(); } if (targetCell) break; } if (!targetCell && scrollState !== null && scrollState !== void 0 && scrollState.renderedRange) { var _scrollState$rendered = scrollState.renderedRange, start = _scrollState$rendered.start, end = _scrollState$rendered.end; //遍历可视范围内的所有行 for (var _i = start; _i <= end; _i++) { var _row3 = me.layoutData.rowData.list.rows[_i]; if (!_row3) continue; if (point.y < _row3.position.y || point.y > _row3.position.y + _row3.size.height) continue; //遍历行内的所有单元格 var _iterator2 = _createForOfIteratorHelper(_row3.cells), _step2; try { for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { var _cell2 = _step2.value; var _cellPosition = _objectSpread({}, _cell2.position); if (me.leftColSticky > 0 && _cell2.col.colIndex < me.leftColSticky) { _cellPosition.x += scrollState.scrollLeft; } //检查点是否在当前cell的矩形范围内 if (point.x >= _cellPosition.x && point.x <= _cellPosition.x + _cell2.size.width && point.y >= _cellPosition.y && point.y <= _cellPosition.y + _cell2.size.height) { targetCell = _cell2; break; } } } catch (err) { _iterator2.e(err); } finally { _iterator2.f(); } if (targetCell) break; } } if (targetCell && targetCell.cellData.isEmpty) { targetCell = targetCell.cellData.spanOriginCell || targetCell; } return targetCell; } }, { key: "checkCellIsSelected", value: function checkCellIsSelected(cell) { /**这个检查单元格是否已经被选中的方法有三种情况要判断, 如果this.selectedCells中的所有type为cell的选中项目中有value和这个cell.id相等的,就判断是选中, 如果type是row的话,要检测这个cell.row.id是否存在,有也认为是被选中了(选中行),如果有type是col的数据,要检测这个cell.col.id是否存在,有存在的也认为是被选中了(列选中) */ //如果没有选中数据,直接返回false var isSelected = false; //if( !(this.selected.cellIds.length == 0 && this.selected.row.length == 0 && this.selected.col.length == 0) ){ if ((0, _typeof2.default)(cell) != 'object') { cell = this.getCellById(cell); } //先检查是否有全选行的选中 //let checkedAllItem = this.selected.row.find(item => item.type == 'allrows' && item.checkedAll) if (this.selected.allrows.checkedAll && !this.selected.allrows.excludeRowIds.includes(cell.row.id)) { isSelected = true; return isSelected; } // if( this.selected.allrows.checkedAll // && ( !checkedAllItem.excludeRowIds || !checkedAllItem.excludeRowIds.includes( cell.row.id )) ){ // isSelected = true; // return isSelected; // } //先检查列选中 for (var i = 0; i < this.selected.col.length; i++) { var _selectedCol$excludeC; var selectedCol = this.selected.col[i]; if (cell.col.fieldCellIdStack.includes(selectedCol.colCellId) && (!selectedCol.excludeCellIds || !((_selectedCol$excludeC = selectedCol.excludeCellIds) !== null && _selectedCol$excludeC !== void 0 && _selectedCol$excludeC.includes(cell.id)))) { var activeCellIndInFields = cell.col.fieldCellIdStack.indexOf(this.activeCellId); if (cell.type == 'th' && activeCellIndInFields > -1) { //如果activeCellId是当前单元格的父级,则认为是选中 var cellIdIndex = cell.col.fieldCellIdStack.indexOf(cell.id); if (cellIdIndex >= activeCellIndInFields) { isSelected = true; return isSelected; } } else { isSelected = true; return isSelected; } } } //再检查行选中 for (var _i2 = 0; _i2 < this.selected.row.length; _i2++) { var _selectedRow$excludeC; var selectedRow = this.selected.row[_i2]; if (selectedRow.rowId == cell.row.id && !((_selectedRow$excludeC = selectedRow.excludeCellIds) !== null && _selectedRow$excludeC !== void 0 && _selectedRow$excludeC.includes(cell.id))) { isSelected = true; return isSelected; } } //最后检查单元格选中 if (this.selected.cellIds.includes(cell.id)) { isSelected = true; return isSelected; } //} } }, { key: "checkRowIsSelected", value: function checkRowIsSelected(row) { return this.selected.row.find(function (item) { return item.type == 'row' && item.rowId == row.id; }) || this.selected.allrows.checkedAll && !this.selected.allrows.excludeRowIds.includes(row.id); } }, { key: "unselect", value: function unselect(list) { var _this3 = this; if (!this.selected.enabled) { return; } if (list == undefined) { //没有传入参数,则清空所有选中 this.selected.cellIds = []; this.selected.row = []; this.selected.col = []; this.selected.allrows.excludeRowIds = []; this.selected.allrows.checkedAll = false; } else { if (!Array.isArray(list)) { list = [list]; } list.forEach(function (item) { if (item.type == 'col') { //删除this.selected.col中对应的item _this3.selected.col.splice(_this3.selected.col.indexOf(_this3.selected.col.find(function (col) { return col.colCellId == item.colCellId; })), 1); return; } if (item.type == 'row') { //删除this.selected.row中对应的item _this3.selected.row.splice(_this3.selected.row.indexOf(_this3.selected.row.find(function (row) { return row.rowId == item.rowId; })), 1); return; } var cell; if ((0, _typeof2.default)(item) != 'object') { cell = _this3.getCellById(item); } else { cell = item; } if (!_this3.selected.cellIds.includes(cell.id)) { return; } _this3.selected.cellIds.splice(_this3.selected.cellIds.indexOf(cell.id), 1); }); } this.refreshAllCellStyle(); this.action({ type: 'unSelect', info: { selected: this.selected } }); } }, { key: "select", value: function select(list) { var _this4 = this; if (!this.selected.enabled) { return; } if (!Array.isArray(list)) { list = [list]; } list.forEach(function (item) { if (item.type == 'allrows') { Object.assign(_this4.selected.allrows, item); return; } if (item.type == 'col') { if (!_this4.selected.col.find(function (col) { return col.colCellId == item.colCellId; })) { _this4.selected.col.push(item); } return; } if (item.type == 'row') { if (!_this4.selected.row.find(function (row) { return row.rowId == item.rowId; })) { _this4.selected.row.push(item); } return; } //下面都是select单元格的逻辑 if (item.type == 'cell') { var newIds = item.cellIds;