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

D3.js路径描边交互设置问题(鼠标悬停、右键菜单)

解决D3.js路径仅描边触发交互的问题

当前你的路径设置了填充色,导致鼠标悬停或右键点击路径的整个区域(包括填充部分)都会触发事件。要实现仅描边触发交互,只需利用SVG的pointer-events属性:

  • 给路径添加pointer-events: stroke,该属性会限制鼠标事件仅在元素的描边区域触发
  • 如果不需要路径填充,也可以直接设置fill: none,这样路径的点击区域就只有描边本身

关键修改部分

在路径的属性配置中添加一行代码即可:

links = linksContainer.selectAll(".link")
    .data(data.links)
    .enter()
    .append("path")
    .attr("class", "link")
    .attr("fill", "lightgray")
    .attr("stroke", "black")
    .attr("stroke-width", "2px")
    .attr("cursor", "pointer")
    .attr("pointer-events", "stroke") // 关键:仅描边响应鼠标事件
    .on("mouseover", function(d) {
        d3.select(this).attr("stroke", "red")
    })
    .on("mouseout", function(d) {
        d3.select(this).attr("stroke", "black")   
    })
    .on("contextmenu", function(d) {
        alert("ContextMenu selected")
    })

若无需填充色,直接设置fill: none也能达到效果,此时甚至可以省略pointer-events配置:

.attr("fill", "none")

完整修改后的代码

JavaScript

var width = window.innerWidth,
    height = window.innerHeight;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .call(d3.zoom().on("zoom", function (event) {
        svg.attr("transform", event.transform)
    }))
    .append("g")

////////////////////////
// outer force layout

var data = {
    "nodes": [{
        "id": "A",
    },
    {
        "id": "B",
    },
    {
        "id": "C",
    }],
    "links": [{
        "source": "A",
        "target": "B"
    },
    {
        "source": "B",
        "target": "C"
    },
    {
        "source": "C",
        "target": "A"
    }]
}

var simulation = d3.forceSimulation()
    .force("size", d3.forceCenter(width / 2, height / 2))
    .force("charge", d3.forceManyBody().strength(-200))
    .force("link", d3.forceLink().id(function (d) {
        return d.id
    }).distance(250))

linksContainer = svg.append("g").attr("class", "linkscontainer")
nodesContainer = svg.append("g").attr("class", "nodesContainer")


links = linksContainer.selectAll(".link")
    .data(data.links)
    .enter()
    .append("path")
    .attr("class", "link")
    .attr("fill", "lightgray")
    .attr("stroke", "black")
    .attr("stroke-width", "2px")
    .attr("cursor", "pointer")
    .attr("pointer-events", "stroke")
    .on("mouseover", function(d) {
        d3.select(this).attr("stroke", "red")
    })
    .on("mouseout", function(d) {
        d3.select(this).attr("stroke", "black")   
    })
    .on("contextmenu", function(d) {
        alert("ContextMenu selected")
    })

nodes = nodesContainer.selectAll(".nodes")
    .data(data.nodes, function (d) {
        return d.id;
    })
    .enter()
    .append("g")
    .attr("class", "nodes")
    .call(d3.drag()
        .on("start", dragStarted)
        .on("drag", dragged)
        .on("end", dragEnded)
    )

nodes.selectAll("circle")
    .data(d => [d])
    .enter()
    .append("circle")
    .attr("class", "circle")
    .style("stroke", "blue")
    .attr("r", 40)

simulation
    .nodes(data.nodes)
    .on("tick", tick)

simulation
    .force("link")
    .links(data.links)

function tick() {
    links.attr("d", function (d) {
        var dx = (d.target.x - d.source.x),
            dy = (d.target.y - d.source.y),
            dr = Math.sqrt(dx * dx + dy * dy)

        return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
    })

    nodes
        .attr("transform", d => `translate(${d.x}, ${d.y})`);
}

function dragStarted(event, d) {
    if (!event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
}

function dragged(event, d) {
    d.fx = event.x;
    d.fy = event.y;
}

function dragEnded(event, d) {
    if (!event.active) simulation.alphaTarget(0);
    d.fx = null;
    d.fy = null;
}

CSS

.nodes {
    fill: whitesmoke;
    cursor: pointer;
}

HTML

<!DOCTYPE html>
<html lang="de">

<head>
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0">
    <meta charset="utf-8">

    <script src="https://code.jquery.com/jquery-3.6.3.js"></script>
    <script src="https://d3js.org/d3.v7.min.js"></script>
    <script src="https://kit.fontawesome.com/98a5e27706.js" crossorigin="anonymous"></script>
</head>

<body>

</body>

</html>

内容的提问来源于stack exchange,提问作者ICoded

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 13:35:00