需要事先道歉:因为长度和我的无知。我正在尝试自学新概念:d3.js和精灵表。精灵表概念很容易理解,但我很困惑如何将它整合到d3中。基本上我想要做的是从精灵表中选择我想用作图像的精灵,然后使用d3在页面上的其他地方显示这个选定的精灵,并且很可能是同一精灵的多个副本。
实际精灵表供参考(见下文免责声明):
以下是问题:
1)我将精灵表添加到我的html,现在硬编码<clipPath>
,这显示了我想要的特定精灵,然而,精灵的尺寸/位置就像显示整个精灵表一样。我怎样才能“捕捉”精灵本身,而不仅仅是隐藏未使用的精灵?在下图中,我想在d3鼠标悬停事件中使用单个“图标”(第2部分)。
修改此示例:SO: Display CSS image sprite in SVG without using foreignObject
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>
结果
2)我可以使用<pattern>
来确定要在d3对象/事件中显示的图像。就像在矩形中显示图形一样。但这似乎不适用于大型图像(精灵表)?如果我尝试使用精灵表本身及其在模式中的原生尺寸,它会变得奇怪和模糊。如果我们解决第1部分,我们可能会忽略第2部分,但这对于了解一般知识/将来的使用会很好。
修改此示例:SO: Adding an image within a circle object in 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>
使用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");
});
结果
3)如果有更有效的方法来实现这一点,我愿意接受建议。我只是坚持使用d3模型,因为我已经渲染了一个svg对象,我只需要添加它。
免责声明:图标不是我的作品!我使用这些图标仅用于教育目的。作者的链接在这里:Fitness Icons
答案 0 :(得分:8)
我不确定<pattern>
示例会发生什么,但您<image>
元素的问题在于您没有翻译图像,因此您想要的图标位于(0 ,0)SVG的一点。
这就是你需要的:
<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>
当然,如果您要制作大量图标并使用多个位置,我建议:
<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>
然后你引用这样的图标:
<svg class="icon" viewBox="0 0 150 100" height="4em" width="6em">
<use xlink:href="#icon3"/>
</svg>
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");
当然,如果你正在使用d3,你可能会得到一些数据变量来告诉你使用哪个图标而不是类,但你明白了。
答案 1 :(得分:0)
我认为剪辑和定位图标的一种更简单的方法是使用带有适当<svg>
的嵌套viewBox
。
<svg width="100%" height="100%">
<!-- Repeat this for ever icon instance you want.
Just change x and y attributes to set position of the icon in your SVG,
and minX,minY (first two coords) of viewBox to select icon from sprite sheet. -->
<svg x="0" y="0" width="150px" height="150px" viewBox="135 0 150 150">
<image width="550px" height="420px" xlink:href="http://i.stack.imgur.com/qAO2h.png" />
</svg>
</svg>
&#13;