最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the best approach for overlapping SVG elements area fill? - Stack Overflow

programmeradmin2浏览0评论

I am studying some basic image manipulations with SVG and trying to find optimal approach for the following challenge:

We have one SVG file which has various SVG elements (circles, rectangle, triangle). They all are overlapping each other creating new "areas" of different forms (see pic).

So filling actual Elements - no problem there. But what if I want to fill with color only specific intersect area?

My current thinking was:

  • Consider drawing all elements as Paths, then see if I can treat overall position as One large path and then play with fill-rule.
  • Consider calculating the area shape and drawing a new shape on top of it, then fill it.
  • Consider something else?

I am studying some basic image manipulations with SVG and trying to find optimal approach for the following challenge:

We have one SVG file which has various SVG elements (circles, rectangle, triangle). They all are overlapping each other creating new "areas" of different forms (see pic).

So filling actual Elements - no problem there. But what if I want to fill with color only specific intersect area?

My current thinking was:

  • Consider drawing all elements as Paths, then see if I can treat overall position as One large path and then play with fill-rule.
  • Consider calculating the area shape and drawing a new shape on top of it, then fill it.
  • Consider something else?
Share Improve this question edited Feb 28, 2020 at 13:42 trixn 16.3k2 gold badges39 silver badges59 bronze badges asked Aug 3, 2016 at 19:05 Sergey RudenkoSergey Rudenko 9,2353 gold badges30 silver badges51 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 10

Michael's filter method is cool and tricky, but perhaps a little hard to understand.

You can also do it with masks.

<svg width="391" height="400">
  <defs>
    <!-- define the shapes in the image, which we will use for the outlines
         and for creating intersection masks -->
    <rect id="square" x="92" y="48" width="218" height="218"/>
    <polygon id="triangle" points="54,366 277,366 165,142"/>
    <circle id="circle" cx="256" cy="264" r="85"/>
    
    <!-- the masks -->
    <!-- white parts are visible, black parts are invisible -->
    <mask id="square-minus-triangle">
      <!-- square with triangle cut out of it -->
      <use xlink:href="#square" fill="white"/>
      <use xlink:href="#triangle" fill="black"/>
    </mask>
    <mask id="triangle-minus-square">
      <!-- triangle with square cut out of it -->
      <use xlink:href="#triangle" fill="white"/>
      <use xlink:href="#square" fill="black"/>
    </mask>
  </defs>
  
  <!-- background -->
  <rect width="100%" height="100%" fill="#e5e4da"/>
  
  <!-- the intersection shapes (yellow) -->
  <!-- first draw the circle, but use the square-minus-triangle mask.-->
  <use xlink:href="#circle" fill="#e4e400" mask="url(#square-minus-triangle)"/>
  <!-- draw the circle again, but use the triangle-minus-square mask.-->
  <use xlink:href="#circle" fill="#e4e400" mask="url(#triangle-minus-square)"/>
  
  <!-- draw the outlined shapes -->
  <g fill="none" stroke="black" stroke-width="6">
    <use xlink:href="#square"/>
    <use xlink:href="#triangle"/>
    <use xlink:href="#circle"/>
  </g>
</svg>

You can do this with filters. An easy way to do is to use near transparent fill and then use a filter to dial the non-overlapping areas to fully transparent and the overlapping areas to fully opaque. It makes the stroke a little crispy though.

<svg height="600px" width="800px">
     <defs>
       <filter id="opacitychange">
         <feComponentTransfer>
           <feFuncA type="linear" intercept="-.05"/>
           </feComponentTransfer>
         <feComponentTransfer>
           <feFuncA type="gamma" amplitude="4" exponent=".4"/>
           </feComponentTransfer>
         </filter>
       </defs>
  
  <g filter="url(#opacitychange)">
     <circle stroke="black"  fill="blue" fill-opacity="0.05" cx="150" cy="150" r="100"/>
     <rect stroke="black" x="200" y="100" width="100" height="300" fill="blue" fill-opacity="0.05"/>
     <polygon stroke="black"  points="50,50 50,400 300,400" fill="blue" fill-opacity="0.05"/>
 </g>    
     </svg>

发布评论

评论列表(0)

  1. 暂无评论