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
580
Other Decks in Programming
See All in Programming
スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜
atsuki_seo
0
100
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
140
Security issues being discussed on Web Platforms
petamoriken
0
900
Webの地図
yosuke_furukawa
PRO
6
4.4k
AIは賢い。でも実行環境は? CLIおじさんがAI時代に伝えたいこと ~ CLIおじさんがAI時代に伝えたいこと ~
curekoshimizu
1
240
Java 27新機能 / Java 27 new features
kishida
2
130
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.1k
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
190
AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す
theoriatec2024
1
490
AGENTS.md Is Not Enough:Build Skills, Don't Download Them
lx_t
0
110
cdk deploy JawsSonic #MARATHONしながらAWSリソースをデプロイしてみよう
akihisaikeda
2
130
更なる可用性を求めて、5年間運用したKotlinのアプリケーションをGoでリプレイスする話
ken_tunc
0
160
Featured
See All Featured
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
840
The browser strikes back
jonoalderson
0
1.7k
How to Talk to Developers About Accessibility
jct
2
550
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.8k
How STYLIGHT went responsive
nonsquared
100
6.3k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
49
10k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
500
Why Our Code Smells
bkeepers
PRO
340
58k
Optimizing for Happiness
mojombo
378
71k
Facilitating Awesome Meetings
lara
57
7.1k
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