<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>
Simple right? Here's the thing, if I drop this svg into an html file, the masking works perfectly. But when I generate the same svg with virtual dom, the mask has no effect and we just have a huge red rect.
Annoyingly I can get it to display when generated, if I open the developer tools and add a pointless <defs></defs> to the svg. That seems to kick the svg somehow and remind it that it needs to mask.
Anyone know what is going on here? Is there a workaround that doesn't involve setting a timer to inject an empty defs?
Update:
here is the source
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
]
here are some relevant imports
import Html exposing (..)
import Svg
import Svg.Attributes as A
import Html.Attributes as H exposing (style, id)
Update
Figured it out with help from comments. It was node vs Svg.node. When I changed it to Svg.node the problem went away. Question is:
- Why did this fix it?
- What is going on under the covers here that makes this important?
- Can this be made typesafe so that the problem I experienced could be a compile time error?
Its cause of this 2 lines:
The first one imports all attributes of
Htmlincludingnodethe second just import theSvgnamespace. So when you are usingnodein this the environmentnodeis theHtml.node. You would get an compile error with this imports:or this:
cause then, Elm did not know which
nodeyou want to use. So its safer to import the functions that you needed and not using(..)So the main question is why does
Html.nodeacceptsList Svg.Attributewithout throwing an error. Its causeSvg.AttributeandHtml.Attributeare not real types but type aliases forVirtualDom.Property. So for the compiler both are the same type. Same forHtm.HtmlandSvg.Svgwhich are both aliases forVirtualDom.Node.In the end both
nodefunctions have the Signatureso the compiler cant distinguish between them.