LoginSignup
3
3

More than 1 year has passed since last update.

PlayCanvasでモデルがクリックされたときにHTMLの表示を切り替える方法

Last updated at Posted at 2020-06-30

PlayCanvasとHTMLを組み合わせる

PlayCanvasとHTMLを組み合わせる方法について紹介をします。

PlayCanvasは特性上、エディターを使用した開発でHTMLを触ろうとすると少し癖があります。JavaScriptのフレームワークと組み合わせることで解消も可能だったりもします。

一例
playcanvas-next-test

PlayCanvas界隈では様々な方法が試されていると思いますがその中で自分が、メンテナンス性などのも考えて、使いやすかったものを紹介します。

今回はPlayCanvasの基本的な説明は省いています。

今回作るもの

このような3Dモデルが並んでいるページで、モデルがクリックされたらHTMLの表示を切り替えるものを作ります。

例: https://playcanv.as/p/9uV03p1Y/

モデルがクリックされたらモデルの情報をDOMを切り替えるものになります。
  
(モデルはサンディちゃんを使用しています。)

HTMLを組み込む

PlayCanvasのエディター上でHTML, CSSを組み込む

HTMLを組み込むためにそれぞれのスクリプトを追加します。
こちらは様々な方法があるかと思いますが、insertAdjacentHTMLを使用してHTMLを組み込みます。

1. ui.js index.html, style.cssを作成する

ui.js
const Ui = pc.createScript("ui");

Ui.attributes.add("css", {
  type: "asset",
  assetType: "css",
  title: "CSS Asset"
});
Ui.attributes.add("html", {
  type: "asset",
  assetType: "html",
  title: "HTML Asset"
});

Ui.prototype.initialize = function() {
  const body = document.getElementsByTagName("body")[0];
  const head = document.getElementsByTagName("head")[0];
  const style = `<style>${this.css.resource}</style>`;
  body.insertAdjacentHTML("beforebegin", this.html.resource);
  head.insertAdjacentHTML("afterbegin", style);
};
index.html
<div class="container">
    <h2 class="title">タイトル</h2>
    <h2 class="url">URL</h2>
    <img class="image" />
</div>
style.css
.container{
    position: absolute;

    background-color: white;
    z-index:1;
}

.container img{
    object-fit: cover;
    width:300px;
    height:300px;
}

スクリプトにCSSHTMLを追加する

Rootのエンテティにui.jsを追加します。追加ができたら、style.cssindex.htmlを設定します。

スクリプト属性
スクリプトのアトリビュート機能は、スクリプト内で使用する変数をPlayCanvasエディタ内で編集することができるようにする便利な機能です。この機能を使うことで、一度コードを書いた後にエンティティごと作られるインスタンスにそれぞれ違うパラメータを設定する調整ができるようになります。これにより、アーティスト、デザイナーやその他のプログラマーではないチームメンバーがコードを書かずに値を変更できるにプロパティを露出させることができます。
https://developer.playcanvas.com/ja/user-manual/scripting/script-attributes/

情報を保持するためのスクリプトを追加

次に、各モデルに、クリックされた時の情報を追加します。

info.jsを作成

info.jsとしてスクリプトを作成します。
このスクリプトの役割は、プログラムを変更せずに変更できる値を保存しておくために存在しています。

info.js
/*jshint esversion: 6, asi: true, laxbreak: true*/
const Info = pc.createScript('info');
Info.attributes.add("title", {"type": "string", default: "example"})
Info.attributes.add("url", {"type": "string" , default: "https://example.com"})
Info.attributes.add("image", {"type": "asset"})

スクリプトを適用する

スクリプトを追加すると、それぞれtitleurlimageと値を設定できるようになります。クリックされたときにはエンテティのこの値を使用して表示を切り替えるようにします。

クリックされたときに値を切り替えるスクリプトを追加

最後にクリックされたときに情報を切り替えるためのスクリプトを追加します。
こちらはCAMERAコンポーネントを持っている持っているエンテティに追加します。

マウスが押されたときに、直接DOMの切り替えを行なっています。

picker-raycast.js
/*jshint esversion: 6, asi: true, laxbreak: true*/

const PickerRaycast = pc.createScript('pickerRaycast');

// initialize code called once per entity
PickerRaycast.prototype.initialize = function() {
    
    // マウスがクリックされたときに、onSelect関数を実行します
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.onSelect, this);
};

PickerRaycast.prototype.onSelect = function (e) {
    const from = this.entity.camera.screenToWorld(e.x, e.y, this.entity.camera.nearClip);
    const to = this.entity.camera.screenToWorld(e.x, e.y, this.entity.camera.farClip);
    
    // クリックされた位置にエンティティがあれば result.entityにentityの情報が入ります
    const result = this.app.systems.rigidbody.raycastFirst(from, to);
     
    if (result) {
        const entity = result.entity;
        // entityにinfoというスクリプトが含まれているかを調べます。
        if(entity.script && entity.script.hasOwnProperty('info')){
        
        // title: string
        // スクリプト名 infoの属性 titleを参照します
        const title = entity.script.info.title
        
        // url: string
        // スクリプト名 infoの属性 url
        const url = entity.script.info.url

        // image: Asset
        // スクリプト名 infoの属性 imageを参照します
        // imageのtypeはAssetなので、getFileUrl()関数を使用してAssetのURLを参照します。
        const image = entity.script.info.image
        const imageUrl = image.getFileUrl()
        
        // ui.jsで追加したHTMLの要素を取得します
        const titleElement = document.getElementsByClassName("title")[0]
        const urlElement = document.getElementsByClassName("url")[0]
        const imgElement = document.getElementsByClassName("image")[0]
        
        // HTMLの要素を書き換えます
        titleElement.textContent = title
        urlElement.textContent = url
        imgElement.src = imageUrl
        }    
    }
};

感想

すべてのモデルで決まった値を表示したい場合にはこちらの方法を使うことで表示を切り替えることができます。
ただ、複雑に切り替わる場合などには向いていないためシンプルに実装したいときに使っております。

今回のプロジェクトで質問や意見がありましたら。@mxcn3まで連絡をお願いします。

PlayCanvas開発で参考になりそうな記事の一覧です。 入門 応用 その他の記事はこちらになります。 その他関連 - [PlayCanvasタグの付いた記事一覧](https://qiita.com/tags/playcanvas)

PlayCanvasのユーザー会のSlackを作りました!

少しでも興味がありましたら、ユーザー同士で解決・PlayCanvasを推進するためのSlackを作りましたので、もしよろしければご参加ください!

日本PlayCanvasユーザー会 - Slack

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3