fineui是帆软报表和BI产品线所使用的前端框架。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

361 lines
14 KiB

/**
* Created By Shichao on 2017/10/17
* @class BI.CanvasCollectionView
* @extends BI.Widget
*/
BI.CanvasCollectionView = BI.inherit(BI.Widget, {
_defaultConfig: function () {
return BI.extend(BI.CanvasCollectionView.superclass._defaultConfig.apply(this, arguments), {
baseCls: "bi-canvas-collection",
overflowX: true,
overflowY: true,
cellSizeAndPositionGetter: BI.emptyFn,
horizontalOverscanSize: 0,
verticalOverscanSize: 0,
scrollLeft: 0,
scrollTop: 0,
items: []
})
},
_init: function () {
BI.CanvasCollectionView.superclass._init.apply(this, arguments);
var self = this, o = this.options;
this.renderedCells = [];
this.renderedKeys = [];
this._scrollLock = false;
this.scrollTop = this.scrollLeft = 0;
this.summaryScrollTop = this.summaryScrollLeft = 0;
this._debounceRelease = BI.debounce(function () {
self._scrollLock = false;
}, 1000 / 60);
this.canvas = BI.createWidget({
type: "bi.canvas_new"
});
$(document).keydown(BI.bind(this._onResize, this)); // 防止在使用ctrl + 滚轮调整窗口大小时触发mousewheel事件
$(document).keyup(BI.bind(this._onResizeRelease, this))
this.element.mousewheel(BI.bind(this._onMouseWheel, this))
BI.createWidget({
type: "bi.vertical",
element: this,
scrollable: false,
scrolly: false,
scrollx: false,
items: [this.canvas]
});
if (o.items.length > 0) {
this._calculateSizeAndPositionData();
this._populate();
}
if (o.scrollLeft !== 0 || o.scrollTop !== 0) {
BI.nextTick(function () {
self.element.scrollTop(o.scrollTop);
self.element.scrollLeft(o.scrollLeft);
});
}
},
_onMouseWheel: function (e) {
var o = this.options;
if (this._scrollLock) {
return;
}
if (!this._isCtrlPressed) {
o.scrollTop += -e.originalEvent.wheelDelta;
o.scrollTop = BI.clamp(o.scrollTop, 0, this.maxScrollTop);
this._calculateChildrenToRender();
this.fireEvent(BI.CanvasCollectionView.EVENT_SCROLL, {
scrollLeft: o.scrollLeft,
scrollTop: o.scrollTop
});
}
},
_onResize: function (e) {
if (e.ctrlKey) {
this._isCtrlPressed = true;
} else {
this._isCtrlPressed = false;
}
},
_onResizeRelease: function (e) {
var Keys = {
CTRL: 17
};
var keyCode = e.keyCode;
if (keyCode === Keys.CTRL) {
this._isCtrlPressed = false;
}
},
_getMaxScrollTop: function () {
return this._height - this.options.height
},
_calculateSizeAndPositionData: function () {
var o = this.options;
var cellMetadata = [];
var sectionManager = new BI.SectionManager();
var height = 0;
var width = 0;
for (var index = 0, len = o.items.length; index < len; index++) {
var cellMetadatum = o.cellSizeAndPositionGetter(index);
if (cellMetadatum.height == null || isNaN(cellMetadatum.height) ||
cellMetadatum.width == null || isNaN(cellMetadatum.width) ||
cellMetadatum.x == null || isNaN(cellMetadatum.x) ||
cellMetadatum.y == null || isNaN(cellMetadatum.y)) {
throw Error();
}
height = Math.max(height, cellMetadatum.y + cellMetadatum.height);
width = Math.max(width, cellMetadatum.x + cellMetadatum.width);
cellMetadatum.index = index;
cellMetadata[index] = cellMetadatum;
sectionManager.registerCell(cellMetadatum, index);
}
this._cellMetadata = cellMetadata;
this._sectionManager = sectionManager;
if (this._height === height && this._width === width) {
this._isNeedReset = false;
} else {
this._height = height;
this._width = width;
this._isNeedReset = true;
}
this.maxScrollTop = this._getMaxScrollTop();
},
_cellRenderers: function (height, width, x, y) {
this._lastRenderedCellIndices = this._sectionManager.getCellIndices(height, width, x, y);
return this._cellGroupRenderer();
},
_cellGroupRenderer: function () {
var self = this, o = this.options;
var rendered = [];
BI.each(this._lastRenderedCellIndices, function (i, index) {
var cellMetadata = self._sectionManager.getCellMetadata(index);
rendered.push(cellMetadata);
});
return rendered;
},
_calculateChildrenToRender: function () {
var x, y, cellWidth, cellHeight, cellRow, cellCol, value, self = this, o = this.options;
var scrollLeft = o.scrollLeft;
var scrollTop = o.scrollTop;
var left = Math.max(0, scrollLeft - o.horizontalOverscanSize);
var top = Math.max(0, scrollTop - o.verticalOverscanSize);
var right = Math.min(this._width, scrollLeft + o.width + o.horizontalOverscanSize);
var bottom = Math.min(this._height, scrollTop + o.height + o.verticalOverscanSize);
if (right > 0 && bottom > 0) {
var childrenToDisplay = this._cellRenderers(bottom - top, right - left, left, top);
this.canvas.remove(this.scrollLeft, this.scrollTop, o.width, o.height);
for (var i = 0; i < childrenToDisplay.length; i++) {
var datum = childrenToDisplay[i];
var index = this.renderedKeys[datum.index] && this.renderedKeys[datum.index][1];
var rect_tl_x = datum.x,
rect_tl_y = datum.y,
rect_tr_x = rect_tl_x + datum.width,
rect_bl_y = rect_tl_y + datum.height,
cell = o.items[datum.index].cell || o.items[datum.index],
background, color, fontWeight, text;
while (BI.isNull(cell.styles) && !BI.isFunction(cell.styleGetter)) {
cell = cell.cell;
}
if (BI.isNull(cell.styles) && BI.isFunction(cell.styleGetter)) {
background = cell.styleGetter().background;
color = cell.styleGetter().color;
fontWeight = cell.styleGetter().fontWeight;
} else if (!BI.isNull(cell.styles)) {
background = cell.styles.background;
color = cell.styles.color;
fontWeight = cell.styles.fontWeight;
}
if (BI.isNull(cell.text)) {
text = "";
} else {
text = cell.text;
}
if (!BI.isString(text)) {
text = text.toString();
}
if (this.scrollLeft !== o.scrollLeft) {
this.canvas.translate(this.scrollLeft - o.scrollLeft, 0);
this.scrollLeft = o.scrollLeft;
}
if (this.scrollTop !== o.scrollTop) {
this.canvas.translate(0, this.scrollTop - o.scrollTop);
this.scrollTop = o.scrollTop;
}
if (datum.x === 0 && datum.y === 0) {
this.canvas.solid(rect_tl_x, rect_tl_y, rect_tl_x, rect_bl_y, rect_tr_x, rect_bl_y, rect_tr_x, rect_tl_y, rect_tl_x, rect_tl_y, {
strokeStyle: "rgb(212, 218, 221)",
fillStyle: background
});
} else if (datum.x === 0) {
this.canvas.solid(rect_tl_x, rect_tl_y, rect_tl_x, rect_bl_y, rect_tr_x, rect_bl_y, rect_tr_x, rect_tl_y, {
strokeStyle: "rgb(212, 218, 221)",
fillStyle: background
});
} else if (datum.y === 0) {
this.canvas.solid(rect_tl_x, rect_tl_y, rect_tr_x, rect_tl_y, rect_tr_x, rect_bl_y, rect_tl_x, rect_bl_y, {
strokeStyle: "rgb(212, 218, 221)",
fillStyle: background
});
} else {
this.canvas.solid(rect_tr_x, rect_tl_y, rect_tl_x, rect_tl_y, rect_tl_x, rect_bl_y, rect_tr_x, rect_bl_y, {
strokeStyle: "rgb(212, 218, 221)",
fillStyle: background
});
}
this.canvas.setFontWeight(fontWeight);
this.canvas.setFont();
var font = this.canvas.getContext().font,
textSize = this._getTextPixel(font),
textHeight = textSize,
textWidth = this.canvas.getContext().measureText(text).width,
dotsWidth = this.canvas.getContext().measureText("...").width;
var offsetX = this._calcOffsetX(textWidth, datum.width, "center"),
offsetY = this._calcOffsetY(textHeight, datum.height, "center");
if (textHeight > datum.height) {
this.canvas.text(datum.x + offsetX, datum.y + offsetY, "...", color);
} else if (textWidth + 4 > datum.width) {
var sliceIndex = Math.floor((datum.width - dotsWidth - 4) / textWidth * text.length);
this.canvas.text(datum.x + offsetX, datum.y + offsetY, text.slice(0, sliceIndex) + "...", color);
} else {
this.canvas.text(datum.x + offsetX, datum.y + offsetY, text, color);
}
this.canvas.stroke();
}
}
},
_getTextPixel: function (font) {
var p = font.split("px")[0],
s = p.split(" ");
for (var c in s) {
var num;
num = BI.parseInt(s[c]);
if (!BI.isNaN(num)) {
return num;
}
}
},
_calcOffsetX: function (textWidth, cellWidth, position) {
switch (position) {
case "center":
if (textWidth >= cellWidth) {
return 4;
} else {
return (cellWidth - textWidth) / 2;
}
case "right":
if (textWidth >= cellWidth) {
return 0;
} else {
return cellWidth - textWidth;
}
default:
return 0;
}
},
_calcOffsetY: function (textHeight, cellHeight, position) {
switch (position) {
case "center":
if (textHeight >= cellHeight) {
return textHeight;
} else {
return (cellHeight + textHeight) / 2;
}
case "bottom":
if (textHeight >= cellHeight) {
return cellHeight;
} else {
return cellHeight + textHeight;
}
default:
return textHeight;
}
},
_populate: function (items) {
var o = this.options;
if (items && items !== this.options.items) {
this.options.items = items;
this._calculateSizeAndPositionData();
}
if (o.items.length > 0) {
this.canvas.setBlock();
this.canvas.setWidth(o.width);
this.canvas.setHeight(o.height);
this.restore();
this._calculateChildrenToRender();
this.element.scrollTop(o.scrollTop);
this.element.scrollLeft(o.scrollLeft);
}
},
populate: function (items) {
if (items && items !== this.options.items) {
this.restore();
}
this._populate(items);
},
setWidth: function (width) {
BI.CanvasCollectionView.superclass.setWidth.apply(this, arguments);
this.options.width = width;
},
setHeight: function (height) {
BI.CanvasCollectionView.superclass.setHeight.apply(this, arguments);
this.options.height = height;
},
restore: function () {
this.canvas.remove(this.scrollLeft, this.scrollTop, this.options.width, this.options.height);
this.renderedKeys = [];
this._scrollLock = false;
},
setScrollLeft: function (scrollLeft) {
if (this.options.scrollLeft === scrollLeft) {
return;
}
this._scrollLock = true;
this.options.scrollLeft = scrollLeft;
this._debounceRelease();
this._calculateChildrenToRender();
this.element.scrollLeft(this.options.scrollLeft);
},
setScrollTop: function (scrollTop) {
if (this.options.scrollTop === scrollTop) {
return;
}
this._scrollLock = true;
this.options.scrollTop = scrollTop;
this._debounceRelease();
this._calculateChildrenToRender();
this.element.scrollTop(this.options.scrollTop);
},
getScrollLeft: function () {
return this.options.scrollLeft;
},
getScrollTop: function () {
return this.options.scrollTop;
}
})
BI.CanvasCollectionView.EVENT_SCROLL = "EVENT_SCROLL";
BI.shortcut("bi.canvas_collection_view", BI.CanvasCollectionView);