Your SlideShare is downloading. ×
Inline SVG - トラブルとその対策
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

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

5,402
views

Published on

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

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


0 Comments
19 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,402
On Slideshare
0
From Embeds
0
Number of Embeds
12
Actions
Shares
0
Downloads
18
Comments
0
Likes
19
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Inline SVG - トラブルとその対策 2013/10/12 第8回HTML5など勉強会 @kadoppe
  • 2. 自己紹介 ● 名前 ● 門脇 恒平 @kadoppe ● 職業 ● ソフトウェアエンジニア ● 所属 ● 株式会社シェアウィズ & HTML5-WEST.jp
  • 3. 本日のスライド ● SlideShare ● http://www.slideshare.net/kadoppe
  • 4. アジェンダ ● SVGとInline SVG ● なぜInline SVGを使ったのか ● トラブルと対策 ● 学んだこと・教訓
  • 5. SVGとInline SVG
  • 6. SVGとは ● S: Scalable(拡大可能な) ● V: Vector(ベクター形式の) ● G: Graphic(画像) ● 直訳すると「拡大可能なベクター画像」
  • 7. 特徴1: 拡大・縮小してもきれい 点で画像を表現 線で画像を表現
  • 8. 特徴2: XML形式のフォーマット ● XML要素で円や線などの形を表現 ● テキストエディタで編集可能
  • 9. Inline SVGとは ● HTML5 からの新機能 ● HTMLドキュメントにSVGマークアップ を埋め込み可能に
  • 10. Inline SVGのサンプル <html> <body> <h1>Inline SVGサンプル</h1> <svg width=100 height=100> <circle r=50 cx=50 cy=50 /> </svg> </body> </html>
  • 11. Inline SVGのメリット ● 画像のルックアンドフィールをCSSで 変更可能 ● 円の色、線の太さを変える、など ● 画像内の各要素に対するユーザ操作を JavaScriptでハンドリング可能 ● マウスクリック、ドラッグなどに対する処理
  • 12. 利用可能なブラウザ ブラウザ 対応バージョン Internet Explorer 9以降 Firefox 3.0以降 Chrome 4.0以降 Safari 3.2以降 iOS Safari 3.2以降 Android 3.0以降
  • 13. JavaScriptライブラリ ● D3.js - http://d3js.org ● Webページでデータビジュアライゼーション ● Raphaël - http://raphaeljs.com ● Webページ上でベクター画像を動的に生成
  • 14. WebにおけるSVGの活用事例 ● 活用例1 ● ロゴやアイコン画像 ● 活用例2 ● インタラクティブなWebアプリケーション
  • 15. ロゴやアイコン画像
  • 16. ロゴやアイコン画像
  • 17. Webアプリケーション 無料学習サイト ShareWis http://share-wis.com
  • 18. なぜInline SVGを 使ったのか
  • 19. ShareWis開発前の要件 ● GoogleマップのようなUI上に コンテンツを配置 ● マウス操作に応じて各コンテンツが アニメーション ● iPadのSafariに対応 ● 古いブラウザ(IE 8以下)は非対応
  • 20. 利用する技術の選択肢 ● Flash ● Google Maps JavaScript API (カスタムオーバレイ) ● Inline SVG
  • 21. 利用する技術の選択肢 ● Flash ● Google Maps JavaScript API (カスタムオーバレイ) ● Inline SVG
  • 22. トラブルと対策 Inline SVGから始まる茨の道
  • 23. やりたかったこと(1) text要素に下線を引く
  • 24. text-decoration属性 <svg witdh=100 height=100> <text text-decoration=underline x=0 y=20>Hello World</text> </svg> 下線が表示される
  • 25. 発生したトラブル Firefoxで下線が 表示されない
  • 26. 原因調査 ● 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のレンダリング方法の問題
  • 27. 対策1: line要素で下線を引く ● 手順 1. text要素の大きさ(高さと幅)をgetBBox() メソッドを使って取得 2. 適切な座標にline要素を挿入
  • 28. 解説 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
  • 29. 【朗報】
  • 30. 対策2: 新しいFirefoxをつかう ● Firefox 25 ● 2013/10/29 リリース予定 ● 待望のtext要素の下線表示に対応
  • 31. やりたかったこと(2) 要素の大きさを取得する
  • 32. getBBox()メソッド var textElm = document.getElementById('text'); var box = textElm.getBBox(); alert(box.height); // text要素の高さ alert(box.width); // text要素の幅
  • 33. 発生したトラブル Firefoxで NS_ERROR_FAILURE
  • 34. NS_ERROR_FAILURE? 意味 「なんかエラー」
  • 35. NS_ERROR_FAILURE? 23 /* Returned when a function fails */ 24 ERROR(NS_ERROR_FAILURE, 0x80004005), mozilla/xpcom/base/ErrorList.h 何らかの原因で関数の実行が失敗した時のエラー
  • 36. 原因調査 ● 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
  • 37. バグ再現方法 ● 方法1 ● ドキュメントにまだ追加されていない 要素に対してgetBBox()メソッドを呼び出す ● 方法2 ● ドキュメントに追加されているが display: none な要素に対して getBBox()メソッドを呼び出す
  • 38. 対策1: try-catch文で囲む try { var textElm = document.getElementById('text'); var box = textElm.getBBox(); } catch (e) { alert(e); } NS_ERROR_FAILUREはtry-catchで補足可能
  • 39. 対策2: displayプロパティを確認する var textElm = document.getElementById('text'); if (getComputedStyle(textElm, null).display !== ‘none’) { var box = textElm.getBBox(); } getBBox()メソッドを呼び出す前に display: noneでないことを確認
  • 40. やりたかったこと(3) テキストを折り返す
  • 41. text要素の文字列を折り返す これは折り返されたテキストです。ラーメ ンが食べたい。無鉄砲のラーメンが食べた いです。 横幅を指定してテキストを自動で折り返し
  • 42. 発生したトラブル テキストが折り返されない これは折り返されたテキストです。ラーメンが食べたい
  • 43. 原因調査 ● SVGの仕様です ● SVGのtext要素はHTMLのdiv要素みたいに 自動で文字列を折り返してくれない ● textArea要素 ● 自動折り返しに対応したtext要素 ● まだどのブラウザも対応していない
  • 44. 対策: tspan要素を使う <svg witdh=100 height=100> <text>これは折り返されたテキストです。ラーメンが食べたい。</text> </svg> <svg witdh=100 height=100> <text> <tspan>これは折り返されたテキストです。</tspan> <tspan>ラーメンが食べたい。</tspan> </text> </svg> 文字列を複数の要素に分割
  • 45. 詳しい手順 1.文字列を単語単位に分割 2.指定された幅を超えるまで 1単語ずつtspan要素に追加 3.超えたら末尾の単語を削除して tspan要素の位置を調整 4.2に戻る
  • 46. 幅を超えたかどうかの判定 for (var i = 0; i < words.length; i++) { tspanEl.textContent += word if (tspanEl.getComputedTextLength() > width) { // 超えた } else { // 超えてない } } getComputedTextLength()で幅を取得
  • 47. 結果こうなる <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>
  • 48. やりたかったこと(4) 縁取り文字を表示する
  • 49. 縁取り文字 ラーメンが食べたいラーメンが食べたい
  • 50. 発生したトラブル 縁取り文字を簡単に 表示できない
  • 51. 原因調査 ● text要素に縁取りを追加する 便利なプロパティが存在しない
  • 52. 方法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では縁が表示されない
  • 53. 方法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つあるのが 文書の意味的におかしい
  • 54. ● SVG Filter ● SVG画像に様々な効果を適用する機能 ● ドロップシャドウ、色の変換など ● まだ試していないので実現できるか不明 方法3: SVG Filterを使う
  • 55. やりたかったこと(5) ズーム時に文字サイズを 固定する
  • 56. ズームの仕組み <svg witdh=100 height=100> <g transform=”scale(倍率)”> <circle /> <circle /> <circle /> <text /> <text /> </g> </svg> 全体を囲むg要素のtransform属性を操作する
  • 57. ズーム
  • 58. 発生したトラブル ズーム時に文字サイズが 変化してしまう
  • 59. テキストテキスト テキスト テキスト OK NGNG
  • 60. 原因調査 ● SVGの仕様です
  • 61. 対策: 文字サイズを動的に変更 $elm.on(‘mousewheel’, function() { // 略 var scale = 現在の倍率 var originalFontSize = 24; var currentFontSize = originalFontSize / scale; // 略 (text要素のfontサイズ変更処理) } 問題点:text要素の数が多いと処理が重たくなる
  • 62. 対策: 文字サイズ変更を遅延 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); } マウスホイールイベントが連続して発生しているときは 文字サイズを変更しない
  • 63. 学んだこと
  • 64. SVG Textには トラブルがいっぱい
  • 65. ●SVGの仕様では(シンプルに)実現でき ない表現がある ●ブラウザ間の差異が存在する
  • 66. 教訓
  • 67. ●SVGで(シンプル)に実現できないこと はしない ●ブラウザ間の差異を許容する
  • 68. そうしないと… ● コードが必要以上に複雑になる ● パフォーマンス低下・バグ発生の原因に
  • 69. そんなInline SVGは 使っていて楽しい技術
  • 70. みんなもっと 使って情報交換しよう
  • 71. おしまい

×