如何在D3.js图谱中实现选中节点的自动缩放(保留高亮效果)
D3.js演员节点图谱实现选中节点自动缩放功能
我有一个基于D3.js的演员节点图谱,已经实现了搜索栏功能,可以搜索并选中演员,选中时节点会以黄色光晕高亮。现在需要实现:选中演员节点时自动缩放至该节点,同时保留黄色光晕效果。以下是处理黄色高亮的代码,请教如何用D3.js实现自动缩放功能:
actorSearched: function () { // if actor selected in autocomplete if (this.actorSearched != "" && this.actorSearched) { //reset radius when switching to one actor to another if (this.lastSearchedNodeHtmlElement) { this.lastSearchedNodeHtmlElement.setAttribute("r", this.lastSearchedNodeDefaultRadius) this.lastSearchedNodeCoords = [] } //reset vars this.lastSearchedNodeDefaultRadius = 0 this.lastSearchedNodeHtmlElement = "" //get the searched node's html elem var elements = document.getElementsByClassName("circle-group") let elementsArray = [].slice.call(elements); let searchedElement = elementsArray.filter((obj) => { return ( ([this.actorSearched].includes(obj.id)) ); }); // set variables this.lastSearchedNodeDefaultRadius = searchedElement[0].firstChild.getAttribute("r") this.lastSearchedNodeHtmlElement = searchedElement[0].firstChild searchedElement[0].firstChild.setAttribute("r", "25px") this.getNode(this.lastSearchedNodeHtmlElement.__data__.id) // parse node coords let coordsRaw = searchedElement[0].getAttribute("transform") coordsRaw = coordsRaw.substring(10) coordsRaw = coordsRaw.slice(0, -1) this.lastSearchedNodeCoords = coordsRaw.split(",") }
注:黄色光晕通过放大目标节点后方的黄色节点实现,选中效果为节点带有黄色光晕高亮。
实现自动缩放的具体方案
1. 先确保SVG容器绑定缩放行为
如果你的SVG还没绑定d3.zoom,先添加这段基础代码(假设图谱元素都放在.graph-group分组下):
// 初始化缩放行为 const zoom = d3.zoom() .scaleExtent([0.1, 10]) // 限制缩放范围,避免过度缩放 .on("zoom", (event) => { // 让图谱分组跟随缩放平移 this.svg.select(".graph-group").attr("transform", event.transform); }); // 把缩放行为绑定到SVG容器上 this.svg.call(zoom);
2. 修改actorSearched函数,添加缩放逻辑
在原代码的节点坐标解析完成后,新增自动缩放的代码:
actorSearched: function () { // if actor selected in autocomplete if (this.actorSearched !== "" && this.actorSearched) { //reset radius when switching to one actor to another if (this.lastSearchedNodeHtmlElement) { this.lastSearchedNodeHtmlElement.setAttribute("r", this.lastSearchedNodeDefaultRadius); this.lastSearchedNodeCoords = []; } //reset vars this.lastSearchedNodeDefaultRadius = 0; this.lastSearchedNodeHtmlElement = ""; //get the searched node's html elem var elements = document.getElementsByClassName("circle-group"); let elementsArray = [].slice.call(elements); let searchedElement = elementsArray.filter((obj) => { return [this.actorSearched].includes(obj.id); }); // set variables this.lastSearchedNodeDefaultRadius = searchedElement[0].firstChild.getAttribute("r"); this.lastSearchedNodeHtmlElement = searchedElement[0].firstChild; searchedElement[0].firstChild.setAttribute("r", "25px"); this.getNode(this.lastSearchedNodeHtmlElement.__data__.id); // parse node coords,转换为数字类型 let coordsRaw = searchedElement[0].getAttribute("transform"); coordsRaw = coordsRaw.substring(10); coordsRaw = coordsRaw.slice(0, -1); this.lastSearchedNodeCoords = coordsRaw.split(",").map(Number); // --- 新增自动缩放逻辑 --- const targetX = this.lastSearchedNodeCoords[0]; const targetY = this.lastSearchedNodeCoords[1]; const svgWidth = this.svg.node().clientWidth; const svgHeight = this.svg.node().clientHeight; const scale = 2; // 自定义缩放倍数,可根据需求调整 // 计算平移量,让目标节点居中显示 const translateX = svgWidth / 2 - scale * targetX; const translateY = svgHeight / 2 - scale * targetY; // 执行平滑缩放过渡 this.svg.transition() .duration(750) // 动画时长(毫秒),可调整 .call(zoom.transform, d3.zoomIdentity.translate(translateX, translateY).scale(scale)); } }
关键说明
d3.zoomIdentity是初始缩放状态,通过translate和scale调整到目标视图- 使用
transition()添加平滑动画,避免缩放切换过于突兀 - 确保所有图谱元素都在同一个可被平移缩放的分组内(比如示例中的
.graph-group),否则只有部分元素会跟随缩放 - 缩放倍数
scale可以根据你的可视化需求调整,比如设为3表示放大3倍
内容的提问来源于stack exchange,提问作者Quentin
相关产品推荐
相关产品推荐

