我在 networkx 的帮助下从 wikidata 创建了如下有向图和 nxv .结果是一个 svg 文件,它可能嵌入到一些 html 页面中。
现在我希望每个节点和每条边都是“可点击的”,这样用户就可以将他们的评论添加到图形的特定元素中。我认为这可以通过弹出一个模态对话框来完成。这个对话框应该知道它是从哪个元素触发的,并且应该通过 post 请求将 textarea 的内容发送到某个 url。
实现这一目标的最佳方法是什么?
最佳答案
包裹在 W3C standard Web Component (在所有现代浏览器中都支持)您可以将其设为通用 src="filename.svg"
<graphviz-svg-annotator src="https://graphviz.org/Gallery/directed/fsm.svg">
</graphviz-svg-annotator>
<graphviz-svg-annotator src="fsm.svg"></graphviz-svg-annotator>
<graphviz-svg-annotator src="Linux_kernel_diagram.svg"></graphviz-svg-annotator>
<style>
svg .annotate { cursor:pointer }
</style>
<script>
customElements.define('graphviz-svg-annotator', class extends HTMLElement {
constructor() {
let loadSVG = async ( src , container = this.shadowRoot ) => {
container.innerHTML = `<style>:host { display:inline-block }
::slotted(svg) { width:100%;height:200px }
</style>
<slot name="svgonly">Loading ${src}</slot>`;
this.innerHTML = await(await fetch(src)).text(); // load full XML in lightDOM
let svg = this.querySelector("svg");
svg.slot = "svgonly"; // show only SVG part in shadowDOM slot
svg.querySelectorAll('g[id*="node"],g[id*="edge"]').forEach(g => {
let label = g.querySelector("text")?.innerHTML || "No label";
let shapes = g.querySelectorAll("*:not(title):not(text)");
let fill = (color = "none") => shapes.forEach(x => x.style.fill = color);
let prompt = "Please annotate: ID: " + g.id + " label: " + label;
g.classList.add("annotate");
g.onmouseenter = evt => fill("lightgreen");
g.onmouseleave = evt => fill();
g.onclick = evt => g.setAttribute("annotation", window.prompt(prompt));
})
}
super().attachShadow({ mode: 'open' });
loadSVG("//graphviz.org/Gallery/directed/"+this.getAttribute("src"));
}});
</script>
详细:
this.innerHTML = ...
在组件中注入(inject)完整的 XML 光域 (因为元素有shadowDOM,所以lightDOM在浏览器中是不可见的)
<slot>
仅用于 反射(reflect) <svg>
<svg>
仍然可以从 设置样式全局 CSS (见 cursor:pointer
)<g>
ID 值可能会发生冲突。完整的 SVG 可以是 移动 到 shadowDOM:
let svg = container.appendChild( this.querySelector("svg") );
但是你不能再用全局 CSS 为 SVG 设置样式,因为全局 CSS 不能为 shadowDOM 设置样式关于javascript - 如何使 svg 交互以收集对描绘元素的评论/注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66263255/