是否可以在 SVG 中线性渐变填充分组路径(通过 jQuery 事件上的 css 或 attr)

发布于 2024-10-27 02:26:38 字数 2041 浏览 6 评论 0原文

如何在 SVG 图像中填充 的一个渐变,而不是填充所选 中的所有

在本例中,我想展示非洲,仅填充从黄色到红色的一种渐变,但由于存在子组,填充会产生许多渐变。

javascript:

<script type="text/javascript">
function svgOver() { 
    var what = $(this).attr("id");
    $("#world #"+what, svg.root()).attr("fill", "url(#red_black)"); 
} 
function svgOut() { 
    $(this).attr("fill", "");
}

...

$("#map").svg({ 
    loadURL: 'http://teszt.privilegetours.hu/skins/privilege/svg/worldmap.svg',
        onLoad: function(svg) { 
        $("#world > g", svg.root()).bind('mouseover', svgOver).bind('mouseout', svgOut).bind('click', svgZoom);
        },
    settings: {}
});

SVG:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" mlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="570px" height="300px" viewBox="146.605 71.42 570 300" enable-background="new 146.605 71.42 570 300" xml:space="preserve">

<defs>
    <linearGradient id="red_black" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
    </linearGradient>
</defs>

<g id="world" transform="scale(1)" fill="#AAAAAA" stroke="#FFFFFF" stroke-width="0.1">
    <g id="africa" name="africa"> // < i want to fill this
        <g id="er" transform="translate(-29.9017, -45.0745)"> // < instead of theese
            <path d="..."/>
        </g>
        <g id="yt"> // < instead of theese
            <path d="..."/>
        </g> 
        ...

this is the africa

我该如何解决此问题?
如何在不向原始图像添加另一个 标签的情况下解决此问题?

How can i fill one gradient for a <g> in an SVG image instead of fill all the <g>s in the selected <g>?

In this case, I'd like to show africa, filled with just one gradient from yellow to red, but because of the sub-groups the fill makes many of gradients.

The javascript:

<script type="text/javascript">
function svgOver() { 
    var what = $(this).attr("id");
    $("#world #"+what, svg.root()).attr("fill", "url(#red_black)"); 
} 
function svgOut() { 
    $(this).attr("fill", "");
}

...

$("#map").svg({ 
    loadURL: 'http://teszt.privilegetours.hu/skins/privilege/svg/worldmap.svg',
        onLoad: function(svg) { 
        $("#world > g", svg.root()).bind('mouseover', svgOver).bind('mouseout', svgOut).bind('click', svgZoom);
        },
    settings: {}
});

The SVG:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" mlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="570px" height="300px" viewBox="146.605 71.42 570 300" enable-background="new 146.605 71.42 570 300" xml:space="preserve">

<defs>
    <linearGradient id="red_black" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
    </linearGradient>
</defs>

<g id="world" transform="scale(1)" fill="#AAAAAA" stroke="#FFFFFF" stroke-width="0.1">
    <g id="africa" name="africa"> // < i want to fill this
        <g id="er" transform="translate(-29.9017, -45.0745)"> // < instead of theese
            <path d="..."/>
        </g>
        <g id="yt"> // < instead of theese
            <path d="..."/>
        </g> 
        ...

this is the africa

How can I fix this problem?
How can I fix this problem without adding an another <g> tag to the original image?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

不寐倦长更 2024-11-03 02:26:38

您的问题可以通过将渐变坐标系设置为用户空间(而不是默认的对象边界框)来解决。

您可以尝试

<defs>
    <linearGradient id="red_black" x1="0%" y1="0%" x2="0%" y2="100%" gradientUnits="userSpaceOnUse">
        <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
    </linearGradient>
</defs>

该解决方案不会违背 e.nelson 的评论 - 这里发生的情况是,代表国家的每个子组仍然应用其单独的渐变实例,而所有这些实例共享相同的坐标原点和用户空间的相同转换 -因此,在最终渲染的任何时刻,哪个渐变实例可见并不重要。

需要进行两项调整:

  1. [ 次要]
    您必须调整渐变定义的 y1/y2 偏移(或停止偏移) - 因为它们指的是整个地图的用户坐标空间,非洲仅覆盖定义的停止之间的梯度的一部分。尝试 y1="50%"y2="100%"

  2. [中]
    如果您查看了定义国家/地区形状的 svg g-elements,您会注意到其中一些需要进行额外的转换。它们有效地改变了用户坐标系,因此也适用于导致受影响的国家/地区形状在地图上看起来像斑点的渐变。
    这个 spios 变换可能是用于创建地图的生成器中的动作的产物。
    可以通过将平移偏移添加到相应 g 元素内路径元素中的每个绝对坐标来补救。由于这些路径是使用缝合在一起的片段的相对坐标来定义的,因此这减少了更改路径 d 属性中初始“M”和最终“C”命令的坐标。

我编写了一个临时 Perl 脚本来标准化表示实现上述修改的国家边界的 svg 代码的结构。请注意,这些更改也可以在 js 中相当方便地完成。 这就是结果

希望对您有所帮助,如果您需要有关如何执行上述调整的更多信息,请给我留言。

附:
我刚刚注意到生成的输出中仍然缺少莫桑比克 - 对于该国家的形状,还指定了另一个翻译。这个小细节将在今天晚些时候添加,但是...

结果

your problem can be solved by setting the gradients coordinate system to user space (instead of the default object-bounding box).

you might try

<defs>
    <linearGradient id="red_black" x1="0%" y1="0%" x2="0%" y2="100%" gradientUnits="userSpaceOnUse">
        <stop offset="0%" style="stop-color:rgb(255,0,0);stop-opacity:1"/>
        <stop offset="100%" style="stop-color:rgb(255,255,0);stop-opacity:1"/>
    </linearGradient>
</defs>

the solution does not defy the comment by e.nelson - what happens here is that each subgroup representing the nations still has its individual gradient instance applied while all these instances share the same coord origin and the same transformations w.r.t the user space - so at any point in the final rendering, it doesn't matter which gradient instance is visible.

two adjustments are required:

  1. [ minor]
    you have to adjust the y1/y2 offsets (or the stop offsets) of the gradient definition - as they refer to the user coord space of the whole map, africa only covers a portion of the gradient between the stops defined. try y1="50%" and y2="100%".

  2. [medium]
    if you have a look at svg g-elements defining the country shapes you'll note that some of them are subjected to an additional translation. they effectively shift the user coordinate system and therefore also apply to the gradient which causes the affected country shapes to appear like blotches on the map.
    this spurios transform is probably an artefact of the actions in the generator used to create the map.
    it can be remedied by adding the translation offsets to each absolute coordinate in the path elements inside the respective g-elements. as these paths are defined using relative coordinates for the pieces stitched together, this reduces to altering the coords of the initial 'M' and final 'C' commands in the path's d-attribute.

i have cooked up an ad hoc perl script to normalize the structure of the svg code representing the country borders that implements the abovementioned modifications. note that these alterations can be done rather conveniently in js too. This is the result.

hope that helps and drop me a note if you need additional informations on how to perform the adjustments mentioned.

PS:
i just noticed that mozambique is still missing from the generated output - for that single country's shape yet another translation has been specified. this minor detail is something to be added later today, however ...

result

榆西 2024-11-03 02:26:38

“然而,绘画总是在每个图形元素上单独完成,而不是在容器元素(例如“g”)级别上完成。因此,对于以下 SVG,即使在“g”上指定了渐变填充,渐变只是通过“g”元素继承到每个矩形,每个矩形都被渲染,使其内部用渐变绘制。”

http://www.w3.org/TR/SVGTiny12/painting.html#InheritanceOfPaintingProperties

根据规范,您所要求的是不可能的。如果有要求,您可以探索以下方法之一:让 SVG 创建者为您添加鼠标悬停路径;组合服务器上代码中的路径(可能很棘手);选择纯色而不是渐变,这样问题就不那么明显了。

"Painting, however, is always done on each graphics element individually, never at the container element (e.g., a 'g') level. Thus, for the following SVG, even though the gradient fill is specified on the 'g', the gradient is simply inherited through the 'g' element down into each rectangle, each of which is rendered such that its interior is painted with the gradient."

http://www.w3.org/TR/SVGTiny12/painting.html#InheritanceOfPaintingProperties

What you're asking for isn't possible, according to the spec. If it's a requirement, you could explore one of: having the SVG creator add mouse over paths for you; combine the paths in code on the server (potentially tricky); choose a solid color instead of a gradient so the problem isn't so obvious.

醉酒的小男人 2024-11-03 02:26:38

如果您想用一个渐变填充整个非洲,那么您需要合并该填充的路径。也许你应该使用不同的地图?一个只有大陆的地方?

无论如何,解决此问题的一种方法是:

  1. 在 Inkscape 中打开它,
  2. 选择要填充的所有路径,
  3. 从“路径”菜单中选择“联合”,
  4. 保存文件(或复制并粘贴联合路径)

另一种方法:

  1. 查看对于其他地图,请参阅 http://d-maps.com/http://commons.wikimedia.org。这是仅限大陆,标记为非洲

完成此操作后,您可以将渐变应用到该新路径。

您还可以通过其他一些方式来完成此操作,但出于性能原因,它们可能不太好。其中一种(不推荐)方法是用渐变填充矩形,其中您已在其中创建了由组中的路径组成的剪辑路径。沿着这些思路:

<clipPath id="clip">
  <use xlink:href="#africa"/>
</clipPath>
<rect width="100" height="100" fill="url(#grad)" clip-path="url(#clip)"/>
<g id="africa">...</g>

If you want to fill all of Africa with one gradient, then you want the union the paths for that fill. Maybe you should use a different map? One with only the continents?

Anyway one way to fix it would be to:

  1. open it up in Inkscape
  2. select all the paths that you want to fill
  3. choose "Union" from the "Path" menu
  4. save the file (or copy&paste the unioned path)

Another way:

  1. Look for another map, see http://d-maps.com/ or http://commons.wikimedia.org. Here's one with the continents only, africa marked.

After doing that you can apply the gradient to that new path.

You could also do it in some other ways, but they're probably not as good for performance reasons. One of those (not recommended) ways would be to fill a rectangle with the gradient where you've made a clip-path consisting of the paths in the group. Something along these lines:

<clipPath id="clip">
  <use xlink:href="#africa"/>
</clipPath>
<rect width="100" height="100" fill="url(#grad)" clip-path="url(#clip)"/>
<g id="africa">...</g>
¢好甜 2024-11-03 02:26:38

我认为你的问题可能是 fill 继承,根据SVG 中 CSS 的标准规则。因此,您需要在子 g 元素上设置显式的 fill 透明。如果不是这样,我会在您获得在线示例后回来再看一下。

I think your problem might be that fill is inherited according to the standard rules of CSS in SVG. So you'd need to set an explicit fill of transparent on the child g elements. If it's not that I'll come back and have another look after you've got an online example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文