chartx
Version:
Data Visualization Chart Library
284 lines (269 loc) • 9.41 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _canvax = _interopRequireDefault(require("canvax"));
/**
* @fileOverview 表格虚拟滚动控制器
* @author litao.lt@alibaba-in.com
* @version 1.0
*/
var Rect = _canvax.default.Shapes.Rect;
function _default() {
var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
// 当前滚动位置
var scrollTop = opt.scrollTop || 0;
var scrollLeft = opt.scrollLeft || 0;
// 总可滚动区域尺寸
var scrollHeight = 0;
var scrollWidth = 0;
// 可视区域尺寸
var viewportHeight = opt.viewportHeight || 0;
var viewportWidth = opt.viewportWidth || 0;
// 行高和缓冲区配置
var rowMinHeight = opt.rowMinHeight || 40; // 默认最小行高
var bufferSize = opt.bufferSize || 0; // 可视区域上下额外渲染的行数
var dataLength = opt.dataLength || 0; // 数据总长度
var viewportHeightShowRowsCount = Math.ceil(viewportHeight / rowMinHeight);
// 当前已渲染的行范围
var renderedRange = {
start: 0,
end: Math.min(viewportHeightShowRowsCount + bufferSize, dataLength) - 1
};
var container = opt.container || null;
var rightScrollBar, bottomScrollBar;
var barMinLength = 10;
var barLineWidth = 6;
var scrollHandle = opt.scrollHandle || function () {
return {
x: 0,
y: 0
};
};
if (container) {
//添加一个右边的scrollBar 和 下面的scrollBar
var x = container.context.width - barLineWidth;
rightScrollBar = new Rect({
id: 'rightScrollBar',
dragEnabled: true,
hoverClone: false,
context: {
cursor: 'pointer',
x: x,
y: 0,
width: barLineWidth,
height: barMinLength,
fillStyle: "#999",
fillAlpha: 0.6,
radius: [barLineWidth / 2, barLineWidth / 2, barLineWidth / 2, barLineWidth / 2],
visible: false
}
});
rightScrollBar.hover(function () {
if (scrollHeight <= viewportHeight) {
return;
}
rightScrollBar.context.width = barLineWidth + 2;
rightScrollBar.context.x = x - 2;
}, function () {
if (scrollHeight <= viewportHeight) {
return;
}
rightScrollBar.context.width = barLineWidth;
rightScrollBar.context.x = x;
});
rightScrollBar.on('draging', function () {
rightScrollBar.context.x = x - 2;
if (rightScrollBar.context.y < 0) {
rightScrollBar.context.y = 0;
}
if (rightScrollBar.context.y + rightScrollBar.context.height > viewportHeight) {
rightScrollBar.context.y = viewportHeight - rightScrollBar.context.height;
}
//重新计算最新的scrollTop
var preScrollTop = scrollTop;
scrollTop = parseInt(rightScrollBar.context.y * (scrollHeight - viewportHeight) / (viewportHeight - rightScrollBar.context.height));
scrollHandle({
x: 0,
y: preScrollTop - scrollTop
});
});
container.addChild(rightScrollBar);
var y = container.context.height - barLineWidth;
bottomScrollBar = new Rect({
id: 'bottomScrollBar',
dragEnabled: true,
hoverClone: false,
context: {
cursor: 'pointer',
x: 0,
y: y,
width: barMinLength,
height: barLineWidth,
fillStyle: "#999",
fillAlpha: 0.6,
radius: [barLineWidth / 2, barLineWidth / 2, barLineWidth / 2, barLineWidth / 2],
visible: false
}
});
bottomScrollBar.hover(function () {
if (scrollWidth <= viewportWidth) {
return;
}
bottomScrollBar.context.height = barLineWidth + 2;
bottomScrollBar.context.y = y - 2;
}, function () {
if (scrollWidth <= viewportWidth) {
return;
}
bottomScrollBar.context.height = barLineWidth;
bottomScrollBar.context.y = y;
});
bottomScrollBar.on('draging', function () {
bottomScrollBar.context.y = y - 2;
if (bottomScrollBar.context.x < 0) {
bottomScrollBar.context.x = 0;
}
if (bottomScrollBar.context.x + bottomScrollBar.context.width > viewportWidth) {
bottomScrollBar.context.x = viewportWidth - bottomScrollBar.context.width;
}
//重新计算最新的scrollLeft
var preScrollLeft = scrollLeft;
scrollLeft = parseInt(bottomScrollBar.context.x * (scrollWidth - viewportWidth) / (viewportWidth - bottomScrollBar.context.width));
scrollHandle({
x: preScrollLeft - scrollLeft,
y: 0
});
});
container.addChild(bottomScrollBar);
}
var updateScrollBar = function updateScrollBar() {
// 修正滚动条位置的计算公式
// 纵向滚动条(rightScrollBar)的y坐标
if (rightScrollBar && scrollHeight) {
if (scrollHeight <= viewportHeight) {
rightScrollBar.context.visible = false;
} else {
var scrollBarHeight = viewportHeight * viewportHeight / scrollHeight;
if (scrollBarHeight < barMinLength) {
scrollBarHeight = barMinLength;
}
var maxScrollTop = Math.max(1, scrollHeight - viewportHeight);
var maxBarY = viewportHeight - scrollBarHeight;
var scrollBarY = 0;
if (scrollHeight > viewportHeight) {
scrollBarY = scrollTop / maxScrollTop * maxBarY;
} else {
scrollBarY = 0;
}
rightScrollBar.context.height = scrollBarHeight;
rightScrollBar.context.y = scrollBarY;
rightScrollBar.context.visible = true;
}
}
// 横向滚动条(bottomScrollBar)的x坐标
if (bottomScrollBar && scrollWidth) {
if (scrollWidth <= viewportWidth) {
bottomScrollBar.context.visible = false;
} else {
var scrollBarWidth = viewportWidth * viewportWidth / scrollWidth;
if (scrollBarWidth < barMinLength) {
scrollBarWidth = barMinLength;
}
var maxScrollLeft = Math.max(1, scrollWidth - viewportWidth);
var maxBarX = viewportWidth - scrollBarWidth;
var scrollBarX = 0;
if (scrollWidth > viewportWidth) {
scrollBarX = scrollLeft / maxScrollLeft * maxBarX;
} else {
scrollBarX = 0;
}
bottomScrollBar.context.width = scrollBarWidth;
bottomScrollBar.context.x = scrollBarX;
bottomScrollBar.context.visible = true;
}
}
};
// 更新滚动位置
var scrollTo = function scrollTo() {
var left = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : scrollLeft;
var top = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scrollTop;
// 限制滚动位置在有效范围内
scrollTop = Math.max(0, Math.min(top, scrollHeight - viewportHeight));
scrollLeft = Math.max(0, Math.min(left, scrollWidth - viewportWidth));
updateScrollBar();
return {
scrollTop: scrollTop,
scrollLeft: scrollLeft,
renderedRange: renderedRange
};
};
// 更新滚动区域尺寸
var setState = function setState() {
var opt = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
if (opt.scrollHeight !== undefined) {
scrollHeight = Math.max(0, opt.scrollHeight);
updateScrollBar();
}
if (opt.scrollWidth !== undefined) {
scrollWidth = Math.max(0, opt.scrollWidth);
updateScrollBar();
}
if (opt.viewportHeight !== undefined) {
viewportHeight = Math.max(0, opt.viewportHeight);
}
if (opt.viewportWidth !== undefined) {
viewportWidth = Math.max(0, opt.viewportWidth);
}
if (opt.dataLength !== undefined) {
dataLength = Math.max(0, opt.dataLength);
}
if (opt.rowMinHeight !== undefined) {
rowMinHeight = Math.max(0, opt.rowMinHeight);
}
// 更新尺寸后确保滚动位置仍然有效
return scrollTo();
};
// 获取当前状态
var getState = function getState() {
return {
scrollTop: scrollTop,
scrollLeft: scrollLeft,
scrollHeight: scrollHeight,
scrollWidth: scrollWidth,
viewportHeight: viewportHeight,
viewportWidth: viewportWidth,
rowMinHeight: rowMinHeight,
bufferSize: bufferSize,
renderedRange: renderedRange
};
};
var checkRowPositionIsInViewport = function checkRowPositionIsInViewport(row) {
if (scrollTop == 482) {}
//console.log( scrollTop )
if (!row) {
return false;
}
var rowTop = row.position.y - scrollTop;
var rowBottom = rowTop + row.size.height;
//return rowBottom > - bufferSize * rowMinHeight && rowTop < viewportHeight + bufferSize*rowMinHeight
return !(rowBottom < -bufferSize * rowMinHeight || rowTop > viewportHeight + bufferSize * rowMinHeight);
};
var showScrollBar = function showScrollBar() {
rightScrollBar.context.visible = true;
bottomScrollBar.context.visible = true;
};
var hideScrollBar = function hideScrollBar() {
rightScrollBar.context.visible = false;
bottomScrollBar.context.visible = false;
};
// 暴露公共方法
this.scrollTo = scrollTo;
this.setState = setState;
this.getState = getState;
this.showScrollBar = showScrollBar;
this.hideScrollBar = hideScrollBar;
this.checkRowPositionIsInViewport = checkRowPositionIsInViewport;
}