@visactor/vtable
Version:
canvas table width high performance
312 lines (288 loc) • 16.3 kB
JavaScript
import { createArc, createCircle, createLine, createRect, REACT_TO_CANOPUS_EVENTS, Text, Group as VGroup } from "./../../vrender";
import { isArray, isFunction, isObject, isString, isValid } from "@visactor/vutils";
import { Icon } from "../graphic/icon";
import { emptyCustomLayout } from "../../components/react/react-custom-layout";
import { getTargetCell } from "../../event/util";
export const CUSTOM_MERGE_PRE_NAME = "_custom_";
export const CUSTOM_CONTAINER_NAME = "custom-container";
export const CUSTOM_MERGE_CONTAINER_NAME = CUSTOM_MERGE_PRE_NAME + "_0";
export function dealWithCustom(customLayout, customRender, col, row, width, height, autoWidth, autoHeight, padding, range, table) {
var _a, _b, _c;
let expectedWidth, expectedHeight, customElements, elementsGroup, renderDefault = !0, enableCellPadding = !1;
if ("react-custom-layout" === customLayout && (customLayout = (null === (_a = table.reactCustomLayout) || void 0 === _a ? void 0 : _a.getCustomLayoutFunc(col, row)) || emptyCustomLayout),
"function" == typeof customLayout) {
const customRenderObj = customLayout({
col: null !== (_b = null == range ? void 0 : range.start.col) && void 0 !== _b ? _b : col,
row: null !== (_c = null == range ? void 0 : range.start.row) && void 0 !== _c ? _c : row,
dataValue: table.getCellOriginValue(col, row),
value: table.getCellValue(col, row) || "",
rect: {
left: 0,
top: 0,
right: width,
bottom: height,
width: width,
height: height
},
table: table,
originCol: col,
originRow: row
});
if (!customRenderObj) return {
renderDefault: !0
};
customRenderObj.rootContainer && (customRenderObj.rootContainer = decodeReactDom(customRenderObj.rootContainer, table.animationManager.timeline)),
customRenderObj.rootContainer instanceof VGroup && (elementsGroup = customRenderObj.rootContainer,
elementsGroup.name = CUSTOM_CONTAINER_NAME, elementsGroup.col = col, elementsGroup.row = row),
renderDefault = customRenderObj.renderDefault, enableCellPadding = customRenderObj.enableCellPadding;
} else if ("function" == typeof customRender) {
const customRenderObj = customRender({
col: col,
row: row,
dataValue: table.getCellOriginValue(col, row),
value: table.getCellValue(col, row) || "",
rect: {
left: 0,
top: 0,
right: width,
bottom: height,
width: width,
height: height
},
table: table
});
customRenderObj && (customElements = customRenderObj.elements, renderDefault = customRenderObj.renderDefault,
expectedWidth = customRenderObj.expectedWidth, expectedHeight = customRenderObj.expectedHeight);
} else customRender && (expectedWidth = customRender.expectedWidth, expectedHeight = customRender.expectedHeight,
customElements = customRender.elements, renderDefault = customRender.renderDefault);
if (customElements) {
elementsGroup = adjustElementToGroup(customElements, autoWidth ? expectedWidth : width, autoHeight ? expectedHeight : height, table.getCellValue(col, row));
}
return enableCellPadding && elementsGroup.setAttributes({
x: padding[3],
y: padding[0],
width: width - padding[1] - padding[3],
height: height - padding[0] - padding[2]
}), dealPercentCalc(elementsGroup, width, height), !range || range.start.col === range.end.col && range.start.row === range.end.row || bindAttributeUpdate(elementsGroup, col, row, 0),
{
elementsGroup: elementsGroup,
renderDefault: renderDefault
};
}
function adjustElementToGroup(elements, width, height, value) {
const customGroup = new VGroup({
x: 0,
y: 0,
width: width,
height: height,
fill: !1,
stroke: !1,
pickable: !1
});
customGroup.name = CUSTOM_CONTAINER_NAME;
return adjustElementsPos(elements, width, height, value).forEach((element => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
switch (element.clickable && (element.pickable = element.clickable), element.type) {
case "arc":
const arc = createArc({
x: element.x,
y: element.y,
dx: null !== (_a = element.dx) && void 0 !== _a ? _a : 0,
dy: null !== (_b = element.dy) && void 0 !== _b ? _b : 0,
fill: element.fill,
stroke: element.stroke,
outerRadius: element.radius,
startAngle: element.startAngle,
endAngle: element.endAngle,
pickable: !!element.pickable,
cursor: element.cursor
});
arc.name = element.name, customGroup.appendChild(arc);
break;
case "text":
if (element.background) {
const expandX = null !== (_d = null === (_c = element.background) || void 0 === _c ? void 0 : _c.expandX) && void 0 !== _d ? _d : 0, expandY = null !== (_f = null === (_e = element.background) || void 0 === _e ? void 0 : _e.expandY) && void 0 !== _f ? _f : 0, textBackRect = createRect({
x: element.x - expandX,
y: element.y - expandY,
dx: null !== (_g = element.dx) && void 0 !== _g ? _g : 0,
dy: null !== (_h = element.dy) && void 0 !== _h ? _h : 0,
width: element.width + 2 * expandX,
height: element.height + 2 * expandY,
cornerRadius: null !== (_k = null === (_j = element.background) || void 0 === _j ? void 0 : _j.cornerRadius) && void 0 !== _k ? _k : 0,
fill: null !== (_m = null === (_l = element.background) || void 0 === _l ? void 0 : _l.fill) && void 0 !== _m ? _m : "#888"
});
customGroup.appendChild(textBackRect);
}
const text = new Text(Object.assign({
pickable: !!element.pickable,
fill: null !== (_o = element.color) && void 0 !== _o ? _o : element.fill
}, element));
text.name = element.name, customGroup.appendChild(text);
break;
case "rect":
const rect = createRect({
x: element.x,
y: element.y,
dx: null !== (_p = element.dx) && void 0 !== _p ? _p : 0,
dy: null !== (_q = element.dy) && void 0 !== _q ? _q : 0,
width: element.width,
height: element.height,
cornerRadius: element.radius,
fill: element.fill,
stroke: element.stroke,
pickable: !!element.pickable,
cursor: element.cursor
});
rect.name = element.name, customGroup.appendChild(rect);
break;
case "circle":
const circle = createCircle({
x: element.x,
y: element.y,
dx: null !== (_r = element.dx) && void 0 !== _r ? _r : 0,
dy: null !== (_s = element.dy) && void 0 !== _s ? _s : 0,
radius: element.radius,
fill: element.fill,
stroke: element.stroke,
pickable: !!element.pickable,
cursor: element.cursor
});
circle.name = element.name, customGroup.appendChild(circle);
break;
case "icon":
const icon = new Icon({
x: element.x,
y: element.y,
dx: null !== (_t = element.dx) && void 0 !== _t ? _t : 0,
dy: null !== (_u = element.dy) && void 0 !== _u ? _u : 0,
width: element.width,
height: element.height,
image: element.svg,
backgroundWidth: element.hover ? null !== (_v = element.hover.width) && void 0 !== _v ? _v : element.width : void 0,
backgroundHeight: element.hover ? null !== (_w = element.hover.width) && void 0 !== _w ? _w : element.width : void 0,
backgroundColor: element.hover ? null !== (_x = element.hover.bgColor) && void 0 !== _x ? _x : "rgba(22,44,66,0.2)" : void 0,
pickable: !!element.pickable,
cursor: element.cursor
});
icon.name = element.name, icon.role = "icon-custom", customGroup.appendChild(icon);
break;
case "image":
const image = new Icon({
x: element.x,
y: element.y,
dx: null !== (_y = element.dx) && void 0 !== _y ? _y : 0,
dy: null !== (_z = element.dy) && void 0 !== _z ? _z : 0,
width: element.width,
height: element.height,
image: element.src,
backgroundWidth: element.hover ? null !== (_0 = element.hover.width) && void 0 !== _0 ? _0 : element.width : void 0,
backgroundHeight: element.hover ? null !== (_1 = element.hover.width) && void 0 !== _1 ? _1 : element.width : void 0,
backgroundColor: element.hover ? null !== (_2 = element.hover.bgColor) && void 0 !== _2 ? _2 : "rgba(22,44,66,0.2)" : void 0,
pickable: !!element.pickable,
cursor: element.cursor,
shape: element.shape
});
image.name = element.name, image.role = "image-custom", customGroup.appendChild(image);
break;
case "line":
const line = createLine({
points: element.points,
lineWidth: null !== (_3 = element.lineWidth) && void 0 !== _3 ? _3 : 1,
stroke: element.stroke,
pickable: !!element.pickable,
cursor: element.cursor
});
line.name = element.name, customGroup.appendChild(line);
}
})), customGroup;
}
function adjustElementsPos(originalElements, width, height, value) {
const result = [], borderLineWidths = [ 0, 0, 0, 0 ];
for (let i = 0; i < originalElements.length; i++) {
const originalElement = originalElements[i], element = Object.assign({}, originalElement);
for (const name in element) element.hasOwnProperty(name) && isFunction(element[name]) && (element[name] = element[name](value));
const rect = element;
isValid(rect.x) && (rect.x = isString(rect.x) ? transformString(rect.x, width - borderLineWidths[1]) : Number(rect.x)),
isValid(rect.y) && (rect.y = isString(rect.y) ? transformString(rect.y, height - borderLineWidths[2]) : Number(rect.y)),
"width" in element && (element.width = isString(element.width) ? transformString(element.width, width - borderLineWidths[1]) : Number(element.width)),
"height" in element && (element.height = isString(element.height) ? transformString(element.height, height - borderLineWidths[2]) : Number(element.height)),
"radius" in element && (element.radius = isString(element.radius) ? transformString(element.radius, Math.min(width - borderLineWidths[1], height - borderLineWidths[2])) : Number(element.radius)),
"hover" in element && (element.hover.x = isString(element.hover.x) ? transformString(element.hover.x, width - borderLineWidths[1]) : Number(element.hover.x),
element.hover.y = isString(element.hover.y) ? transformString(element.hover.y, height - borderLineWidths[2]) : Number(element.hover.y),
element.hover.width = isString(element.hover.width) ? transformString(element.hover.width, width - borderLineWidths[1]) : Number(element.hover.width),
element.hover.height = isString(element.hover.height) ? transformString(element.hover.height, height - borderLineWidths[2]) : Number(element.hover.height),
element.hover.x += 0, element.hover.y += 0), rect.x = rect.x + 0, rect.y = rect.y + 0,
result.push(element);
}
return result;
}
function transformString(str, size) {
return str.endsWith("px") ? parseInt(str, 10) : str.endsWith("%") && size ? parseInt(str, 10) / 100 * size : parseInt(str, 10);
}
export function dealPercentCalc(group, parentWidth, parentHeight) {
group && group.forEachChildren((child => {
var _a, _b;
child && (isObject(child.attribute.width) && child.attribute.width.percent && child.setAttribute("width", Math.max(0, child.attribute.width.percent / 100 * parentWidth + (null !== (_a = child.attribute.width.delta) && void 0 !== _a ? _a : 0))),
child.attribute.width < 0 && child.setAttribute("width", 0), isObject(child.attribute.height) && child.attribute.height.percent && child.setAttribute("height", Math.max(0, child.attribute.height.percent / 100 * parentHeight + (null !== (_b = child.attribute.height.delta) && void 0 !== _b ? _b : 0))),
child.attribute.height < 0 && child.setAttribute("height", 0), "group" === child.type && dealPercentCalc(child, child.attribute.width, child.attribute.height));
}));
}
export function decodeReactDom(dom, timeline) {
if (!dom || !isValid(dom.$$typeof) && !isValid(dom.vtype)) return dom;
const type = dom.type, {attribute: attribute, children: children, stateProxy: stateProxy, animation: animation} = dom.props, g = type({
attribute: attribute
});
if (parseToGraphic(g, dom.props), stateProxy && (g.stateProxy = stateProxy), g.id = attribute.id,
g.name = attribute.name, isArray(children) ? children.forEach((item => {
const c = decodeReactDom(item, timeline);
c && c.type && g.add(c);
})) : children && g.add(decodeReactDom(children, timeline)), isArray(animation) && timeline) {
const animate = g.animate();
animate.setTimeline(timeline), animation.forEach((item => {
animate[item[0]](...item.slice(1));
}));
}
return g;
}
function parseToGraphic(g, props) {
let isGraphic = !1;
switch (g.type) {
case "richtext":
case "rich/image":
break;
default:
isGraphic = !0;
}
isGraphic && Object.keys(props).forEach((k => {
const en = REACT_TO_CANOPUS_EVENTS[k];
en && g.on(en, props[k]);
}));
}
function bindAttributeUpdate(group, col, row, index, preId) {
group && (group.name = `${CUSTOM_MERGE_PRE_NAME}${null != preId ? preId : ""}_${index}`,
group.onBeforeAttributeUpdate = onBeforeAttributeUpdate, "group" === group.type && group.childrenCount && group.forEachChildren(((child, childIndex) => {
bindAttributeUpdate(child, col, row, childIndex, (null != preId ? preId : "") + "_" + index);
})));
}
function onBeforeAttributeUpdate(val, attribute) {
const graphic = this;
if (graphic.skipMergeUpdate) return;
const cellGroup = getTargetCell(graphic);
if (!cellGroup || !cellGroup.stage) return;
const table = cellGroup.stage.table;
graphic.skipAttributeUpdate = !0;
const {mergeStartCol: mergeStartCol, mergeEndCol: mergeEndCol, mergeStartRow: mergeStartRow, mergeEndRow: mergeEndRow} = cellGroup;
if (isValid(mergeStartCol) && isValid(mergeEndCol) && isValid(mergeStartRow) && isValid(mergeEndRow) && (mergeStartCol !== mergeEndCol || mergeStartRow !== mergeEndRow)) {
for (let col = mergeStartCol; col <= mergeEndCol; col++) for (let row = mergeStartRow; row <= mergeEndRow; row++) {
if (col === cellGroup.col && row === cellGroup.row) continue;
const cell = table.scenegraph.highPerformanceGetCell(col, row);
if ("cell" === cell.role) {
const target = cell.getChildByName(graphic.name, !0);
if (!target || target.skipAttributeUpdate) continue;
for (const key in val) val[key] !== target.attribute[key] && "dx" !== key && "dy" !== key && target.setAttribute(key, val[key]);
}
}
graphic.skipAttributeUpdate = void 0;
}
}
//# sourceMappingURL=custom.js.map