• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Inline SVG - トラブルとその対策
 

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

on

  • 5,041 views

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

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

Statistics

Views

Total Views
5,041
Views on SlideShare
4,359
Embed Views
682

Actions

Likes
13
Downloads
15
Comments
0

11 Embeds 682

http://kadoppe.com 488
http://scrtree.github.io 127
https://twitter.com 45
http://cloud.feedly.com 11
https://www.chatwork.com 4
http://tweetedtimes.com 2
http://www.google.co.jp 1
http://feedproxy.google.com 1
http://cache.mummify.it 1
http://digg.com 1
http://webcache.googleusercontent.com 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

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

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