svg + Sprite sheet + d3 + clipPath + position + size [英] svg + Sprite sheet + d3 + clipPath + position + size

查看:294
本文介绍了svg + Sprite sheet + d3 + clipPath + position + size的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

需要提前道歉:长度和我的无知。我想教自己新的概念:d3.js和sprite sheet。 sprite sheet的概念很容易理解,但我很困惑如何将它集成到d3。基本上我想做的是选择我想要使用作为图像从sprite表格的精灵,然后使用d3来显示这个选定的精灵在页面上的其他地方,很可能是同一精灵的多个副本。 p>

实际的sprite表格(参见下面的免责声明):



这里有一些问题:
1)我将sprite表添加到我的html,硬编码< c $ c>< clipPath> 现在,这显示了我想要的特定sprite,然而,sprite的尺寸/定位就好像显示整个sprite。我如何只捕获精灵本身,而不只是隐藏未使用的?在下面的图片中,我想在d3鼠标悬停事件(第2部分)中使用单个图标。



修改此示例:



HTML

 < svg id =mySvgwidth = 550height =420> 
< defs id =mdef>
< pattern id =imagex =0y =0height =550width =420>
< image transform =scale(1.0)x =0y =0width =550height =420xlink:href =static / img / iconSheet.png> < / image>
< / pattern>
< / defs>
< / svg>

Javascript:

 code> var svgContainer = d3.select(div#content-main)append(svg)
.attr(width,740)
.attr ,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对象,我只需要添加东西。



免责声明:图标不是我的工作!我使用这些图标仅用于教育目的。作者的链接位于此处:健身图标


解决方案

我不知道< pattern> ,但是你的< image> 元素的问题是你不是翻译图像,所以你想要的图标在(0,0)点的SVG。



这是你需要的:

 < svg id =mySvg1width =100%height =100%viewBox =0 0 150 150> 
< defs>
< clipPath id =c>
< rect x =135y =0width =150height =150/>
< / clipPath>
< / defs>
< image transform =translate(-135,0)width =550height =420
xlink:href =static / img / iconSheet.pngclip-path = url(#c)/>
< svg>

当然,如果你要制作很多图标并使用它们多个地方,将建议:


  1. 定义< defs> 元素中的图标,然后在需要时使用< use> 元素引用它们;

  2. 使用< code>元素来定位每个图标中的图片,因此您只需要定义图片的网址,高度和宽度一次;

  3. 在一个< g> 元素,并应用剪切路径,以便您只需定义剪切路径一次(假设所有图标的大小相同)。

示例: http://codepen.io / AmeliaBR / pen / mwzBD



定义图标的键码:

 < svg class =icon-defs> 
< defs>
<! - 图标是在SVG< defs>元件;
它可能在一个不同的文件,
,因为图标将被url引用。 - >

<! - 一个剪切路径定义图标大小 - >
< clipPath id =icon-cp>
< rect x =0y =0width =150height =100/>
< / clipPath>

<! - 一个图像元素导入文件 - >
< image id =icon-spritewidth =969height =293
xlink:href =http://i.stack.imgur.com/TPx5h.png/ >

<! - 每个图标片段使用相同的图像
具有不同的翻译 - >
< g id =icon1clip-path =url(#icon-cp)>
< use xlink:href =#icon-sprite
transform =translate(0,0)/>
< / g>
< g id =icon2clip-path =url(#icon-cp)>
< use xlink:href =#icon-sprite
transform =translate(-240,0)/>
< / g>
< g id =icon3clip-path =url(#icon-cp)>
< use xlink:href =#icon-sprite
transform =translate(-240,-193)/>
< / g>
< / defs>

然后你引用这样的图标:

 < svg class =iconviewBox =0 0 150 100height =4emwidth =6em> 
< use xlink:href =#icon3/>
< / svg>

viewBox 属性设置布局图像和每次使用图标时都是一样的;高度和宽度可以是任何你想要的(虽然缩小当然会看起来比放大更好)。如果高度/宽度比不匹配图标,它将被压扁或拉伸,但你可以防止与 preserveAspectRatio 属性。



现在,到d3。它可能最容易定义SVG片段,提前表示图标,可能在一个单独的文件,虽然你可以动态构造DOM。当你真的要插入一个图标时,你



例如,要在每个元素的末尾添加一个带有warning的内联图标图像,像这样:

  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,你可能有一些数据变量告诉你要使用的图标,而不是类,但你得到的想法。


Need to apologize in advance: for length and for my ignorance. I'm trying to teach myself new concepts: d3.js and sprite sheets. The sprite sheet concept is simple to understand, but I'm confused how to integrate this into d3. Basically what I want to do is to select the sprite that I want to use as an image from the sprite sheet and then use d3 to display this selected sprite somewhere else on the page, and most likely multiple copies of the same sprite.

The actual sprite sheet for reference (see disclaimer below):

Here are the issues: 1) I add the sprite sheet to my html, hard code the <clipPath> for now, this displays the particular sprite I want, however, the dimensions/positioning of the sprite is just as though the entire sprite sheet is displayed. How can I only "capture" the sprite itself, not just hide the unused ones? In the image below, I want to use a single "icon" in a d3 mouseover event (part 2).

Modifying this example: 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>

Result

2) I can use <pattern> to determine an image to show in a d3 object/event. Like show a graphic in a rectangle. But this doesn't seem to work for large images (sprite sheets)? It becomes weird and blurry if I try to use the sprite sheet itself and its native dimensions in the pattern. If we solve part 1 we can probably ignore part 2, but this would be good to understand for general knowledge/future use.

Modifying this example: 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");
         });

Result

3) IF there is a more efficient way to accomplish this I am open to suggestion. I'm simply sticking with the d3 model because I've already rendered an svg object and I just need to add things to it.

DISCLAIMER: The icons are not my work! I am using these icons for educational purposes only. The author's link is here: Fitness Icons

解决方案

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.

这篇关于svg + Sprite sheet + d3 + clipPath + position + size的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆