Jam*_*mes 7 javascript svg sprite-sheet d3.js
需要提前道歉:长度和我的无知.我正在尝试自学新概念:d3.js和精灵表.精灵表概念很容易理解,但我很困惑如何将它整合到d3中.基本上我想要做的是从精灵表中选择我想用作图像的精灵,然后使用d3在页面上的其他地方显示这个选定的精灵,并且很可能是同一精灵的多个副本.
实际的精灵表供参考(见下文免责声明):

以下是问题:1)我将精灵表添加到我的html中,硬编码<clipPath>现在,这显示了我想要的特定精灵,但是,精灵的尺寸/位置就像显示整个精灵表一样.我怎样才能"捕捉"精灵本身,而不仅仅是隐藏未使用的精灵?在下图中,我想在d3鼠标悬停事件中使用单个"图标"(第2部分).
修改此示例:SO:在不使用foreignObject的情况下在SVG中显示CSS图像精灵
HTML
<svg id="mySvg1" width="100%" height="100%">
<defs>
<clipPath id="c">
<rect x="135" y="0" width="150" height="150"/>
</clipPath>
</defs>
<image transform="scale(1.0)" x="0" y="0" width="550" height="420" xlink:href="static/img/iconSheet.png" clip-path="url(#c)"/>
<svg>
Run Code Online (Sandbox Code Playgroud)
结果

2)我可以<pattern>用来确定要在d3对象/事件中显示的图像.就像在矩形中显示图形一样.但这似乎不适用于大型图像(精灵表)?如果我尝试使用精灵表本身及其在模式中的原生尺寸,它会变得奇怪和模糊.如果我们解决第1部分,我们可能会忽略第2部分,但是对于一般知识/将来的使用,这将是很好的理解.
修改此示例:SO:在d3 javascript中在圆形对象中添加图像?
HTML
<svg id="mySvg" width="550" height="420">
<defs id="mdef">
<pattern id="image" x="0" y="0" height="550" width="420">
<image transform="scale(1.0)" x="0" y="0" width="550" height="420" xlink:href="static/img/iconSheet.png"></image>
</pattern>
</defs>
</svg>
Run Code Online (Sandbox Code Playgroud)
使用Javascript:
var svgContainer = d3.select("div#content-main").append("svg")
.attr("width", 740)
.attr("height", 760)
.attr("class", "mySvg")
.style("border", "none");
svgContainer.append("rect")
.attr("class", "logo")
.attr("x", 0)
.attr("y", 0)
.attr("width", 550)
.attr("height", 420)
.style("fill", "transparent")
.style("stroke", "black")
.style("stroke-width", 0.25)
.on("mouseover", function(){
d3.select(this)
.style("fill", "url(#image)");
})
.on("mouseout", function(){
d3.select(this)
.style("fill", "transparent");
});
Run Code Online (Sandbox Code Playgroud)
结果

3)如果有更有效的方法来实现这一点,我愿意接受建议.我只是坚持使用d3模型,因为我已经渲染了一个svg对象,我只需要添加它.
免责声明:图标不是我的作品!我使用这些图标仅用于教育目的.作者的链接在这里:健身图标
我不确定<pattern>示例中发生了什么,但你的<image>元素的问题是你没有翻译图像,所以你想要的图标位于SVG的(0,0)点.
这就是你需要的:
<svg id="mySvg1" width="100%" height="100%" viewBox="0 0 150 150">
<defs>
<clipPath id="c">
<rect x="135" y="0" width="150" height="150"/>
</clipPath>
</defs>
<image transform="translate(-135,0)" width="550" height="420"
xlink:href="static/img/iconSheet.png" clip-path="url(#c)"/>
<svg>
Run Code Online (Sandbox Code Playgroud)
当然,如果您要制作大量图标并将它们用于多个位置,我建议:
<defs>元素中的图标,然后在需要时使用<use>元素引用它们;<use>元素在每个图标中定位图像,因此您只需要定义图像的网址,高度和宽度一次;<g>元素中,并将剪切路径应用于它,这样您只需定义剪切路径一次(假设所有图标大小相同).例如:http://codepen.io/AmeliaBR/pen/mwzBD
用于定义图标的关键代码:
<svg class="icon-defs">
<defs>
<!-- The icons are defined in an SVG <defs> element;
it could be in a different file,
since the icons will be referenced by url. -->
<!-- One clipping path defines icon size -->
<clipPath id="icon-cp" >
<rect x="0" y="0" width="150" height="100" />
</clipPath>
<!-- One image element imports the file -->
<image id="icon-sprite" width="969" height="293"
xlink:href="http://i.stack.imgur.com/TPx5h.png" />
<!-- Each icon fragment uses the same image
with a different translation -->
<g id="icon1" clip-path="url(#icon-cp)">
<use xlink:href="#icon-sprite"
transform="translate(0,0)" />
</g>
<g id="icon2" clip-path="url(#icon-cp)">
<use xlink:href="#icon-sprite"
transform="translate(-240,0)" />
</g>
<g id="icon3" clip-path="url(#icon-cp)">
<use xlink:href="#icon-sprite"
transform="translate(-240,-193)" />
</g>
</defs>
Run Code Online (Sandbox Code Playgroud)
然后你引用这样的图标:
<svg class="icon" viewBox="0 0 150 100" height="4em" width="6em">
<use xlink:href="#icon3"/>
</svg>
Run Code Online (Sandbox Code Playgroud)
该viewBox属性设置布局图像的内部尺寸,每次使用图标时都相同; 高度和宽度可以是你想要的任何东西(虽然缩小当然看起来比放大更好).如果高度/宽度比率与图标不匹配,则会被压缩或拉伸,但您可以使用preserveAspectRatio属性来阻止它.
现在,到d3.虽然您可以动态地构造该DOM,但可能最容易定义提前表示图标的SVG片段,可能在单独的文件中.当你真的想要插入一个图标时,你
例如,要在每个元素的末尾添加带有"警告"类的内联图标图像,您可以执行以下操作:
d3.selectAll(".warning")
.append("svg")
.attr("viewBox", "0 0 "+ iconWidth + " " + iconHeight)
.style("display", "inline")
.style("height", "1em")
.style("width", (iconWidth/iconHeight) + "em")
.append("use")
.attr("xlink:href", "#warning");
Run Code Online (Sandbox Code Playgroud)
当然,如果你正在使用d3,你可能会得到一些数据变量来告诉你使用哪个图标而不是类,但你明白了.