16

<g>如何在 SVG 图像中为 a 填充一个渐变,而不是填充<g>所选中的所有 s <g>

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

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

这是非洲

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

4

4 回答 4

42

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

你可以试试

<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 元素,您会注意到其中一些需要额外的翻译。它们有效地改变了用户坐标系,因此也适用于导致受影响国家形状在地图上看起来像斑点的渐变。这种 spurios 变换可能是用于创建地图的生成器中的操作的人工制品。可以通过将平移偏移量添加到相应 g 元素内的路径元素中的每个绝对坐标来解决此问题。由于这些路径是使用拼接在一起的片段的相对坐标定义的,因此这减少了更改路径 d 属性中初始“M”和最终“C”命令的坐标。

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

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

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

结果

于 2011-04-02T09:29:57.480 回答
2

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

无论如何,解决它的一种方法是:

  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>
于 2011-03-30T16:11:24.847 回答
2

“然而,绘画总是在每个图形元素上单独完成,而不是在容器元素(例如,'g')级别。因此,对于下面的 SVG,即使在 'g' 上指定了渐变填充,渐变简单地通过'g'元素向下继承到每个矩形中,每个矩形都经过渲染,使其内部涂有渐变。”

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

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

于 2011-03-30T14:38:44.787 回答
0

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

于 2011-03-30T14:04:03.517 回答