質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
ウェブブラウザ

ウェブブラウザ(インターネットブラウザ)とは、www上に公開されている情報リソースをユーザーに視覚的提供・操作させる機能を持ったソフトウェアプログラムです。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

739閲覧

Rustでicedクレートを使い、Wasmとしてコンパイルしブラウザで開いたところ、画面が初めから表示してくれない

akira_kano1101

総合スコア25

ウェブブラウザ

ウェブブラウザ(インターネットブラウザ)とは、www上に公開されている情報リソースをユーザーに視覚的提供・操作させる機能を持ったソフトウェアプログラムです。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2022/11/20 03:26

編集2022/11/21 02:45

前提

Rustでicedクレートを使い、wasmとしてコンパイルしブラウザで実行させるプログラムを作ろうと思い、最小構成で動作を確認するプログラムを試しています。

後述のコマンドを実行するとコンパイルが通ることを確認し、ブラウザでも表示することに成功しました。

ただ一つ思うようにならない問題が残りました。

それは初期表示です。

ブラウザにアクセスしただけではプログラムがその時点ではまだ動作していないのかブラウザ画面に表示してくれません。

ブラウザの画面にマウスオーバーさせないと最初の表示がされないということが今回問題にしているところなのです。

実現したいこと

ブラウザを開いた時点で、ユーザーがマウスオーバーのアクションをする必要なく最初からicedの画面が表示されているようにしたいです。

発生している問題・エラーメッセージ

実行時のブラウザとコンソールログのアクセスして初期の状態は下図です。
イメージ説明

このブラウザがアクティブな状態でマウスカーソルをブラウザの画面上で動かすと下図のようになります。
イメージ説明

問題としてはユーザがページにアクセスした時点でマウスオーバーするまで初期画面が表示されていないためおかしいと勘違いしてしまう可能性があります。

該当のソースコード

iced_webを参考にコマンドスクリプトとindex.htmlを作成/実行しました。

試したこと

icedクレートのソースコードをGitHubリポジトリからローカルにcloneしました。

console

1% git clone git@github.com:iced-rs/iced.git

ディレクトリを変更します。

console

1% cd iced/examples/

iced/examples/index.htmlを下記のように作成しました。

html

1% cat index.html 2<!DOCTYPE html> 3<html> 4 <head> 5 <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 <title>Tour - Iced</title> 8 </head> 9 <body> 10 <div id="wasm"> 11 <script type="module"> 12 import init from "./tour/tour.js"; 13 14 init("./tour/tour_bg.wasm"); 15 </script> 16 </div> 17 <script type="text/javascript"> 18 window.onload = function() { 19 triggerEvent(document.getElementById("wasm"), "mouseover"); 20 } 21 22 function triggerEvent(element, event) { 23 if (document.createEvent) { 24 var evt = document.createEvent("HTMLEvents"); 25 evt.initEvent(event, true, true); 26 return element.dispatchEvent(evt); 27 } else { 28 var evt = document.createEventObject(); 29 return element.fireEvent("on"+event, evt) 30 } 31 } 32 console.log("動いています"); 33 </script> 34 </body> 35</html>

iced/examples/build.shを下記のように作成しました。

shell

1% cat build.sh 2cd `dirname $0` && 3 cargo build --package tour --target wasm32-unknown-unknown && 4 wasm-bindgen ../target/wasm32-unknown-unknown/debug/tour.wasm --out-dir tour --web && 5 python -m http.server 8080

その後作成したスクリプトを実行します。

console

1% chmod +x build.sh 2% ./build.sh

上記実行後にブラウザでlocalhost:8080にアクセスし、ブラウザの画面の白い部分にマウスカーソルを持っていくとサンプルが始まることが確認できます。

ここでマウスカーソルを持っていかないと始まらないことが問題です。

これを踏まえた上で、マウスカーソルを動かすイベントをjavascriptで発生させれば良いのではと思い、次のサイトを参考にうまくいくかなと思いつつ試しました(追加のコードは前述のindex.htmlに含めさせていただいています)。

Javascript 無理にmouseoverを発火させる

ただ私が独自に追記したconsole.logで、出力されるはずの"動いています"というログが出ないのでこれは動いていない可能性もあってよく理由がわかっていません。
※クォーテーションが全角だったため動作しておらず出力されていなかったことに気づいたため修正しました。"動いています"は出力されるようになりました。しかし初期画面が真っ白なことに変わりはありません。

補足情報(FW/ツールのバージョンなど)

version

1% $SHELL --version 2zsh 5.8.1 (x86_64-apple-darwin22.0) 3% python --version 4Python 3.10.4 5% cargo --version 6cargo 1.65.0 (4bc8f24d3 2022-10-20)

ブラウザはFirefoxを使っています。

解決方法、ご存知の方いらっしゃいましたら、ご教示のほどよろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

一応力技でどうにかできる手法は見つけたんですが、絶対に迷走している気がします。公式のissueで聞いてみたほうがいいかもしれません(面倒で探していない)。pointeroverイベントを発火させてます。
ただし、onloadだとまだcanvasがいないようなので、DOMNodeInsertedを捉えてます。canvasを拾えたらこれ以上イベントを拾わないようにremoveEventListenerで解除してます。

ref: 【JavaScript】addEventListenerの無名関数をremoveEventListenerで消す方法 | Web活

なおinitEventはMDNをみるとわかるようにdeprecatedになっていて、単にdispatchEventにイベントコンストラクタの呼び出し結果を渡せば良いです。

html

1<!DOCTYPE html> 2<html> 3 <head> 4 <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <title>Tour - Iced</title> 7 </head> 8 <body> 9 <script type="module"> 10 import init from "./tour/tour.js"; 11 12 init('./tour/tour_bg.wasm'); 13 function ready(loaded) { 14 if (['interactive', 'complete'].includes(document.readyState)) { 15 loaded(); 16 } else { 17 document.addEventListener('DOMContentLoaded', loaded); 18 } 19 } 20 ready(() => { 21 function eventListener() { 22 const canvas = document.querySelector("canvas"); 23 if (canvas == null) { 24 console.error("cannot find canvas"); 25 return; 26 } 27 canvas.dispatchEvent(new PointerEvent('pointerover')); 28 document.body.removeEventListener('DOMNodeInserted', eventListener); 29 }; 30 document.body.addEventListener('DOMNodeInserted', eventListener); 31 }); 32 </script> 33 </body> 34</html>

投稿2022/11/29 17:12

編集2022/11/29 17:16
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akira_kano1101

2022/11/29 21:55

sumomoneko様 ご回答ありがとうございます。 確かに動きますね! JSで何かやり方がありそうと思っていましたが、やはりイベントリスナーでしたか。 私ももう少し調査と検証を続けたいと思います。 ところで今回、なぜicedを選んだかというと、Commandのperformで非同期処理ができるからという理由でした。 本当はeguiでやりたかったのですが、デフォルトで非同期処理をする機能がなかったからです。 しかし、なんとかeguiで非同期処理をさせる良い方法はないか探っていたらeguiと関係ないところでしたが`wasm_bindgen_futures`という良さそうなクレートを発見しました。こちらも今試してみているところです。色々と引っかかる部分はあるように感じていますが、これとeguiの`request_repaint_after`を組み合わせて使うなどすると、どうやらいけるかもしれません。 あとこの質問の本題ですが、ちょっとicedの本家で対応してくれるようアクションしてみることにします。 ご回答くださりとても嬉しいです。ありがとうございました。 またお世話になる際は、よろしくお願いします。
sumomoneko

2022/12/01 04:53

おっと、回答自体はyumetodoさんです。お礼をリダイレクトしておきますね > yumetodo
akira_kano1101

2022/12/03 12:31

yumetodo様 sumomoneko様 大変失礼しました。それでも、お二人には感謝したいのでここで伝えます。 今回の件に関してリアクションくださり、どうもありがとうございました。 またお世話になることがあればよろしくお願いします。
yumetodo

2022/12/14 16:21

今更ですがIssueの提示ありがとうございます、ここのと同じworkaroundをおいてきました・・・。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問