SVG Masking
TSX
import { Dom } from "OneJS/Dom"
import { h, render } from "preact"
import { useEffect, useRef, useState } from "preact/hooks"
import { Color, ScriptableObject, Vector2 } from "UnityEngine"
import { Background, Painter2D, StyleBackground, VectorImage } from "UnityEngine/UIElements"
const axeImage = resource.loadImage("Images/wooden_axe.png")
const SomeShape = ({ overflow }) => {
const ref = useRef<Dom>()
useEffect(() => {
var v = ScriptableObject.CreateInstance(VectorImage)
var p = new Painter2D()
paint(p)
p.SaveToVectorImage(v)
ref.current.ve.style.backgroundImage = new StyleBackground(Background.FromVectorImage(v))
}, [])
function paint(paint2D: Painter2D) {
paint2D.strokeColor = Color.white
paint2D.fillColor = Color.white
paint2D.lineWidth = 10;
paint2D.BeginPath()
paint2D.MoveTo(new Vector2(0, 160))
paint2D.LineTo(new Vector2(100, 0))
paint2D.LineTo(new Vector2(200, 160))
paint2D.ClosePath()
paint2D.Fill()
}
return <div ref={ref} style={{ width: 200, height: 200, overflow: overflow ? "Hidden" : "Visible" }}>
<image class="w-full h-full" image={axeImage} />
</div>
}
const App = () => {
const [overflow, setOverflow] = useState(false)
return <div class="w-full h-full flex justify-center items-center">
<SomeShape overflow={overflow} />
<button onClick={() => setOverflow(!overflow)} text="Toggle" />
</div>
}
render(<App />, document.body)
Ease-of-Use Functional Component based on above example
TSX
export interface MaskParams{image, path:Vector2[]}
export const MaskedImage=({image, path}:MaskParams)=>{
var maskInstance = ScriptableObject.CreateInstance(VectorImage)
var mask = new Painter2D()
drawMask(mask)
mask.SaveToVectorImage(maskInstance)
function drawMask(mask:Painter2D){
mask.BeginPath()
path.map((pos, index)=>index == 0 ? mask.MoveTo(pos) : mask.LineTo(pos))
mask.ClosePath()
mask.Fill()
}
return(
<div style={{backgroundImage: maskInstance, width:"100%", height:"100%", overflow:"Hidden"}}>
<div style={{width:"100%", height:"100%", backgroundImage:image}}/>
</div>
)
}
//Define a path like this
var maskPath:Vector2[]=[
new Vector2(9,0),
new Vector2(96,0),
new Vector2(100, 4),
new Vector2(100, 91),
new Vector2(91, 100),
new Vector2(4, 100),
new Vector2(0, 96),
new Vector2(0, 9)
]
//Implement Like this (if you want to change dimensions, style a div around it or implement a style property in its params)
render(<MaskedImage image={axeImage} mask={maskPath}/>, document.body)