inline svg - トラブルとその対策

71
Inline SVG - トラブルとその対策 2013/10/12 第8回HTML5など勉強会 @kadoppe

Upload: kohei-kadowaki

Post on 05-Dec-2014

6.091 views

Category:

Documents


0 download

DESCRIPTION

2013/10/12 に大阪で開催された「第8回HTML5など勉強会」で利用した資料です

TRANSCRIPT

Page 1: Inline SVG - トラブルとその対策

Inline SVG - トラブルとその対策

2013/10/12 第8回HTML5など勉強会 @kadoppe

Page 2: Inline SVG - トラブルとその対策

自己紹介●名前

● 門脇 恒平 @kadoppe

●職業● ソフトウェアエンジニア

●所属● 株式会社シェアウィズ & HTML5-WEST.jp

Page 3: Inline SVG - トラブルとその対策

本日のスライド

● SlideShare● http://www.slideshare.net/kadoppe

Page 4: Inline SVG - トラブルとその対策

アジェンダ

● SVGとInline SVG●なぜInline SVGを使ったのか●トラブルと対策●学んだこと・教訓

Page 5: Inline SVG - トラブルとその対策

SVGとInline SVG

Page 6: Inline SVG - トラブルとその対策

SVGとは

● S: Scalable(拡大可能な)● V: Vector(ベクター形式の)● G: Graphic(画像)●直訳すると「拡大可能なベクター画像」

Page 7: Inline SVG - トラブルとその対策

特徴1: 拡大・縮小してもきれい

点で画像を表現 線で画像を表現

Page 8: Inline SVG - トラブルとその対策

特徴2: XML形式のフォーマット● XML要素で円や線などの形を表現●テキストエディタで編集可能

Page 9: Inline SVG - トラブルとその対策

Inline SVGとは

● HTML5 からの新機能● HTMLドキュメントにSVGマークアップを埋め込み可能に

Page 10: Inline SVG - トラブルとその対策

Inline SVGのサンプル<html><body> <h1>Inline SVGサンプル</h1>

<svg width=100 height=100> <circle r=50 cx=50 cy=50 /> </svg></body></html>

Page 11: Inline SVG - トラブルとその対策

Inline SVGのメリット●画像のルックアンドフィールをCSSで変更可能● 円の色、線の太さを変える、など

●画像内の各要素に対するユーザ操作をJavaScriptでハンドリング可能● マウスクリック、ドラッグなどに対する処理

Page 12: Inline SVG - トラブルとその対策

利用可能なブラウザブラウザ 対応バージョン

Internet Explorer 9以降Firefox 3.0以降Chrome 4.0以降Safari 3.2以降

iOS Safari 3.2以降Android 3.0以降

Page 13: Inline SVG - トラブルとその対策

JavaScriptライブラリ

● D3.js - http://d3js.org● Webページでデータビジュアライゼーション

● Raphaël - http://raphaeljs.com● Webページ上でベクター画像を動的に生成

Page 14: Inline SVG - トラブルとその対策

WebにおけるSVGの活用事例

●活用例1● ロゴやアイコン画像

●活用例2● インタラクティブなWebアプリケーション

Page 15: Inline SVG - トラブルとその対策

ロゴやアイコン画像

Page 16: Inline SVG - トラブルとその対策

ロゴやアイコン画像

Page 17: Inline SVG - トラブルとその対策

Webアプリケーション

無料学習サイト ShareWis http://share-wis.com

Page 18: Inline SVG - トラブルとその対策

なぜInline SVGを使ったのか

Page 19: Inline SVG - トラブルとその対策

ShareWis開発前の要件● GoogleマップのようなUI上にコンテンツを配置

●マウス操作に応じて各コンテンツがアニメーション

● iPadのSafariに対応●古いブラウザ(IE 8以下)は非対応

Page 20: Inline SVG - トラブルとその対策

利用する技術の選択肢

● Flash● Google Maps JavaScript API(カスタムオーバレイ)

● Inline SVG

Page 21: Inline SVG - トラブルとその対策

利用する技術の選択肢

● Flash● Google Maps JavaScript API(カスタムオーバレイ)

● Inline SVG

Page 22: Inline SVG - トラブルとその対策

トラブルと対策Inline SVGから始まる茨の道

Page 23: Inline SVG - トラブルとその対策

やりたかったこと(1)

text要素に下線を引く

Page 24: Inline SVG - トラブルとその対策

text-decoration属性

<svg witdh=100 height=100> <text text-decoration=underline x=0 y=20>Hello World</text></svg>

下線が表示される

Page 25: Inline SVG - トラブルとその対策

発生したトラブル

Firefoxで下線が表示されない

Page 26: Inline SVG - トラブルとその対策

原因調査● Bugzilla@Mozillaにバグ報告あり

● Bug 317196 - Support the 'text-decoration' property in SVG (underline, etc.) - https://bugzilla.mozilla.org/show_bug.cgi?id=317196

● 報告日: 2005/11/20

● SVG Textのレンダリング方法の問題

Page 27: Inline SVG - トラブルとその対策

対策1: line要素で下線を引く

●手順1. text要素の大きさ(高さと幅)をgetBBox()メソッドを使って取得

2.適切な座標にline要素を挿入

Page 28: Inline SVG - トラブルとその対策

解説var textElm = document.getElementById('text');var box = textElm.getBBox();

alert(box.height); // text要素の高さalert(box.width); // text要素の幅

<svg> <text x=0 y=20>Hello World</text> <line x1=X1 y1=Y1 x2=X2 y2=Y2 /></svg>

高さと幅をもとにline要素の始点・終点を計算

Hello World

Page 29: Inline SVG - トラブルとその対策

【朗報】

Page 30: Inline SVG - トラブルとその対策

対策2: 新しいFirefoxをつかう

● Firefox 25 ● 2013/10/29 リリース予定

● 待望のtext要素の下線表示に対応

Page 31: Inline SVG - トラブルとその対策

やりたかったこと(2)

要素の大きさを取得する

Page 32: Inline SVG - トラブルとその対策

getBBox()メソッド

var textElm = document.getElementById('text');var box = textElm.getBBox();

alert(box.height); // text要素の高さalert(box.width); // text要素の幅

Page 33: Inline SVG - トラブルとその対策

発生したトラブル

FirefoxでNS_ERROR_FAILURE

Page 34: Inline SVG - トラブルとその対策

NS_ERROR_FAILURE?

23 /* Returned when a function fails */24 ERROR(NS_ERROR_FAILURE,

0x80004005),

意味

「なんかエラー」

Page 35: Inline SVG - トラブルとその対策

NS_ERROR_FAILURE?

23 /* Returned when a function fails */24 ERROR(NS_ERROR_FAILURE, 0x80004005),

23 /* Returned when a function fails */24 ERROR(NS_ERROR_FAILURE,

0x80004005),

mozilla/xpcom/base/ErrorList.h

何らかの原因で関数の実行が失敗した時のエラー

Page 36: Inline SVG - トラブルとその対策

原因調査

● Bugzilla@Mozillaにバグ報告あり● Bug 612118 - SVGLocatable.getBBox() fails unless the SVG element it is applied to is attached and rendered - https://bugzilla.mozilla.org/show_bug.cgi?id=612118

Page 37: Inline SVG - トラブルとその対策

バグ再現方法●方法1

● ドキュメントにまだ追加されていない要素に対してgetBBox()メソッドを呼び出す

●方法2● ドキュメントに追加されているがdisplay: none な要素に対してgetBBox()メソッドを呼び出す

Page 38: Inline SVG - トラブルとその対策

対策1: try-catch文で囲む

try { var textElm = document.getElementById('text'); var box = textElm.getBBox();} catch (e) { alert(e);}

NS_ERROR_FAILUREはtry-catchで補足可能

Page 39: Inline SVG - トラブルとその対策

対策2: displayプロパティを確認する

var textElm = document.getElementById('text');if (getComputedStyle(textElm, null).display !== ‘none’) { var box = textElm.getBBox();}

getBBox()メソッドを呼び出す前にdisplay: noneでないことを確認

Page 40: Inline SVG - トラブルとその対策

やりたかったこと(3)

テキストを折り返す

Page 41: Inline SVG - トラブルとその対策

text要素の文字列を折り返す

これは折り返されたテキストです。ラーメンが食べたい。無鉄砲のラーメンが食べたいです。

横幅を指定してテキストを自動で折り返し

Page 42: Inline SVG - トラブルとその対策

発生したトラブル

テキストが折り返されないこれは折り返されたテキストです。ラーメンが食べたい。無鉄砲のラーメンが食べたいです。

Page 43: Inline SVG - トラブルとその対策

原因調査● SVGの仕様です

● SVGのtext要素はHTMLのdiv要素みたいに自動で文字列を折り返してくれない

● textArea要素● 自動折り返しに対応したtext要素

● まだどのブラウザも対応していない

Page 44: Inline SVG - トラブルとその対策

対策: tspan要素を使う<svg witdh=100 height=100> <text>これは折り返されたテキストです。ラーメンが食べたい。</text></svg>

<svg witdh=100 height=100> <text> <tspan>これは折り返されたテキストです。</tspan> <tspan>ラーメンが食べたい。</tspan>

</text></svg>

文字列を複数の要素に分割

Page 45: Inline SVG - トラブルとその対策

詳しい手順1.文字列を単語単位に分割

2.指定された幅を超えるまで1単語ずつtspan要素に追加

3.超えたら末尾の単語を削除してtspan要素の位置を調整

4.2に戻る

Page 46: Inline SVG - トラブルとその対策

幅を超えたかどうかの判定

for (var i = 0; i < words.length; i++) { tspanEl.textContent += word if (tspanEl.getComputedTextLength() > width) { // 超えた } else { // 超えてない }}

getComputedTextLength()で幅を取得

Page 47: Inline SVG - トラブルとその対策

結果こうなる<svg witdh=100 height=100> <text> <tspan x=0 dy=”18”>これは折り返された</tspan> <tspan x=0 dy=”18”>テキストです。ラー</tspan> <tspan x=0 dy=”18”>メンが食べたい。</tspan> </text></svg>

Page 48: Inline SVG - トラブルとその対策

やりたかったこと(4)

縁取り文字を表示する

Page 49: Inline SVG - トラブルとその対策

縁取り文字

ラーメンが食べたいラーメンが食べたい

Page 50: Inline SVG - トラブルとその対策

発生したトラブル

縁取り文字を簡単に表示できない

Page 51: Inline SVG - トラブルとその対策

原因調査

● text要素に縁取りを追加する便利なプロパティが存在しない

Page 52: Inline SVG - トラブルとその対策

方法1: text-shadow<svg witdh=100 height=100> <text>ラーメンが食べたい</text></svg>

text { fill: white; text-shadow: -1px -1px black, 1px -1px black, -1px 1px black, -1px -1px black;}

・縁が汚い・Firefoxでは縁が表示されない

Page 53: Inline SVG - トラブルとその対策

方法2: text要素を重ねる<svg witdh=100 height=100> <text class=”outline”>ラーメンが食べたい</text> <text class=”body”>ラーメンが食べたい</text>

</svg>

.outline { stroke: black; stroke-width: 3px;}.body { fill: white;}

text要素が2つあるのが文書の意味的におかしい

Page 54: Inline SVG - トラブルとその対策

● SVG Filter● SVG画像に様々な効果を適用する機能

● ドロップシャドウ、色の変換など

●まだ試していないので実現できるか不明

方法3: SVG Filterを使う

Page 55: Inline SVG - トラブルとその対策

やりたかったこと(5)

ズーム時に文字サイズを固定する

Page 56: Inline SVG - トラブルとその対策

ズームの仕組み

<svg witdh=100 height=100> <g transform=”scale(倍率)”> <circle /> <circle /> <circle /> <text /> <text /> </g></svg>

全体を囲むg要素のtransform属性を操作する

Page 57: Inline SVG - トラブルとその対策

ズーム

Page 58: Inline SVG - トラブルとその対策

発生したトラブル

ズーム時に文字サイズが変化してしまう

Page 59: Inline SVG - トラブルとその対策

テキストテキスト

テキスト

テキスト

OK

NGNG

Page 60: Inline SVG - トラブルとその対策

原因調査

● SVGの仕様です

Page 61: Inline SVG - トラブルとその対策

対策: 文字サイズを動的に変更

$elm.on(‘mousewheel’, function() { // 略 var scale = 現在の倍率 var originalFontSize = 24; var currentFontSize = originalFontSize / scale;

// 略 (text要素のfontサイズ変更処理)}

問題点:text要素の数が多いと処理が重たくなる

Page 62: Inline SVG - トラブルとその対策

対策: 文字サイズ変更を遅延var timer = false;$elm.on(‘mousewheel’, function() { if (timer !== false) { clearTimeout(timer); } timer = setTimeout(function() { var scale = 現在の倍率 var originalFontSize = 24; var currentFontSize = originalFontSize / unscale;

// 略 (text要素の文字サイズ変更処理) }, 200);}

マウスホイールイベントが連続して発生しているときは文字サイズを変更しない

Page 63: Inline SVG - トラブルとその対策

学んだこと

Page 64: Inline SVG - トラブルとその対策

SVG Textにはトラブルがいっぱい

Page 65: Inline SVG - トラブルとその対策

●SVGの仕様では(シンプルに)実現できない表現がある

●ブラウザ間の差異が存在する

Page 66: Inline SVG - トラブルとその対策

教訓

Page 67: Inline SVG - トラブルとその対策

●SVGで(シンプル)に実現できないことはしない

●ブラウザ間の差異を許容する

Page 68: Inline SVG - トラブルとその対策

そうしないと…

●コードが必要以上に複雑になる●パフォーマンス低下・バグ発生の原因に

Page 69: Inline SVG - トラブルとその対策

そんなInline SVGは使っていて楽しい技術

Page 70: Inline SVG - トラブルとその対策

みんなもっと使って情報交換しよう

Page 71: Inline SVG - トラブルとその対策

おしまい