SVG¶
Create SVG¶
You can create SVG using JSX or lit-HTML. For example, below is a reimplementation of a snabbdom example by Jon Kleiser (@jkleiser).
SVG use JSX¶
const style=`
svg {
display: block;
margin-bottom: 10px;
border: 1px solid gray;
}
g#carousel {
-webkit-transition: -webkit-transform 1s ease;
transition: transform 1s ease;
}
polygon {
stroke: #808000;
transition: fill 0.5s linear;
}
polygon#yellow {
fill: rgba(255,255,0,0.4);
}
polygon#yellow:hover, polygon#yellow:active {
fill: yellow;
}
polygon#green {
fill: rgba(0,128,0,0.4);
}
polygon#green:hover, polygon#green:active {
fill: green;
}
polygon#magenta {
fill: rgba(255,0,255,0.4);
}
polygon#magenta:hover, polygon#magenta:active {
fill: magenta;
}
polygon#red {
fill: rgba(255,0,0,0.4);
}
polygon#red:hover, polygon#red:active {
fill: red;
}
polygon#cyan {
fill: rgba(0,255,255,0.4);
}
polygon#cyan:hover, polygon#cyan:active {
fill: cyan;
}
polygon#blue {
fill: rgba(0,0,255,0.4);
}
polygon#blue:hover, polygon#blue:active {
fill: blue;
}
`
const triangles = [
{id: "yellow", rot: 0},
{id: "green", rot: 60},
{id: "magenta", rot: 120},
{id: "red", rot: 180},
{id: "cyan", rot: 240},
{id: "blue", rot: 300}
];
class SvgComponent extends Component {
state = 0;
view = state => {
const transform = "rotate(" + state + "deg)";
return <div className="view">
<style>{style}</style>
<svg width="380" height="380" viewBox="-190,-190,380,380">
<g id="carousel" style={{transform}}>
{triangles.map(t =>
<polygon id={t.id}
points="-50,-88 0,-175 50,-88"
transform={`rotate(${t.rot})`}
stroke-width="3" />
)}
</g>
</svg>
<button $onclick="rot+60">Rotate Clockwise</button>
<button $onclick="rot-60">Rotate Anticlockwise</button>
<button $onclick="reset">Reset</button>
</div>
};
update = {
"rot+60": state => state + 60,
"rot-60": state => state - 60,
"reset": state => 0,
};
}
new SvgComponent().start(document.body);
SVG use lit-HTML¶
const style=`
svg {
display: block;
margin-bottom: 10px;
border: 1px solid gray;
}
g#carousel {
-webkit-transition: -webkit-transform 1s ease;
transition: transform 1s ease;
}
polygon {
stroke: #808000;
transition: fill 0.5s linear;
}
polygon#yellow {
fill: rgba(255,255,0,0.4);
}
polygon#yellow:hover, polygon#yellow:active {
fill: yellow;
}
polygon#green {
fill: rgba(0,128,0,0.4);
}
polygon#green:hover, polygon#green:active {
fill: green;
}
polygon#magenta {
fill: rgba(255,0,255,0.4);
}
polygon#magenta:hover, polygon#magenta:active {
fill: magenta;
}
polygon#red {
fill: rgba(255,0,0,0.4);
}
polygon#red:hover, polygon#red:active {
fill: red;
}
polygon#cyan {
fill: rgba(0,255,255,0.4);
}
polygon#cyan:hover, polygon#cyan:active {
fill: cyan;
}
polygon#blue {
fill: rgba(0,0,255,0.4);
}
polygon#blue:hover, polygon#blue:active {
fill: blue;
}
`
const triangles = [
{id: "yellow", rot: 0},
{id: "green", rot: 60},
{id: "magenta", rot: 120},
{id: "red", rot: 180},
{id: "cyan", rot: 240},
{id: "blue", rot: 300}
];
class SvgComponent extends Component {
state = 0;
view = state => {
const items = triangles.map(t =>
svg`<polygon id="${t.id}"
points="-50,-88 0,-175 50,-88"
transform="rotate(${t.rot})"
stroke-width="3" />`
);
return html`<div class="view">
<style>${style}</style>
<svg width="380" height="380" viewBox="-190,-190,380,380">
<g id="carousel" style="transform: rotate(${state}deg);">
${items}
</g>
</svg>
<button @click=${run("@rot+60")}>Rotate Clockwise</button>
<button @click=${run("@rot-60")}>Rotate Anticlockwise</button>
<button @click=${run("@reset")}>Reset</button>
</div>`;
};
update = {
"@rot+60": state => state + 60,
"@rot-60": state => state - 60,
"@reset": () => 0,
};
}
new SvgComponent().start(document.body);
SVG - xlink:href¶
You can use xlinkHref to define the xlink:href attribute of SVG.
// SVG - xlink
const view = () => <svg viewBox="0 0 150 20">
<a xlinkHref="https://apprun.js.org/">
<text x="10" y="10" font-size="5">Click Here</text></a>
</svg>
app.start(document.body, {}, view);
SVG Event Handlers¶
You can handle the onclick event of SVG elements. Or use the $onclick directive
// SVG - $onclick
const view = state => <>
<div>click the buttons:</div>
<svg viewBox="0 0 520 520" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="90" height="20" fill="#aaa"
$onclick="test" id="$onclick"/>
<rect x="110" y="10" width="90" height="20" fill="#bbb"
onclick="app.run('test', event)" id="onclick"/>
</svg>
</>
const update = {
test: (state, evt) => alert("You have used: " + evt.target.id)
}
app.start(document.body, '', view, update);
SVG Animation¶
You can use the animate element to add animation to SVG.
// SVG - animation
const view = () => <>
<svg height="60" width="160">
<rect width="100%" height="100%" rx="10" ry="10" fill="lightgrey" />
<circle cx="30" cy="30" r="20" fill='lime'>
<animate
attributeType="XML"
attributeName="fill"
values="lime;lightgrey;lime;lightgrey"
dur="0.5s"
repeatCount="indefinite"/>
</circle>
<circle cx="80" cy="30" r="20" fill='yellow' fill-opacity='0.2'/>
<circle cx="130" cy="30" r="20" fill='orangered' fill-opacity='0.2' />
</svg>
</>;
app.start(document.body, {}, view);