【问题标题】:Svg masking doesn't render when generated生成时不渲染 Svg 遮罩
【发布时间】:2016-05-27 04:44:08
【问题描述】:
<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 时,遮罩没有效果,我们只有一个巨大的红色矩形。

如果我打开开发人员工具并将毫无意义的&lt;defs&gt;&lt;/defs&gt; 添加到 svg,我可以在生成时显示它。这似乎以某种方式踢了 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)

更新

在 cmets 的帮助下解决了这个问题。这是nodeSvg.node。当我将其更改为Svg.node 时,问题就消失了。问题是:

  1. 为什么要修复它?
  2. 究竟是什么让这变得如此重要?
  3. 是否可以将其设为类型安全,以便我遇到的问题可能是编译时错误?

【问题讨论】:

  • 向我们展示生成 SVG 的代码。我想这就是问题所在。
  • 很可能是发帖者试图将 elm-html 用于 svg 元素并且在它不起作用时会感到困惑(有一个 elm-svg 库)
  • 更新代码@RobertLongson
  • @kakigoori 更新了代码,我也在使用 elm-svg,我认为没有区别。
  • 似乎Svg.nodeHtml.node有相似的签名:&gt; Html.node &lt;function: node&gt; : String -&gt; List Html.Attribute -&gt; List Html.Html -&gt; Html.Html&gt; Svg.node &lt;function&gt; : String -&gt; List Svg.Attribute -&gt; List Svg.Svg -&gt; Svg.Svg 我检查了Svg.SvgHtml.Html类型,两者都是Node的别名。由于您得到不同的行为,因此实现肯定会有所不同。

标签: svg elm image-masking virtual-dom


【解决方案1】:

这2行的原因:

import Html exposing (..)
import Svg

第一个导入Html 的所有属性,包括node,第二个只是导入Svg 命名空间。所以当你在这个环境中使用node 时,node 就是Html.node。你会得到这个导入的编译错误:

import Html exposing (..)
import Svg exposing (..)

或者这个:

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

因为那时,Elm 不知道您想使用哪个 node。 所以导入你需要的函数而不使用(..)

会更安全

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

最后两个node 函数都有签名

String -> List VirtualDom.Property -> List VirtualDom.Node -> VirtualDom.Node

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

【讨论】:

  • 谢谢!但是,这并不能回答我的 3 个问题中的任何一个。
  • 对不起,但我认为它回答了所有问题。问题是您在使用(..) 时导入了所有函数。因此,它们现在可以在名称下使用,而无需命名空间前缀。所以Html.nodenode 是一回事。
  • update 部分执行,我说了这么多。我知道导入和混淆Svg.nodeHtml.node 的方式。我明白了,但为什么这很重要?在 HtmlSvg 模块的背后,有什么不同之处使这种差异变得重要?为什么这不是类型错误?会不会是类型错误?以下是上述问题: 1. 为什么要修复它? 2. 是什么让这变得重要? 3. 是否可以将其设为类型安全,以便我遇到的问题可能是编译时错误?
  • 您的回答正确地断言 Svg.nodeHtml.node 是问题所在,但没有解释为什么会这样。
  • 加一句为什么这不会导致编译错误
【解决方案2】:

仅供参考,以下是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

当这种情况发生时,也许编译器应该警告你。

【讨论】:

  • 问题是两个函数有相同的签名。 Html.AttributeSvg.Attribute 都是 VirtualDom.Property 的别名。 Svg.Svg 和Html.Html 相同,它们只是VirtualDom.Node 的别名。
  • 是的,我知道。这就是为什么我说从编译器那里获得警告可能会很好。
  • 很有趣,所以它失败的原因与缺少的svgNamespace 有关,但那是什么?当我查看呈现的页面时,源看起来没有什么不同。
  • 它也应该有命名空间:svgNamespace : Attribute svgNamespace = VirtualDom.property "namespace" (Json.string "http://www.w3.org/2000/svg")
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多