Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
FlutterをHTML elementに埋め込む
Search
ken
July 15, 2023
Programming
1.4k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
FlutterをHTML elementに埋め込む
ken
July 15, 2023
More Decks by ken
See All by ken
Dart3を試す
masumitsu
0
590
Other Decks in Programming
See All in Programming
AI時代のシニアエンジニアとは
yosuke_furukawa
PRO
12
11k
Kotlinの15年とServer-Side Kotlin
n_takehata
1
170
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
220
FactoryBotをやめればRSpecは速くなるのか?
yuta_onishi_97
0
1.2k
TS 7.0 で baseUrl が使えなくなった今、パスエイリアスをどうするか
bicstone
1
270
気持ちぃ〜角丸 Squircle
ryu1013
0
370
AI-Powered Domain-Driven Design
ziobrando
0
360
contenteditable と日本語入力に向き合う
colorful12
0
230
AI時代のIaC入門 〜なぜインフラをコードで管理したいのか?〜 / Introduction to IaC in the AI Era
akihisaikeda
5
1.3k
学びを記事・スライド・Xへ高速展開する― AI-assisted Learning Loopで回すコンテンツ生成術
ochtum
0
170
クラウドゲーミングのパフォーマンス最適化に挑む / Cloud Gaming Performance Tuning
vivion
0
310
パスワード再設定メールのURLについて知っておこう
uyuki234
0
200
Featured
See All Featured
Optimising Largest Contentful Paint
csswizardry
37
4k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
720
The Director’s Chair: Orchestrating AI for Truly Effective Learning
tmiket
1
340
Prompt Engineering for Job Search
mfonobong
0
560
Unsuck your backbone
ammeep
672
58k
Designing Experiences People Love
moore
143
24k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
500
A better future with KSS
kneath
240
18k
Faster Mobile Websites
deanohume
310
32k
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
2
2.9k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
360
WCS-LA-2024
lcolladotor
0
940
Transcript
FlutterをHTML elementに 埋め込む 2023/07/14 第4回 FlutterGakkai
自己紹介 • kenma: 益満 健 (Masumitsu Ken) • 株式会社ディー・エヌ・エー ◦
日比谷音楽祭2023アプリ作成 (Flutter) • Twitter: @kenma • Qiita: @kenma
なぜ埋め込みたい?? • 既存のWebページがあるから ◦ 例えば、WordPressで作られたサイトに、 Flutterを埋め込む • SEOのため ◦ Flutter
for Webは動的コンテンツなので SEOに不向き ◦ HTML/JSでSEO対策をして、コアの部分は Flutterを埋め込む • 高速化のため ◦ (Flutter WASMで)Webの一部をFlutterに置き換えることにより高速化。(?) • 従来は IFrameを利用することで埋め込みができていた。 ◦ が、IFrameの内外間の相互通信が複雑だった。
試してみる!
プロジェクトセットアップ • flutter 3.10.5 • js 0.67 flutter create sample
--platforms web cd sample flutter pub add js flutter run -d chrome
<!-- 3. #flutter_targetのスタイルを指定。--> <link rel="stylesheet" type="text/css" href="css/style.css" /> </head> <body>
<script> window.addEventListener('load', function(ev) { _flutter.loader.loadEntrypoint({ serviceWorker: { serviceWorkerVersion: serviceWorkerVersion, }, onEntrypointLoaded: function(engineInitializer) { engineInitializer.initializeEngine({ // 2. HTMLエレメントを指定 hostElement: document.querySelector("#flutter_target"), }).then(function(appRunner) { appRunner.runApp(); }); } }); }); </script> <section class="contents"> <div>この下にFlutterアプリを表示する。</div> <article> <!-- 1. flutterアプリを表示するHTMLエレメント --> <div id="flutter_target" class="center"></div> </article> </section> </body> </html> index.htmlの修正 1. Flutterアプリを表示するHTMLエレメント (※)を準備 ◦ id = flutter_target 2. initializeEngineの引数 hostElement に HTMLエレメント(※)を指定 3. HTMLエレメント(※)にCSSでスタイルを当 てるためにcssを読み込む
css/style.cssの作成 1. #flutter_targetのwidth, heightを指定 ◦ 忘れると表示されない! /** 重要!! */ #flutter_target
{ border: 1px solid #aaa; width: 320px; height: 480px; border-radius: 0px; transition: all 150ms ease-in; } .center { margin: auto; width: 50%; }
実行
おわり
埋め込むだけなら <iframe> でもできていた WebアプリとFlutter間でインタラクションをしたい! • Webアプリが主で、Flutterアプリ側が従という関係。 • なので、したいことは、 a. Webアプリから、Flutterアプリを操作する。
b. Webアプリから、Flutterアプリのイベントを検知する。
埋め込むだけなら <iframe> でもできていた WebアプリとFlutter間でインタラクションをしたい! • Webアプリが主で、Flutterアプリ側が従という関係。 • なので、したいことは、 a. Webアプリから、Flutterアプリを操作する。
→ JSからFlutterのメソッドを呼ぶ。 b. Webアプリから、Flutterアプリのイベントを検知する。 → JSからFlutterにcallback関数を渡すメソッドを呼ぶ。 ⇒ どちらもJSから、Flutterのメソッドを呼び出せればいい
作りたいもの どちらも同じカウンタ値を表示 どちらのボタンでも、 カウンタをインクリメントできる
FlutterのメソッドをJSにExportする
main.dart • JS側にExportするクラスに@JSExportアノテー ションをつける。 ◦ クラスの全メソッドがExportされる。 • createDataExport()関数で、オブジェクトをJS からアクセスできる形にラップする •
allowInteropは使わなくてよくなった • js_utilを使って、JSコード呼び出し ◦ setProperty() ◦ callMethod() import 'package:js/js.dart' as js; import 'package:js/js_util.dart' as js_util; // _MyHomePageState を JS側にExport可能にする。 @js.JSExport() class _MyHomePageState extends State<MyHomePage> { int _counter = 0; @override void initState() { super.initState(); // _MyHomePageStateオブジェクトを、JS側にExportする final export = js_util.createDartExport(this); // JS側の globalThis(ブラウザの場合はwindow)の _appStateプロパ ティとして、 // export (_MyHomePageState) をセットする。 js_util.setProperty(js_util.globalThis, '_appState', export); // JS側の globalThisの_stateSetメソッドを引数無しで呼び出す。 js_util.callMethod<void>(js_util.globalThis, '_stateSet', []); }
index.html (function () { // _stateSet関数作成 window._stateSet = function ()
{ console.log('_stateSet function is called') // _appStateプロパティの値を取得 let appState = window._appState; console.log('_appState property is ', appState); }; }()); <!-- js/js-interop.js の読み込み --> <script src="js/js-interop.js" defer></script> </head> • js/js-interop.js を追加 js/js-interop.js • window._stateSet関数の作成 ◦ js_util.callMethod(, _stateSet,) で、呼ば れる
実行 _MyHomePageStateの全プロパティがExportさ れている。
main.dart • JS側にExportするメソッドに@JSExportアノ テーションをつける。 ◦ 指定したメソッドのみ JS側にExportされる ◦ @JSExport(‘foo’) と名前を指定すると、
JSからそ の名前でExportする。 //@js.JSExport() //コメントアウト class _MyHomePageState extends State<MyHomePage> { int _counter = 0; @override void initState() { super.initState(); // _MyHomePageStateオブジェクトを、JS側にExportする final export = js_util.createDartExport(this); // JS側の globalThis(ブラウザの場合は、window)に プロパティ (_appState)、値 (export)をセットする。 js_util.setProperty(js_util.globalThis, '_appState', export); // JS側の globalThisの_stateSetメソッドを引数無しで呼び出す。 js_util.callMethod<void>(js_util.globalThis, '_stateSet', []); } @js.JSExport('inc') // inc という名前でExport void _incrementCounter() {
実行 incメソッドのみExportされている。
HTML/JSからFlutterのコードを呼ぶ HTML/JSから、Flutterのカウンター値を増加させる。
main.dart • JS側にExportするメソッドに @js.JSExportアノテーションをつ ける • callback関数を受け取るメソッドも 特殊なことはしない。 // @js.JSExportしない
class _MyHomePageState extends State<MyHomePage> { @js.JSExport() void _incrementCounter() { setState(() { _counter++; // 変更を通知 _streamController.add(null); }); } @js.JSExport() int get count => _counter; // callback関数を受け取る関数を Exportする @js.JSExport() void addHandler(void Function() handler) { _streamController.stream.listen((event) { handler(); }); }
index.html • カウンター機能を追加 ◦ カウンター値表示 ◦ インクリメントボタン <section class="contents"> <aside
id="demo_controls"> <fieldset id="interop"> <legend>JS Interop</legend> <!--カウンター値を表示 --> <label for="value"> Value <input id="value" value="" type="text" readonly /> </label> <!--インクリメントボタン --> <input id="increment" value="Increment" type="button" /> </fieldset> </aside> <article> <!-- 1. flutterアプリを表示するHTMLエレメント --> <div id="flutter_target" class="center"></div> </article> </section>
js/js-interop.js • インクリメントボタンを押したら、 Flutterの_incrementCounter()を 呼び出す。 • Flutterのカウンタが更新したら、 updateStateがコールバックされ る。 (function
() { window._stateSet = function () { // js_util.setProperty() でセットした、_appStateプロパティの取得 const appState = window._appState; // インクリメントボタンのHTMLエレメント取得 const incrementButton = document.querySelector("#increment"); incrementButton.addEventListener("click", (event) => { // Flutterの_MyHomePageState._incrementCounter()の呼び出し appState._incrementCounter(); }); // カウンター値表示エリアの HTMLエレメント取得 const valueField = document.querySelector("#value"); const updateState = function () { // Flutterの_MyHomePageState.count の呼び出し valueField.value = appState.count; }; updateState(); // Flutterの_MyHomePageState.addHandlerを呼び出す。 // callback関数 updateStateを与える。 appState.addHandler(updateState); }; }());
実行
まとめ • FlutterをHTML elementに埋め込める。 • FlutterとHTML/JS間でインタラクションが簡単に
まとめ • FlutterをHTML elementに埋め込める。 • FlutterとHTML/JS間でインタラクションが簡単に • しかしながら、実プロダクトで利用するには時期尚早 ◦ Reactアプリに埋め込む場合、実際には大変。ドキュメントが必要だが、まだない。
▪ 参照 https://github.com/flutter/flutter/issues/123940 ◦ JSからDartのAsync関数を呼べない。 ▪ 参照 https://tinyurl.com/29c7fb8c • おまけ ◦ 今日見せたコード:https://github.com/kenmasumitsu/flutter-web-enbedding