Posted at
Riot.jsDay 14

Riot.jsでSVGを描画しようとしたら小一時間程ハマった話

More than 1 year has passed since last update.

この記事はRiot.js Advent Calendar 2016の14日目の記事です。

昨日に続いて記事を書かせていただきます!

先日Riot.jsでSVG画像を生成するコードを書いていたのですが、その時ハマった時のお話です。

以下のコードを実行するとこのような画像が描画されます。


svg.html

<svg-cross></svg-cross>

<script src="https://cdnjs.cloudflare.com/ajax/libs/riot/2.6.7/riot+compiler.js"></script>
<script type="riot/tag">
<svg-cross>
<svg width="100" height="100" version="1.1" viewbox="0 0 100 100">
<line x1="0" y1="50.5" x2="100" y2="50.5" stroke="gray"/>
<line x1="50.5" y1="0" x2="50.5" y2="100" stroke="gray"/>
<line each={l in lines} x1={l.x1} y1={l.y1} x2={l.x2} y2={l.y2} stroke={l.color} stroke-dasharray="2,2"/>
</svg>
this.lines = [
{
x1: 10.5,
y1: 10.5,
x2: 90.5,
y2: 90.5,
color: 'red',
},
{
x1: 90.5,
y1: 10.5,
x2: 10.5,
y2: 90.5,
color: 'blue',
},
];
</svg-cross>
</script>
<script>
riot.mount('svg-cross');
</script>

見た目上はまったく問題ないんですがコンソールログを見たら大量のエラーが…


コンソールログ(一部抜粋)

riot+compiler.js:1994 Error: <line> attribute x1: Expected length, "{l.x1}".

setInnerHTML @ riot+compiler.js:1994
_mkdom @ riot+compiler.js:996
Tag @ riot+compiler.js:1497
mountTo @ riot+compiler.js:2454
pushTags @ riot+compiler.js:2597
each @ riot+compiler.js:1959
pushTags @ riot+compiler.js:2601
riot.mount @ riot+compiler.js:2652
(anonymous) @ riot+compiler.js:3537
done @ riot+compiler.js:3453
compileTag @ riot+compiler.js:3460
compileScripts @ riot+compiler.js:3471
(anonymous) @ riot+compiler.js:3524
riot.mount @ riot+compiler.js:3537
(anonymous) @ svg.html:36
riot+compiler.js:1994 Error: <line> attribute y1: Expected length, "{l.y1}".
setInnerHTML @ riot+compiler.js:1994
_mkdom @ riot+compiler.js:996
Tag @ riot+compiler.js:1497
mountTo @ riot+compiler.js:2454
pushTags @ riot+compiler.js:2597
each @ riot+compiler.js:1959
pushTags @ riot+compiler.js:2601
riot.mount @ riot+compiler.js:2652
(anonymous) @ riot+compiler.js:3537
done @ riot+compiler.js:3453
compileTag @ riot+compiler.js:3460
compileScripts @ riot+compiler.js:3471
(anonymous) @ riot+compiler.js:3524
riot.mount @ riot+compiler.js:3537
(anonymous) @ svg.html:36
riot+compiler.js:1994
...

lineの座標指定属性に設定したテンプレート変数用の{}がうまくパースできなくて怒られているみたい?(マジックナンバーでは問題なし)

別に表示上は問題ないのですが、コンソールログが出続けるのは気持ち悪い!(SPAにした日にはガンガンコンソールログが蓄積されていきますしね。。)

いろいろ調べていたら解決策っぽいのが…?

SVG tries to render before RiotJS replaces variables

明確な原因までは書かれていませんでしたが、x1,x2,y1,y2の属性名にそれぞれriot-を付けてあげればいいみたいですね。

-  <line each={l in lines} x1={l.x1} y1={l.y1} x2={l.x2} y2={l.y2} stroke={l.color}/>

+ <line each={l in lines} riot-x1={l.x1} riot-y1={l.y1} riot-x2={l.x2} riot-y2={l.y2} stroke={l.color}/>

ちなみに<line>以外ですと、<text>のx,yでも発生しました。

はー、すっきりした。。。

しかしRiot.jsでSVGを扱えるのはありがたいですね。図やグラフもサクサク描けそうです。