You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shadow DOM中Plotly Sankey图提示框不显示及节点点击识别异常问题求助

Shadow DOM中Plotly Sankey图提示框不显示及节点点击识别异常问题求助

大家好,我正在基于Web Component(Shadow DOM)开发一个自定义的Sankey图组件,使用的是plotly.js v2.30.1。目前图表可以正常渲染,但碰到了两个关键问题:

  • *悬停提示框(hover tooltips)*完全无法显示,我尝试过用全局CSS样式进行调整,但没有任何效果
  • 节点点击事件识别异常:点击节点时,触发的是链接(link)点击的提示,而不是预期的节点点击逻辑

以下是我的最小复现示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title></title>
    <script src="https://cdn.plot.ly/plotly-2.30.1.min.js"></script>
    <style>
        html, body { height: 100%; margin: 0; }
        sankey-sd { display: block; width: 100vw; height: 100vh; }
    </style>
</head>
<body>
    <sankey-sd></sankey-sd>
    <script>
        window.addEventListener('DOMContentLoaded', () => {
            class SankeySD extends HTMLElement {
                constructor() {
                    super();
                    this.attachShadow({ mode: 'open' });
                }

                connectedCallback() {
                    const chartDiv = document.createElement('div');
                    chartDiv.id = 'chart';
                    chartDiv.style.width = '100%';
                    chartDiv.style.height = '100%';
                    chartDiv.style.minWidth = '200px';
                    chartDiv.style.minHeight = '200px';
                    this.shadowRoot.appendChild(chartDiv);

                    const labels = ["Start", "Middle", "Begin", "End", "Final"];
                    const labelIndex = new Map(labels.map((label, i) => [label, i]));

                    const links = [
                        { source: "Start", target: "Middle", value: 5, label: "Test" },
                        { source: "Start", target: "Middle", value: 3, label: "Test2" },
                        { source: "Middle", target: "Start", value: 1, label: "" },
                        { source: "Start", target: "End", value: 2, label: "" },
                        { source: "Begin", target: "Middle", value: 5, label: "Test" },
                        { source: "Middle", target: "End", value: 3, label: "" },
                        { source: "Final", target: "Final", value: 0.0001, label: "" }
                    ];

                    const sources = links.map(link => labelIndex.get(link.source));
                    const targets = links.map(link => labelIndex.get(link.target));
                    const values = links.map(link => link.value);
                    const customData = links.map(link => [link.source, link.target, link.value]);

                    const trace = {
                        type: "sankey",
                        orientation: "h",
                        arrangement: "fixed",
                        node: {
                            label: labels,
                            pad: 15,
                            thickness: 20,
                            line: { color: "black", width: 0.5 },
                            hoverlabel: {
                                bgcolor: "white",
                                bordercolor: "darkgrey",
                                font: { color: "black", family: "Open Sans, Arial", size: 14 }
                            },
                            hovertemplate: '%{label}<extra></extra>',
                            color: ["#a6cee3", "#1f78b4", "#b2df8a", "#a9b1b9", "#a9b1b9" ]
                        },
                        link: {
                            source: sources,
                            target: targets,
                            value: values,
                            arrowlen: 20,
                            pad: 20,
                            thickness: 20,
                            line: { color: "black", width: 0.2 },
                            color: sources.map(i => ["#a6cee3", "#1f78b4", "#b2df8a", "#a9b1b9", "#a9b1b9"][i]),
                            customdata: customData,
                            hoverlabel: {
                                bgcolor: "white",
                                bordercolor: "darkgrey",
                                font: { color: "black", family: "Open Sans, Arial", size: 14 }
                            },
                            hovertemplate: '<b>%{customdata[0]}</b> → <b>%{customdata[1]}</b><br>' +
                                'Flow Value: <b>%{customdata[2]}</b><extra></extra>'
                        }
                    };

                    const layout = {
                        font: { size: 14 },
                        margin: { t: 20, l: 10, r: 10, b: 10 },
                        hovermode: 'closest'
                    };

                    Plotly.newPlot(chartDiv, [trace], layout, { responsive: true, displayModeBar: true })
                        .then((plot) => {
                            chartDiv.on('plotly_click', function(eventData) {
                                if (!eventData || !eventData.points || !eventData.points.length) return;
                                const point = eventData.points[0];
                                if (typeof point.pointIndex === "number") {
                                    const nodeLabel = point.label;
                                    alert("Node clicked: " + nodeLabel + "\nNode index: " + point.pointIndex);
                                    console.log("Node clicked:", point);
                                } else if (typeof point.pointNumber === "number") {
                                    const linkIdx = point.pointNumber;
                                    const linkData = customData[linkIdx];
                                    alert(
                                        "Link clicked: " + linkData[0] + " → " + linkData[1] + "\nValue: " + linkData[2] + "\nLink index: " + linkIdx
                                    );
                                    console.log("Link clicked:", point);
                                } else {
                                    console.log("Clicked background", point);
                                }
                            });
                        });
                }
            }
            customElements.define('sankey-sd', SankeySD);
        });
    </script>
</body>
</html>

想请教一下社区的各位:

  1. Plotly.js目前是否支持在Shadow DOM环境下的Sankey图正常显示hover tooltips?如果支持的话,我的代码哪里可能出了问题?
  2. 节点点击识别异常的问题该如何修复,让点击节点时能正确触发节点的点击逻辑?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 09:44:32