2017-11-16 4 views
2

は、次のSVG画像のコードを考えてみましょう:私のSVGパスがChrome、Edge、Firefoxで突然クラッピングするのはなぜですか?

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"> 
    <title>Clipped Path Problem Demo</title> 
    <g id="group:image"> 
     <defs> 
      <mask id="mask"> 
       <rect id="rectangle:inset" x="250" y="134" width="500" height="732" fill="white"/> 
      </mask> 
     </defs> 
     <g id="group:curves" mask="url('#mask')"> 
      <!-- <rect id="rectangle:filler.shape" width="1" height="1" fill="transparent"/> --> 
      <path id="path:curves" d=" 
       M 441 327 
       c -85 88 -85 175 -85 175 
       c 0 88 85 175 85 175 
       s 90 103 90 103 
       c 85 88 85 175 85 175" fill="transparent" stroke="black" stroke-width="73"/> 
     </g> 
    </g> 
    <g id="group:guides"> 
     <rect id="rectangle:guide.area:inset" x="250" y="134" width="500" height="732" fill="transparent" stroke="black" stroke-dasharray="20 10" stroke-width="1"/> 
    </g> 
</svg> 

(CodePen:https://codepen.io/patrickdark/full/zPEVVg/(私は画面に収まるように、それはより多くの可能性を高めるためにペンにheight="500px"属性を追加しました)。)

を残しましたマスクが画像のその部分を含むのに必要な大きさを十分上回っていても、湾曲した経路の一側が垂直線にクリップされる。

マスクされたg要素に0以外の任意のサイズの図形を挿入すると(XMLコメント内の1×1の透過矩形など)、クリッピングされたエッジは魔法のようにクリップが解除されます。

これはChrome(62)、Edge(41)、Firefox Developer Edition(58 Beta 4)で起こっていること以外はバグだと思います。私が知りたいのはなぜこの一見無意味な切り抜きが起こっているのですか?

(注:湾曲経路の下部にクリッピングが意図的である)

答えて

2

マスクは色とアルファチャンネル値(潜在的に高価な演算)で動作するので、それは無限に伸ばすが、描画しませんマスクされた要素のオブジェクトバウンディングボックスと、すべての方向に10%(境界ボックス単位で属性x, y, width, heightで定義されます)でデフォルトでクリップされます。

オブジェクトの境界ボックスは、ストロークの幅を含まないように定義されていますが、これらの制限を超えており、少なくともマスクのxwidth属性に調整を加える必要があります。

これは直感的ではないように思われるので、マスクを適用するための一般的なアルゴリズムは、このように書きます:

  1. マスクが適用された領域を特定します。これは、常に<mask>要素のx, y, width, height属性によって与えられる長方形です。デフォルトの場合、maskUnits属性がobjectBoundingBoxと指定されている場合、その座標は、マスクが適用される要素のobject bounding boxによって決定されます。マスクの内容はであり、ではありません。その座標系における0と1は、マスクされた要素とそのすべての子孫の結合バウンディングボックスの最小値と最大値です。
  2. マスク要素の内容と、適用された要素を重ね合わせます。デフォルトでは、これらの要素を配置するために使用される座標系はmaskContentUnits="userSpaceOnUse"で与えられます。これは、マスクされた要素が描画されるのと同じ座標系を意味します。
  3. 上記で定義した領域内のすべての点について、マスクされたコンテンツの不透明度にマスクするコンテンツの輝度を掛けて、マスクされた要素の不透明度を計算します。
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"> 
     
        <title>Clipped Path Problem Resoved</title> 
     
        <g id="group:image"> 
     
         <defs> 
     
          <mask id="mask" x="-20%" width="140%"> 
     
           <rect id="rectangle:inset" x="250" y="134" width="500" height="732" fill="white"/> 
     
          </mask> 
     
         </defs> 
     
         <g id="group:curves"mask="url('#mask')"> 
     
          <!-- <rect id="rectangle:filler.shape" width="1" height="1" fill="transparent"/> --> 
     
          <path id="path:curves" d=" 
     
           M 441 327 
     
           c -85 88 -85 175 -85 175 
     
           c 0 88 85 175 85 175 
     
           s 90 103 90 103 
     
           c 85 88 85 175 85 175" fill="transparent" stroke="black" stroke-width="73"/> 
     
         </g> 
     
        </g> 
     
        <g id="group:guides"> 
     
         <rect id="rectangle:guide.area:inset" x="250" y="134" width="500" height="732" fill="transparent" stroke="black" stroke-dasharray="20 10" stroke-width="1"/> 
     
        </g> 
     
    </svg>
+0

感謝。したがって、パスの幅は260単位であり、マスクによってその塗りつぶしボックスのみが考慮されるという問題があります。既定の-10%マスクインセットでは、マスクは塗りつぶしボックスの外側に26単位を塗りますが、塗りつぶしボックスの外にあるストロークの36.5単位(50%)に対応するには不十分です。 -14.039%(0 - 36)のマスクインセットが必要です。5÷260)と128.078%(1 + 36.5÷260 * 2)の幅を持っています。 –

+0

フィラーの形状は、左上の座標を0,0に設定するときにオブジェクトの境界ボックスを変更するため、問題を解決します。これは、(マスクされたコンテンツとは対照的に)マスクの一部であり、マスクの外側の境界に位置していないストロークを収容するための唯一の戦略であるようである。 (マスクはその構成シェイプを反復して、それぞれ別々に-10%のインセットを適用するので、マスクの途中でクリッピングが発生する可能性があります...)ストロークがシンボルから作成された複合シェイプ上にある場合、明らかにシンボルの内側に配置する必要があります。直感的ではないことについて話してください。 –

+0

私はあなたのコメントを完全に理解しているかどうかはわかりませんが、誤解があるかもしれません。私は答えを広げた。 – ccprog

関連する問題