javascript - svg + Sprite 表 + d3 + clipPath + 位置 + 大小

原文 标签 javascript svg d3.js sprite-sheet

需要提前道歉:长度和我的无知。我正在尝试自学新概念:d3.js 和 Sprite 表。 Sprite 表的概念很容易理解,但我很困惑如何将其集成到 d3 中。基本上我想要做的是从 Sprite 表中选择我想用作图像的 Sprite ,然后使用 d3 在页面上的其他地方显示这个选定的 Sprite ,并且很可能是同一 Sprite 的多个副本。

供引用的实际 Sprite 表(请参阅下面的免责声明):
Sample icons see disclaimer below

以下是问题:
1) 我将 Sprite 表添加到我的 html,硬编码 <clipPath>现在,这显示了我想要的特定 Sprite ,但是, Sprite 的尺寸/位置就像显示了整个 Sprite 表一样。我怎样才能只“捕获” Sprite 本身,而不仅仅是隐藏未使用的 Sprite ?在下图中,我想在 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>

结果

Using clipPath

2) 我可以使用 <pattern>确定要在 d3 对象/事件中显示的图像。就像在矩形中显示图形一样。但这似乎不适用于大图像( Sprite 表)?如果我尝试在模式中使用 Sprite 表本身及其原始尺寸,它会变得奇怪和模糊。如果我们解决了第 1 部分,我们可能可以忽略第 2 部分,但这对于理解一般知识/ future 使用会很好。

修改这个例子: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");
         });

结果

Weird scaling when using <pattern>

3)如果有更有效的方法来实现这一点,我愿意接受建议。我只是坚持使用 d3 模型,因为我已经渲染了一个 svg 对象,我只需要向它添加一些东西。

免责声明:图标不是我的作品!我仅将这些图标用于教育目的。作者链接在此:Fitness Icons

最佳答案

我不确定 <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>

当然,如果您要制作大量图标并在多个地方使用它们,我建议:
  • <defs> 中定义图标元素,然后在需要时使用 <use> 引用它们元素;
  • 使用 <use>用于在每个图标中定位图像的元素,因此您只需定义图像 url、高度和宽度一次;
  • <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属性设置用于布局图像的内部尺寸,并且每次使用图标时都相同;高度和宽度可以是你想要的任何东西(尽管缩小当然看起来比放大更好)。如果高度/宽度比与图标不匹配,它将被压扁或拉伸(stretch),但您可以使用 preserveAspectRatio 来防止这种情况发生。属性。

    现在,进入 d3。提前定义表示图标的 SVG 片段可能是最简单的,可能在一个单独的文件中,尽管您可以动态构建该 DOM。当你真的想插入一个图标时,你

    例如,要在每个具有“警告”类的元素的末尾添加一个内嵌图标图像,您可以执行以下操作:
    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,您可能有一些数据变量告诉您​​使用哪个图标,而不是一个类,但是您明白了。

    关于javascript - svg + Sprite 表 + d3 + clipPath + 位置 + 大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21193447/

    相关文章:

    javascript - jQuery将JSON值插入具有特定类的元素

    javascript - 如何定义“溢出”属性

    javascript - D3js - 单个外部 SVG 文件的多个实例

    javascript - 如何获取svg文档中嵌入式图像的真实(未缩放)大小?

    javascript - 在JavaScript中使用RegEx查找html标签

    javascript - 在v-if和else条件内给出btn-next时不起作用?

    javascript - 即使鼠标不动,也会触发D3“拖动”事件

    javascript - jQuery slider 设置不正确的ui.values

    d3.js - D3JS 选择和类

    javascript - 另一个函数中的 JQuery 函数调用