Svg屏蔽在生成时不会呈现

时间:2016-02-16 04:03:58

标签: svg elm image-masking virtual-dom

<svg x="0" y="0" height="2048" width="4096" style="position: absolute; top: 0px; left: 0px; pointer-events: none;">
   <defs>
      <mask x="0" y="0" id="shadowLayerMask">
         <polygon fill="#FFF" points="1042,1578 630,2048 3902,2048 3370,1464"></polygon>
      </mask>
   </defs>
   <rect x="0" y="0" fill="red" mask="url(#shadowLayerMask)" maskContentUnits="userSpaceOnUse" height="2048" width="4096"></rect>
</svg>

简单吧?这就是事情,如果我把这个svg放到一个html文件中,屏蔽效果就会很好。但是当我使用虚拟dom生成相同的svg时,掩码没有效果,我们只有一个巨大的红色矩形。

令人讨厌的是,如果我打开开发人员工具并向svg添加一个毫无意义的<defs></defs>,我可以在生成时显示它。这似乎以某种方式踢了svg并提醒它需要掩盖。

任何人都知道这里发生了什么?是否有一种解决方法并不涉及设置计时器以注入空defs

更新

这是源

render : Layer -> Html
render { key, shader, mask, size } =
  let
    key' =
      key ++ "LayerMask"

    style' =
      [ "position" => "absolute"
      , "top" => "0px"
      , "left" => "0px"
      , "pointer-events" => "none"
      ]

    hw =
      [ A.height << toString <| getY size
      , A.width << toString <| getX size
      ]

    polygon =
      Svg.polygon
        [ A.fill "#FFF"
        , toPoints mask
        ]
        []

    mask' =
      node
        "mask"
        [ A.x "0", A.y "0", id key' ]
        [ polygon ]

    image =
      Svg.rect
        (A.x "0"
          ::
            A.y "0"
          --   :: A.xlinkHref shader
          ::
            A.fill "red"
          ::
            A.mask (url key')
          ::
            A.maskContentUnits "userSpaceOnUse"
          ::
            hw
        )
        []
  in
    Svg.svg
      (A.x "0" :: A.y "0" :: style style' :: hw)
      [ Svg.defs [] [ mask' ]
      , image
      ]

这里有一些相关的进口

import Html exposing (..)
import Svg
import Svg.Attributes as A
import Html.Attributes as H exposing (style, id)

更新

在评论的帮助下计算出来。它是node vs Svg.node。当我将其更改为Svg.node时,问题就消失了。问题是:

  1. 为什么要修复它?
  2. 这里有什么重要的内容?
  3. 这可以设置为类型安全,以便我遇到的问题可能是编译时错误吗?

2 个答案:

答案 0 :(得分:3)

这两行的原因是:

import Html exposing (..)
import Svg

第一个导入Html的所有属性,包括node,第二个只导入Svg命名空间。因此,当您在node中使用node时,Html.nodeimport Html exposing (..) import Svg exposing (..) 。使用此导入会出现编译错误:

import Html exposing (node)
import Svg exposing (node)

或者这个:

node

因此,榆树不知道您要使用哪个(..)。 因此,导入所需的功能而不使用Html.node

更安全

所以主要问题是为什么List Svg.Attribute接受VirtualDom.Property而不会抛出错误。其原因Svg.AttributeHtml.Attribute不是真实类型,而是Htm.Html的类型别名。所以对于编译器来说两者都是相同的类型。 Svg.SvgVirtualDom.Node相同,它们都是node的别名。

最后,String -> List VirtualDom.Property -> List VirtualDom.Node -> VirtualDom.Node 个函数都有签名

<div>

所以编译器无法区分它们。

答案 1 :(得分:1)

仅供参考,以下是node个函数的代码:

--Html.node
node : String -> List Attribute -> List Html -> Html
node =
    VirtualDom.node


--Svg.node
node : String -> List Attribute -> List Svg -> Svg
node name =
  \attributes children ->
    VirtualDom.node name (svgNamespace :: attributes) children

当发生这种情况时,编译器可能会发出警告。