<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
Html
includingnode
the second just import theSvg
namespace. So when you are usingnode
in this the environmentnode
is theHtml.node
. You would get an compile error with this imports:or this:
cause then, Elm did not know which
node
you want to use. So its safer to import the functions that you needed and not using(..)
So the main question is why does
Html.node
acceptsList Svg.Attribute
without throwing an error. Its causeSvg.Attribute
andHtml.Attribute
are not real types but type aliases forVirtualDom.Property
. So for the compiler both are the same type. Same forHtm.Html
andSvg.Svg
which are both aliases forVirtualDom.Node
.In the end both
node
functions have the Signatureso the compiler cant distinguish between them.