SVG填充不填充边界

时间:2013-03-26 07:17:04

标签: svg

查看以下SVG文件:

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<polygon points="10,10 10,390 390,390 10,10" style="fill:rgb(140,90,90)" />
<polygon points="10,10 390,390 390,10 10,10" style="fill:rgb(90,140,90)" />
</svg>

如果你试试这个,这两个三角形有一个薄的灰色区域,将它们分开。我想摆脱这些,因为我有数百个小三角形,然后分离线作为区域上的网格可见,应该被三角形覆盖。我注意到,Mathematica的SVG导出确实存在这个问题。

我试图用相同颜色和宽度1的笔划填充轮廓。但是,三角形溢出。因此,外观取决于绘制三角形的顺序。

是否有任何干净的解决方案或至少是对此问题的改进?

3 个答案:

答案 0 :(得分:1)

您看到的似乎是将矢量图形映射到位图设备的工件。为了补偿它,轻微扰动所涉及的三角形之一,其数量少于1个单位。

示例(代码见下文):通过沿x轴移动0.2个单位来平移紫色多边形。

请注意,结果的质量 - 除了明显的因素 - 将取决于缩放系数。在给定的例子中,我可以看到分离线在chrome 25中以> = 150%的缩放级别消失。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<polygon points="10.2,10   10.2,390 390.2,390 10.2,10" style="fill:rgb(140,90,90)" />
<polygon points="  10,10    390,390   390,10    10,10" style="fill:rgb(90,140,90)" />
</svg>

另一种选择可能是将一些三角形改为五边形,一个相邻的梯形区域覆盖三角形之间的分隔线(见下面的代码),该区域适用于缩放因子&gt; 67%。是否对三角形及其在平面中的方向有任何限制(如直角,正交格上的边)?

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
<polygon points="10,10  10,390  390,390 390,389.6 10.4,10 10,10" style="fill:rgb(140,90,90)" />
<polygon points="10,10      390,390 390,10  10,10"               style="fill:rgb(90,140,90)" />
</svg>

答案 1 :(得分:1)

这是使用光栅化策略的结果,并没有简单的解决方法。

一个解决方法是划动三角形,但行程非常非常薄。例如,这是一个行程为0.2px的行程:

演示:http://jsfiddle.net/Qw2HL/

或者,您可以将图形加倍并在实际内容下面渲染描边版本。

演示:http://jsfiddle.net/Qw2HL/1/

<g id="underlay">
  <polygon class="t1" points="10,10 10,390 390,390 10,10" />
  <polygon class="t2" points="10,10 390,390 390,10 10,10" />
</g><g id="content">
  <polygon class="t1" points="10,10 10,390 390,390 10,10" />
  <polygon class="t2" points="10,10 390,390 390,10 10,10" />
</g>
.t1 { fill:rgb(140,90,90); stroke:rgb(140,90,90) }
.t2 { fill:rgb(90,140,90); stroke:rgb(90,140,90) }
#underlay polygon { stroke-width:1px }
#content  polygon { stroke:none      }

(如果您在用户代理(如可用的Web浏览器)中运行,则可以通过JS自动执行此操作。)


此演示非常清楚地显示了问题。

问题:http://jsfiddle.net/tbCxT/

<svg xmlns="http://www.w3.org/2000/svg">
  <g id="aligned">
    <polygon class="a" points="10,10 10,100 100,100, 100,10" />
    <polygon class="b" points="100,10 100,100 200,100, 200,10" />
  </g>
  <g id="shifted" transform="translate(0.5,110)">
    <polygon class="a" points="10,10 10,100 100,100, 100,10" />
    <polygon class="b" points="100,10 100,100 200,100, 200,10" />
  </g>
</svg>

这里我们有两个垂直边缘正好在彼此的顶部。在第一种情况下,它们在像素网格上精确对齐。左侧形状精确填充左侧的所有像素,右侧形状精确填充右侧的所有像素,并且不填充间隙。

然而,在第二种情况下,两种形状都落在像素边界之间。由于我们的形状与这些像素重叠了50%,因此抗锯齿在这种情况下告诉我们应该填充我们重叠50%不透明度的像素。因此左侧形状填充此共享像素列50%不透明,然后右侧形状填充共享列,其中像素为50%不透明度。

不幸的是,不透明度通过乘法而不是加法来构建。 rgba(0,0,0,0.5)上方的rgba(0,0,0,0.5)像素生成rgba(0,0,0,0.75),而不是rgba(0,0,0,1)

这是问题的症结所在,并不是SVG所特有的。例如,请参阅:

当您将无限精确的矢量图像采样到有限像素网格时,信息会丢失。你需要破解它来解决它。

答案 2 :(得分:1)

我在共享边缘的多边形之间存在相同的空间问题。这是两个共享一条边的三角形,具有各种不透明度:

http://jsfiddle.net/YfH9N/embedded/result/

...当多边形具有更高的不透明度时,空间更明显。正如在其他答案中所建议的那样,向多边形添加描边轮廓会有所帮助,但是笔划的正确宽度取决于多边形的不透明度。

使用恒定的1px笔画宽度:

http://jsfiddle.net/LKQHf/embedded/result/

使用笔划宽度= polygon_alpha ^ 6:

http://jsfiddle.net/ekwk3/2/embedded/result/

...我只是凭经验使用这个Perl脚本找到了笔画宽度的等式,所以你可以自己试试:

#!/usr/bin/perl

print "<?xml version=\"1.0\" standalone=\"no\"?>
<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">
<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1100\" height=\"100\">
";

for (my $alpha = 0; $alpha<=1; $alpha+=0.025) {
    my $alpha_str = sprintf("%.3f", $alpha);
    my $alpha_stroke = 1;#$alpha ** 6;
    my $alpha_stroke_str = sprintf("%.3f", $alpha_stroke);
    my $stroke_width = $alpha ** 6;
    my $stroke_width_str = sprintf("%.3fpx", $stroke_width);

    print "
    <g transform=\"translate(".($alpha*1000).",0)\">    
        <polygon points=\"20,10 25,49 6,40\" style=\"fill:rgb(255,100,0);fill-opacity:$alpha_str;stroke:rgb(255,100,0);stroke-width:$stroke_width_str;stroke-opacity:$alpha_stroke_str\" />
        <polygon points=\"20,10 25,49 40,4\" style=\"fill:rgb(255,100,0);fill-opacity:$alpha_str;stroke:rgb(255,100,0);stroke-width:$stroke_width_str;stroke-opacity:$alpha_stroke_str\" />
    </g>\n";
}

print "</svg>";
相关问题