antvis / S2

⚡️ A practical visualization library for tabular analysis.

Home Page:https://s2.antv.antgroup.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

next版本自定义 DataCell,给数值单元格添加HTML内容, HTML会覆盖在冻结行列上方

FuYanson opened this issue · comments

🏷 Version
node: v20.10.0
npm: 9.5.0
"@antv/g": "^6.0.2",
"@antv/s2": "2.0.0-next.17",
"@antv/s2-vue": "2.0.0-next.12",
"vue": "^3.3.8",

export class CustomDataCell extends DataCell {
    // 重写数值单元格
    initCell () {
        super.initCell();
        // 绘制图形
        this.renderDrawGraph();
    }
    // 绘制图形
    renderDrawGraph () {
        let { x, y, width, height, data, valueField, rowIndex, colIndex, rowId, colId, spreadsheet, field, id } = this.meta;
        const cellMeta = spreadsheet.facet.getCellMeta(rowIndex, colIndex)
        const layoutResult = spreadsheet.facet?.getLayoutResult()
        const canvas = spreadsheet.getCanvas()
        let { customParams } = this.spreadsheet.options
        const params = customParams?.params
        let positionX = x;
        let positionY = y + height / 2;
        const currentData = data?.raw
        const innerHTML = `<div id="container" style="overflow: hidden;">
                <div></div>
                <div style="display:inline-block;">
                    <div style="background-color: #F1F2F6; border-radius: 6px;color: #aaaaab;">同比</div> 
                    <div>20%</div> 
                </div>
                <div style="display:inline-block;">
                    <div style="background-color: #F1F2F6; border-radius: 6px;color: #aaaaab;">上期</div> 
                    <div>200.00</div> 
                </div>
            <div>`
            const html = new HTML({
                style: {
                    x,
                    y,
                    width,
                    height,
                    innerHTML,
                    fontSize: '12px',
                    textAlign: 'center',
                    pointerEvents: 'none', // 让事件穿透它
                    // color: '#000',
                    // visibility: 'hidden',
                },
            })
            // canvas.appendChild(html);
            this.appendChild(html);
    }
image image

appendChild 绘制的图形 始终定位在一处, 未根据所设置的x、y轴坐标定位

你好 @FuYanson,请编辑你的 issue 标题, 一个言简意赅的 issue 标题可以节省大家的时间, 请不要将标题当做正文, 或者为空。

Hello, @FuYanson, please edit your issue title. a concise issue title will save everyone time. please do not leave the title as the body or empty.

你在 initCell 后渲染的 HTML 图层, 如 G 的文档所示, HTML 的实现是在 <canvas/> 中添加一个 DOM 元素, 就好比所有元素都是绝对定位, 而不是一个 Canvas 元素, 所以肯定是会覆盖的, 需要自行管理所有图层的坐标的裁剪.

image

内部单元格已经适配了滚动后的裁剪:

protected dynamicRenderCell(skipScrollEvent?: boolean) {
const {
scrollX,
scrollY: originalScrollY,
rowHeaderScrollX,
} = this.getScrollOffset();
const scrollY = originalScrollY + this.getPaginationScrollY();
this.spreadsheet.hideTooltip();
this.spreadsheet.interaction.clearHoverTimer();
this.realDataCellRender(scrollX, scrollY);
this.updatePanelScrollGroup();
this.translateRelatedGroups(scrollX, scrollY, rowHeaderScrollX);
this.clip(scrollX, scrollY);

你虽然看似是添加在单元格内部, 但是其实元素变成了一个绝对定位的 dom, 而不是一个单元格内部的 Group 图层.

this.appendChild(html);

你光设置了 HTML 的 宽高左边和单元格一致, 但是还需考虑滚动的偏移/裁剪等问题, 比如在滚动裁剪溢出部分, 避免遮挡, 需要对源码和 AntV/G 有一定的了解, 上手成本有点高, 不建议在有滚动条的场景中使用, 可以使用 Text 去绘制.

this.panelScrollGroup.style.clipPath = new Rect({
style: {
x: panelScrollGroupClipX,
y: panelScrollGroupClipY,
width: panelScrollGroupClipWidth,
height: panelScrollGroupClipHeight,
},
});

protected clip(): void {
const { width, viewportHeight, position, spreadsheet } =
this.getHeaderConfig();
const frozenRowGroupHeight = (spreadsheet.facet as FrozenFacet)
.frozenGroupInfo[FrozenGroupType.FROZEN_ROW].height;
this.scrollGroup.style.clipPath = new Rect({
style: {
x: spreadsheet.facet.cornerBBox.x,
y: position.y + frozenRowGroupHeight,
width,
height: viewportHeight,
},
});
this.frozenRowGroup.style.clipPath = new Rect({
style: {
x: spreadsheet.facet.cornerBBox.x,
y: position.y,
width,
height: frozenRowGroupHeight,
},
});
}

作为类比, 比如单元格内添加一个普通的图形, 都是能正常裁剪覆盖的:

    const icon = new GuiIcon({
      x,
      y,
      name: 'Plus',
      width: 24,
      height: 24,
      fill: 'red',
    });

    this.appendChild(icon);
    // this.appendChild(html);

image