svg + Sprite sheet + d3 + clipPath + position + size

僤鯓⒐⒋嵵緔 提交于 2019-12-03 07:13:24

I'm not sure what's going on with <pattern> example, but the problem with your <image> element is that you're not translating the image so that the icon you want is at the (0,0) point of the SVG.

This is what you need:

<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>

Of course, if you're going to be making lots of icons and using them multiple places, I would suggest:

  1. defining the icons within a <defs> element, and then referencing them when needed with <use> elements;
  2. using a <use> element to position the image in each icon, so you only have to define the image url, height, and width once;
  3. nesting each image/use element within a <g> element, and applying the clipping path to it, so that you only have to define the clipping path once (assuming all icons are the same size).

Example here: http://codepen.io/AmeliaBR/pen/mwzBD

Key code for defining the icons:

<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>

Then you reference the icons like this:

<svg class="icon" viewBox="0 0 150 100" height="4em" width="6em">
        <use xlink:href="#icon3"/>
</svg>

The viewBox attribute sets the internal dimensions for laying out the image and will be the same every time you use the icon; the height and width can be anything you want (although scaling down will of course look better than scaling up). If the height/width ratio doesn't match the icon, it will be squished or stretched, but you can prevent that with a preserveAspectRatio attribute.

Now, on to d3. It will probably be easiest to define the SVG fragments that represent the icons ahead of time, possibly in a separate file, although you could construct that DOM dynamically. When you actually want to insert an icon, you

For example, to add an inline icon image at the end of every element with the class "warning", you would do something like this:

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");

Of course, if you're using d3, you've probably got some data variable that tells you which icon to use, instead of a class, but you get the idea.

I think a much simpler way to clip and position the icon is by using a nested <svg> with an appropriate 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>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!