我们有一个静态SVG图像,我们试图在AngularJS应用程序的上下文中使用d3.js动态添加工具提示来说明SVG图像中对象上的悬停事件。
SVG图像是一个平面图并且相当复杂,但是我们在POC过程中开始时非常小。以下是一个部分的小代表性片段:
<g id="f3s362c12">
<g>
<rect x="75.2" y="92.4" pointer-events="visible" fill="none"
width="64.7" height="57.8" />
<polyline fill="none" stroke="#CDDDED" stroke-width="0.5"
stroke-miterlimit="10" points="118.4,149.9 140.3,149.9 140.3,92.4
75.2,92.4 75.2,128.7" />
</g>
<g>
<text transform="matrix(1 0 0 1 87.8719 144.8836)" fill="#010101"
font-family="arial, sans-serif" font-size="13.4182">362.12</text>
</g>
</g>
D3.js对我们来说是新的,但是从我们的研究来看,它似乎能够做我们需要它做的事情,因为它似乎被设计为与SVG一起工作并在SVG中表示数据,但是所有的我们发现的例子是动态创建SVG(主要是图表)但不操纵现有的SVG图像。
简而言之,我们需要做的是:
({ “地板”: “3”, “位置”: “的 f3s362c12 ”, “名称”:“大卫 Byrne的”, “OCC”: “歌手”, “IMG”: “IMG / davidAvatar.jpg \ R”})
我创建了一个Plunk:
我们遇到的问题是d3.js. 例如,在我们的Plunk中,在script.js中,我们这样做是为了找到我们的g标签:
var svg = d3.select("#svgFP");
var allG = svg.selectAll("g").each(function (d,i) {}
然而,由于我们试图使用“this”关键字在allG上找到一个矩形,所以我们就此碰到了。
if (this.id.indexOf("f3") > -1)
{
//1. Add label/div/hover
//2. Find corresponding record from array object.
//3. Inject respective name, occupation and image into label/div along with mouseover/mouseout event.
}
我们一直在使用Firebug来尝试查找要使用的属性,但至少可以说它非常令人沮丧且毫无结果,因此我们认为在SO中可能会有一个或两个d3 /角度大师可能向我们展示道路。
提前致谢。
答案 0 :(得分:3)
您在plunker中遇到的第一个问题是您的CSV:CSV的第一行必须是标题,它定义了每列的内容。因此,我将您的CSV修改为:
floor,location,name,surname,role,image
3,f3s362c12,David ,Byrne,Singer,img/davidAvatar.jpg
3,f3s362c11,Tina,Weymouth,Bassist,img/tinaAvatar.jpg
3,f3s362c2,Jerry,Harrison,Keyboards,img/jerryAvatar.jpg
3,f3s362c1,Chris,Frantz,Drums,img/chrisAvatar.jpg
现在出现了你的实际问题。
D3代码的最佳解决方案是将数据绑定到DOM元素(在本例中为SVG)。但是,既然你已经有了一个静态的SVG,而不是用D3制作而没有任何绑定数据,那么这就是一个解决方案。
首先,选择所有相关的组元素:
var groups = d3.selectAll("g[id^='f3']");
并将mouseover
代码添加到该选择中。
在mouseover
代码中出现了此解决方案中最重要的部分:我们获取了光标所在元素的ID ...
var groupId = this.id
...然后,根据此ID,我们会过滤先前加载的CSV:
var thisData = data.filter(function(d) {
return d.location === groupId
});
以上代码的作用如下:我们将CSV加载到名为data
的变量中。该变量是一个对象数组,每个对象都有一个location
属性(查看我创建的CSV标题)。然后,我们将每个对象的location
(d.location
)与组的ID(groupId)进行比较。
现在,您有一个名为thisData
的变量,您可以使用它来填充工具提示。
以下是包含 MCVE 版本代码的演示:
var tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("background-color", "gainsboro")
.style("border", "1px solid black")
.style("padding", "20px")
.style("pointer-events", "none")
.style("font-size", "12px");
var data = d3.csvParse(d3.select("#csv").text());
var groups = d3.selectAll("g[id^='f3']");
groups.on("mousemove", function() {
var groupId = this.id
var thisData = data.filter(function(d) {
return d.location === groupId
});
tooltip.html("Name: " + thisData[0].name + " " + thisData[0].surname + "<br>Role: " + thisData[0].role)
.style("top", (d3.event.pageY - 2) + "px").style("left", (d3.event.pageX + 2) + "px")
.style("visibility", "visible");
}).on("mouseout", function() {
tooltip.style("visibility", "hidden");
});
&#13;
pre {
display: none;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300" height="100%">
<g id="background">
<rect x="1.5" y="0.3" fill="#5A8CC9" width="298.7" height="300.4" />
</g>
<g id="f3s362c12">
<g>
<rect x="75.2" y="92.4" pointer-events="visible" fill="none" width="64.7" height="57.8" />
<polyline fill="none" stroke="#CDDDED" stroke-width="0.5" stroke-miterlimit="10" points="118.4,149.9 140.3,149.9 140.3,92.4
75.2,92.4 75.2,128.7 " />
</g>
<g>
<text transform="matrix(1 0 0 1 87.8719 144.8836)" fill="#010101" font-family="arial, sans-serif" font-size="13.4182">362.12</text>
</g>
</g>
<g id="f3s362c11">
<g>
<rect x="75.2" y="149.9" pointer-events="visible" fill="none" width="64.7" height="57.8" />
<polyline fill="none" stroke="#CDDDED" stroke-width="0.5" stroke-miterlimit="10" points="118.4,207.8 140.3,207.8 140.3,149.9
75.2,149.9 75.2,186.2 " />
</g>
<g>
<text transform="matrix(1 0 0 1 87.8719 201.6532)" fill="#010101" font-family="arial, sans-serif" font-size="13.4182">362.11</text>
</g>
</g>
<g id="f3s362c2">
<g>
<rect x="140.3" y="149.9" pointer-events="visible" fill="none" width="68.8" height="57.8" />
<polyline fill="none" stroke="#CDDDED" stroke-width="0.5" stroke-miterlimit="10" points="208.7,183.5 208.7,149.9 140.3,149.9
140.3,207.8 185.8,207.8 " />
</g>
<g>
<text transform="matrix(1 0 0 1 163.782 201.6532)" fill="#010101" font-family="arial, sans-serif" font-size="13.4182">362.2</text>
</g>
</g>
<g id="f3s362c1">
<g>
<rect x="140.3" y="92.4" pointer-events="visible" fill="none" width="68.8" height="57.8" />
<polyline fill="none" stroke="#CDDDED" stroke-width="0.5" stroke-miterlimit="10" points="208.7,126 208.7,92.4 140.3,92.4
140.3,149.9 185.8,149.9 " />
</g>
<g>
<text transform="matrix(1 0 0 1 163.782 144.8836)" fill="#010101" font-family="arial, sans-serif" font-size="13.4182">362.1</text>
</g>
</g>
</svg>
<pre id="csv">floor,location,name,surname,role,image
3,f3s362c12,David ,Byrne,Singer,img/davidAvatar.jpg
3,f3s362c11,Tina,Weymouth,Bassist,img/tinaAvatar.jpg
3,f3s362c2,Jerry,Harrison,Keyboards,img/jerryAvatar.jpg
3,f3s362c1,Chris,Frantz,Drums,img/chrisAvatar.jpg</pre>
&#13;
总结一下,这些是步骤:
<g>
上时,请根据<g>
的ID过滤您的数据阵列; html
。 PS:在此代码段中,我使用<pre>
元素存储您的CSV。我只是这样做,因为与Plunker不同,我无法使用S.O.加载CSV。片段。