如何使用多边形掩盖SVG的背景?

时间:2016-02-17 21:10:22

标签: svg

我正在尝试用渐变背景颜色从红色到黄色到绿色制作一个SVG,在SVG里面我有2个多边形(现在因为那里会更多)我希望会掩盖SVG的背景。我尝试了以下代码:

<svg height="500" width="500">
    <defs>
    <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
    <stop offset="0%" style="stop-color:rgb(34,177,76);stop-opacity:1" />
    <stop offset="50%" style="stop-color:rgb(255,242,0);stop-opacity:1" />
    <stop offset="100%" style="stop-color:rgb(237,28,36);stop-opacity:1" />
    </linearGradient>
    </defs>

    <polygon points="0, 0, 100, 0, 100, 100, 0, 100" fill="url(#grad1)">
    <polygon points="100, 100, 150, 250, 300, 350, 150, 400, 100, 300" fill="url(#grad1)" >
    </svg>

如何将背景应用于SVG并让多边形根据其位置显示背景的一部分?

enter image description here

更新

我更新了我的代码(是的,它需要一些工作),以获得具有统一背景的路径,并且还有透明多边形,以防您希望添加onclick事件。

<?php
//Array with the different sections and their coordinates
        $body['item1'] = array(array(0, 0), array(100, 0), array(100, 100), array(0, 100));
        $body['item2'] = array(array(100, 100), array(150, 250), array(300, 350), array(150, 300), array(100, 300));
        $body['item3'] = array(array(300, 50), array(300, 350), array(200, 350), array(200, 50));
        ?>
        <svg x="0px" y="0px" height="500px" width="500px">
        <defs>
        <linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
        <stop offset="0" style="stop-color:rgb(34,177,76);" />
        <stop offset="50%" style="stop-color:rgb(255,242,0);" />
        <stop offset="100%" style="stop-color:rgb(237,28,36);" />
        </linearGradient>
        </defs>

        <g id="singlePath_correctGradient" fill="url(#gradient)">
        <?php
        $polygon = '';
        echo '<path d="';
        foreach ($body as $key => $values) {
            $polygon .= '<polygon points="';
            $a = 1;

            foreach ($values as $coord) {
                echo $a == 1 ? ' M ' . $coord[0] . ', ' . $coord[1] : '';
                echo $a == 2 ? ' L ' . $coord[0] . ', ' . $coord[1] : '';
                echo $a > 2 ? ', ' . $coord[0] . ', ' . $coord[1] : '';

                $polygon .= ($a == 1 ? '' : ', ') . $coord[0] . ', ' . $coord[1];
                $a++;
            }
            $polygon .= '" onclick="alert(\'' . $key . '\')" fill-opacity="0"/>';
        }
        echo '"></path>';

        echo $polygon;
        ?>
        </g>
        </svg>

2 个答案:

答案 0 :(得分:1)

Change your gradientUnits to "userSpaceOnUse" - that way the gradient is defined in the SVG box space, not the filled unit. Easy. (and please, close your elements!! - SVG is XML)

<svg x="0px" y="0px" height="500px" width="500px" viewBox="0 0 500 500">
    <defs>
    <linearGradient id="grad1" x1="0" y1="0" x2="300" y2="350" gradientUnits="userSpaceOnUse">
    <stop offset="0" style="stop-color:rgb(34,177,76);" />
    <stop offset="50%" style="stop-color:rgb(255,242,0);" />
    <stop offset="100%" style="stop-color:rgb(237,28,36);" />
    </linearGradient>
    </defs>

    <polygon points="0, 0, 100, 0, 100, 100, 0, 100" fill="url(#grad1)"/>
    <polygon points="100, 100, 150, 250, 300, 350, 150, 400, 100, 300" fill="url(#grad1)" />
    </svg>

答案 1 :(得分:0)

更新:我现在在下面显示两个代码段。第一个(原始)代码段显示了手动解决方案。第二个(较新的)代码段显示了使用JavaScript的编程解决方案。

将多边形转换为路径是否正常?如果是这样,您可以将多个多边形组合成一个路径,然后将渐变应用于整个事物。在下面的第一个代码段中,我展示了三个组:

  1. 您原来的两个多边形......不正确的渐变
  2. 两个多边形转换为两个路径......仍然是错误的渐变
  3. 两条路径合并为一条路径......正确渐变
  4. 基本上,要将多边形转换为路径,请将points属性更改为d属性。然后,在d值字符串中,在开头放置一个M(用于“MoveTo”),在前两个数字后放置一个L(用于“LineTo”)。在路径中间放置一个M就可以告诉程序“抬起笔,无需绘制任何东西,将其移动到这个新位置并继续绘制”,有效地允许您绘制多个“形状”一条路。

    <svg height="500" width="500">
      <defs>
        <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%" style="stop-color:rgb(34,177,76);stop-opacity:1" />
          <stop offset="50%" style="stop-color:rgb(255,242,0);stop-opacity:1" />
          <stop offset="100%" style="stop-color:rgb(237,28,36);stop-opacity:1" />
        </linearGradient>
      </defs>
    
      <g id="twoPolygons_incorrectGradient" fill="url(#grad1)" transform="scale(0.5) translate(0,0)">
        <polygon points="0, 0 100, 0, 100, 100, 0, 100"></polygon>
        <polygon points="100, 100 150, 250, 300, 350, 150, 400, 100, 300"></polygon>
      </g>
      <g id="twoPaths_incorrectGradient" fill="url(#grad1)" transform="scale(0.5) translate(300,0)">
        <path d="M 0, 0 L 100, 0, 100, 100, 0, 100"></path>
        <path d="M 100, 100 L 150, 250, 300, 350, 150, 400, 100, 300"></path>
      </g>
      <g id="singlePath_correctGradient" fill="url(#grad1)" transform="scale(0.5) translate(600,0)">
        <path d="M 0, 0 L 100, 0, 100, 100, 0, 100 
                 M 100, 100 L 150, 250, 300, 350, 150, 400, 100, 300"></path>
      </g>
      <g>
        <text   x="0" y="70">wrong</text>
        <text x="150" y="70">wrong</text>
        <text x="300" y="70">right</text>
      </g>
    </svg>

    我已手动完成上述转换。但是,这种类型的转换也可以通过编程方式完成,例如,使用JavaScript,我在下面的第二个片段中完成了。基本上,这会做到以下几点:

    • 获取所有想要的多边形
    • 对于每个多边形,请阅读points属性值字符串
    • 复制最终点(以数字方式关闭每个形状......对笔划/边框很重要)
    • 如上所述插入“M”(MoveTo)和“L”(LineTo)
    • 连接所有这些字符串
    • 添加最后的“Z”(ClosePath)以关闭路径
    • 创建新的单一路径元素
    • 将上面的连接字符串放入路径的d属性
    • 将渐变应用于新路径

    下面的示例最初显示了7个多边形,其中相同的渐变应用于每个单独的形状。请注意,最后一个多边形只是一个点,因此是不可见的,用虚线圆圈表示。

    单击“组合...”按钮后,多边形2和3将合并为一条路径,多边形4和5以及多边形6和7也会合并。现在将相同的渐变应用于每个组合路径。请注意路径组合如何影响渐变颜色的位置。

    请注意,我编写的实用程序函数就像向数组中添加更多的多边形ID一样简单,以便将两个以上的多边形组合在一起。

    var xmlns = "http://www.w3.org/2000/svg";
    
    var combine = function(polygonIds, newPathId) {
      var $newPath = $(document.createElementNS(xmlns, "path"));
      // jQuery does not work here, e.g. var $newPath = $("<path>", {id: newPathId});
      $newPath.attr("id", newPathId);
      $("svg").append($newPath);
      var dStr = "";
      polygonIds.forEach(function(polygonId, idx, arr) {
        var $polygon = $("#" + polygonId);
        var ptsStr = $polygon.attr("points");
        dStr += "M " + ptsStr.replace(/, *| +/g, " ").trim().replace(/^([^ ]+ [^ ]+ )(.*)/, "$1L $2 $1");
      });
      dStr += "Z";
      $newPath.attr("d", dStr);
    };
    
    $("button#combine").click(function() {
      combine(["shape2", "shape3"], "path2and3");
      combine(["shape4", "shape5"], "path4and5");
      combine(["shape6", "shape7"], "path6and7");
      $("#path2and3").attr("fill", "url(#grad1)");
      $("#path4and5").attr("fill", "url(#grad1)");
      $("#path6and7").attr("fill", "url(#grad1)");
      $("#labels").remove().appendTo($("svg"));
    });
    $("button#delete").click(function() {
      $("path").remove();
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <p>Best viewed on "Full Page"</p>
    <p>The "Combine..." button will combine polygons 2 and 3, polygons 4 and 5, and polygons 6 and 7. Polygon 7 is a single dot and is thus essentially invisible. The same gradient is applied to each individual polygon as well as to each of the new paths.</p>
    <div>
      <button id="combine">Combine polygons into paths</button>
      <button id="delete" >Delete new paths           </button>
    </div>
    <svg height="500" width="500">
      <defs>
        <linearGradient id="grad1" x1="0%" y1="0%" x2="0%" y2="100%">
          <stop offset="0%"   style="stop-color:rgb(34,177,76);stop-opacity:1" />
          <stop offset="50%"  style="stop-color:rgb(255,242,0);stop-opacity:1" />
          <stop offset="100%" style="stop-color:rgb(237,28,36);stop-opacity:1" />
        </linearGradient>
      </defs>
    
      <g fill="url(#grad1)" transform="scale(1) translate(0,0)">
        <polygon id="shape1" points=" 30, 100   60, 160   30, 220    0, 160"></polygon>
        <polygon id="shape2" points="100,   0  120,   0  110, 120"          ></polygon>
        <polygon id="shape3" points="130, 100  160, 160  130, 220  100, 160"></polygon>
        <polygon id="shape4" points="230, 100  260, 160  230, 220  200, 160"></polygon>
        <polygon id="shape5" points="210, 200  220, 320  200, 320"          ></polygon>
        <polygon id="shape6" points="330, 100  360, 160  330, 220  300, 160"></polygon>
        <polygon id="shape7" points="330, 320"                              ></polygon>
      </g>
      <circle cx="330" cy="320" r="10" fill="none" stroke="black" stroke-dasharray="3 3"></circle>
      <g id="labels" font-family="Verdana" font-size="18">
        <text x=" 24" y="165">1</text>
        <text x="104" y=" 20">2</text>
        <text x="124" y="165">3</text>
        <text x="224" y="165">4</text>
        <text x="204" y="310">5</text>
        <text x="324" y="165">6</text>
        <text x="324" y="305">7</text>
      </g>
      
    </svg>