Quantcast
Channel: CSSタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8925

チュートリアル - Vue.jsでPlayCanvas製3Dモデルビュワーサイトを作る 4 / 4

$
0
0

前回はVue.jsでモデルを切り替えたりTweenを入れて動かしたりするまで行いました。
次は各モデルごとに詳細ページを作っていきたいと思います。

3Dモデルごとに詳細ページを作る

選択した3Dモデルごとに対応したDOMを表示させるようにします。

まずは3Dモデルの各Entityに載せたい情報が入ったHTMLを登録していきます。

今回は私の方で用意したHTMLを追加します。
中の記述は任意で変更してみてください。

[content01.html]

<article><h1class="color-base">3Dモデルビュワー01</h1><p>杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー杏マナー</p></article><article><h2class="color-base">プリミティブでも綺麗なものは作れる</h2><divclass="tableWrap"><table><tbody><tr><thclass="bgcolor-sub-5">Primitive</th><td>Box/Sphere</td></tr><tr><thclass="bgcolor-sub-5">Material</th><td>None</td></tr><tr><thclass="bgcolor-sub-5">Collision</th><td>0On</td></tr><tr><thclass="bgcolor-sub-5">RighidBody</th><td>On</td></tr></tbody></table></div></article><article><h3>プリミティブでも良いところはある</h3><ul><li><spanclass="color-base">プリミティブだから</span></li><ul><li><span>軽い</span></li><li><span>見栄えは気にしちゃいけない</span></li></ul></ul><ol><li><span>モデリングができなくても…</span></li><li><span>プリミティブでも頑張ろう…</span></li></ol></article><article><h2>宣伝</h2><p><ahref="https://pcpo.sabo.jp/3dwebsite/"target="_blank"><spanclass="color-base">3DWebSite</span></a><span>というPlayCanvas運営事務局が作った3DのWebサイト</span><br><span>その3DWebSiteが</span><ahref="https://webgl.souhonzan.org/entry/?v=1588"target="_blank"><spanclass="color-base">WebGL総本山</span></a><span>で紹介していただきました!</span></p></article><article><dl><dt>PlayCanvas運営事務局</dt><dd>キドユウタ</dd></dl></article>

切り替えた時に中のHTMLがちゃんと切り替わっているか判断しやすくするために、HTMLは複数作っておきます。
8E5577C0E75192DD24E3CA6408E41423.png

念の為、中の文章を変更するなどしておくと良いです。
758C54CCCE6B223844B68126749072AC.png

作成したHTMLをそれぞれEntityに当てはめて行きます。
そのために、当てはめる用のjsを作成します。

HTMLを追加するためだけなので、属性設定に登録できるようにします。

[addhtml.js]

varAddhtml=pc.createScript('addhtml');Addhtml.attributes.add("sethtml",{type:"asset",assetType:"html"});Addhtml.prototype.initialize=function(){};Addhtml.prototype.update=function(dt){};

該当Entityを選択して、ADD COMPONENTからScriptsを選択。
ADD SCRIPTから先ほど作成したaddhtml.jsを登録し、ParseしてからHTMLを登録します。

7D0BF2BF54FB39F095BF99773DDC6203.png

同じjsをテンプレート化して使いまわしたいというやり方がPlayCanvasのEditorではできます。
各々のEntityに登録ができるので、開発も少し楽ができますね。

index.jsに戻りまして、先ほど登録したHTMLを取得してVueを使ってindex.htmlに流し込みます。
ます、どのデータに登録したHTMLが入っているのか探す必要があります。

ここで以下のコードをindex.jsの一番下に追加します。

[index.js]

Index.prototype.swap=function(old){for(vark=0;k<old.target.children.length;k++){console.log(old.target.children[k]);}};

swapというのは、このscriptがホットリロードされた時に呼び出します。
Lauchをリロードせずともscriptで使いたい情報を探すのに活用できます。

ここで参照しているのは、Entitiesの子要素であるEntityを参照しています。
子要素のEntityの属性に取得したいHTMLが入っているのでこれを探します。

すると以下にたどり着けると思います。

[index.js]

Index.prototype.swap=function(old){for(vark=0;k<old.target.children.length;k++){console.log(old.target.children[k].script.addhtml.__attributes.sethtml._resources[0]);}};

これを使って追加していきます。
先ほどswapで確認したやり方を使ってHTMLのソースを取得し、それをVueに渡してあげます。

以下をコピペして書き換えます。書き加えたのは17-20行目と27行目です。

[index.js]

varIndex=pc.createScript('index');Index.attributes.add("baseHtml",{type:"asset",assetType:"html"});// 登録したhtmlを取得Index.attributes.add("target",{type:"entity"});// 参照するEntityを登録Index.prototype.initialize=function(){varself=this;// this書き換えvarcanvas=document.getElementsByTagName("canvas")[0];// canvasを取得canvas.classList.add("pcCanvas");// canvasにclass名を指定varwrapper=document.createElement("div");// div作成wrapper.classList.add("wrapper");// 作成したdivにwrapperというclass名を指定wrapper.innerHTML=self.baseHtml._resources[0];// 事前に登録していたhtmlをwrapperに流し込みdocument.body.appendChild(wrapper);// bodyにwrapperを追加varnowEntity="";// どのEntityが選択されているか保管vart_htmls={};// htmlを保管for(vark=0;k<self.target.children.length;k++){// Entitiesの子要素に登録されたHTMLを参照t_htmls[k]=self.target.children[k].script.addhtml.__attributes.sethtml._resources[0];// 登録されたHTMLのソースを取得}varapp=newVue({// Vue呼び出しel:'#app',// id名がappの要素を参照data:{// 使用するdataを登録clickFlag:false,// クリックされたかentities:self.target.children,// 属性で追加したEntityの子どもを参照contents:t_htmls// HTMLをVueに渡す},methods:{// イベントハンドラ作成onEntityClick:function(target,index){// Entityを選択された時varv_self=this;// thisを保管if(v_self.clickFlag)return;// クリックされて処理中かv_self.clickFlag=true;// クリック処理中self.target.tween(self.target.getLocalRotation()).rotate(newpc.Vec3(180,0,0),0.5,pc.QuadraticIn).on('complete',function(){// tweenでrotateをアニメーション completeで完了後呼び出しif(nowEntity){// Entityが保管されているかnowEntity.enabled=false;}target.enabled=true;// 選択したEntityを表示nowEntity=target;// 選択したEntityを保管self.target.tween(newpc.Vec3(180,0,0)).rotate(newpc.Vec3(360,0,0),1,pc.BounceOut).on('complete',function(){v_self.clickFlag=false;}).start();// 選択したEntityのアニメーション}).start();}}});};Index.prototype.swap=function(old){for(vark=0;k<old.target.children.length;k++){console.log(old.target.children[k].script.addhtml.__attributes.sethtml._resources[0]);}};

Vueに追加したcontentsにHTMLのソースが入っているので、これをindex.htmlに追加します。

以下にコピペして書き換えます。
14行目に先ほどのcontentsを展開して挿入しています。

[index.html]

<divid="app"><headerclass="header"><nav><ol><liv-for="(entity,index) in entities"@click="onEntityClick(entity,index)"><span>{{entity.name}}</span></li></ol></nav></header><mainclass="main"><divclass="container"><sectionv-for="(content,index) in contents"v-html="content"></section></div></main></div>

Launchからディベロッパーツールで確認してみますと、section要素に先ほどのHTMLが追加されているのが確認できると思います。

FD5FD5D5C71FD782A173D5DA5BAB2F20.png

表示するためのHTMLも追加できましたので、
次に詳細ページに切り替えるための処理を書いていきます。

詳細ページへの切り替えなどの処理を作る

各々の詳細が書いてあるHTMLを追加できたので、それを表示するための処理を作っていきます。

選択したEntityから詳細ページへ行くためのボタンを用意します。
また、詳細ページから前のページに戻るためのボタンも用意します。

[index.html]

<divid="app"><headerclass="header"><nav><ol><liv-for="(entity,index) in entities"@click="onEntityClick(entity,index)"><span>{{entity.name}}</span></li></ol></nav></header><divclass="detailBtn"v-show="detailBtnShow"@click="onDetailClick()"></div><mainclass="main"><divclass="closeBtn"@click="onCloseClick()"></div><divclass="container"><sectionv-for="(content,index) in contents"v-show="sectionNum == index"v-html="content"></section></div></main></div>

detailBtnとcloseBtnを追加すると合わせて、この後行うクリックイベントとv-showという表示非表示を処理するための記述も書いています。
これらを使うために、index.jsに処理を書いていきます。

index.jsのVueの箇所を以下に書き換えます。

[index.js]

varapp=newVue({// Vue呼び出しel:'#app',// id名がappの要素を参照data:{// 使用するdataを登録clickFlag:false,// クリックされたかdetailFlag:false,// 詳細を表示しているかdetailBtnShow:false,// 詳細ボタンを表示しているかentities:self.target.children,// 属性で追加したEntityの子どもを参照contents:t_htmls,// HTMLをVueに渡すsectionNum:"",// 何個目のEntityが表示されているか},methods:{// イベントハンドラ作成onCloseClick:function(){// 詳細を閉じるdocument.body.classList.remove("is-open");detailFlag=false;},onDetailClick:function(target){// 詳細を表示detailFlag=true;document.body.classList.add("is-open");},onEntityClick:function(target,index){// Entityを選択された時varv_self=this;// thisを保管if(v_self.clickFlag)return;// クリックされて処理中かif(!v_self.detailBtnShow)v_self.detailBtnShow=true;// 詳細ボタンを表示(初回のみ)v_self.clickFlag=true;// クリック処理中this.sectionNum=index;// 何個目のEntityが表示されているかself.target.tween(self.target.getLocalRotation()).rotate(newpc.Vec3(180,0,0),0.5,pc.QuadraticIn).on('complete',function(){// tweenでrotateをアニメーション completeで完了後呼び出しif(nowEntity){// Entityが保管されているかnowEntity.enabled=false;}target.enabled=true;// 選択したEntityを表示nowEntity=target;// 選択したEntityを保管self.target.tween(newpc.Vec3(180,0,0)).rotate(newpc.Vec3(360,0,0),1,pc.BounceOut).on('complete',function(){v_self.clickFlag=false;}).start();// 選択したEntityのアニメーション}).start();}}});

onDetailClickとonCloseClickのイベントハンドラを作成しています。
ここで詳細の表示非表示を行いますが、その表示非表示はclass名を参照しています。
htmlのbody要素に特定のclass名を持つときにCSSを使って表示非表示するようにしました。
v-showを使うことでもできなくはないですが、アニメーションを含めるならCSSが簡単と思いましてこちらを採用しています。

これで3Dモデルビュワーは完成していますが、もう一点、スマホ対応もさせておきたいと思います。

index.htmlとindex.jsのVueの箇所を以下に書き換え

[index.html]

<divid="app"><divclass="navBtn"@click="onNavClick()"></div><headerclass="header"><nav><ol><liv-for="(entity,index) in entities"@click="onEntityClick(entity,index)"><span>{{entity.name}}</span></li></ol></nav></header><divclass="detailBtn"v-show="detailShow"@click="onDetailClick()"></div><mainclass="main"><divclass="closeBtn"@click="onCloseClick()"></div><divclass="container"><sectionv-for="(content,index) in contents"v-show="sectionNum == index"v-html="content"></section></div></main></div>

[index.js]

varapp=newVue({// Vue呼び出しel:'#app',// id名がappの要素を参照data:{// 使用するdataを登録clickFlag:false,// クリックされたかnavFlag:false,// スマホ時のメニュー表示しているかdetailFlag:false,// 詳細を表示しているかdetailBtnShow:false,// 詳細ボタンを表示しているかentities:self.target.children,// 属性で追加したEntityの子どもを参照contents:t_htmls,// HTMLをVueに渡すsectionNum:"",// 何個目のEntityが表示されているか},methods:{// イベントハンドラ作成onNavClick:function(){//メニューボタン押すif(!this.navFlag){// メニュー表示this.navFlag=true;document.body.classList.add("is-nav");}else{// メニュー非表示this.navFlag=false;document.body.classList.remove("is-nav");}},onCloseClick:function(){// 詳細を閉じるdocument.body.classList.remove("is-open");detailFlag=false;},onDetailClick:function(target){// 詳細を表示detailFlag=true;document.body.classList.add("is-open");},onEntityClick:function(target,index){// Entityを選択された時varv_self=this;// thisを保管document.body.classList.remove("is-nav");if(v_self.clickFlag)return;// クリックされて処理中かif(!v_self.detailBtnShow)v_self.detailBtnShow=true;// 詳細ボタンを表示(初回のみ)v_self.clickFlag=true;// クリック処理中this.sectionNum=index;// 何個目のEntityが表示されているかself.target.tween(self.target.getLocalRotation()).rotate(newpc.Vec3(180,0,0),0.5,pc.QuadraticIn).on('complete',function(){// tweenでrotateをアニメーション completeで完了後呼び出しif(nowEntity){// Entityが保管されているかnowEntity.enabled=false;}target.enabled=true;// 選択したEntityを表示nowEntity=target;// 選択したEntityを保管self.target.tween(newpc.Vec3(180,0,0)).rotate(newpc.Vec3(360,0,0),1,pc.BounceOut).on('complete',function(){v_self.clickFlag=false;}).start();// 選択したEntityのアニメーション}).start();}}});

navBtnという要素を追加して、onNavClickのイベントハンドラを呼ぶことでスマホ時でもメニューを開いて操作することができます。
ここでもbody要素にclass名のis-navを付与することでメニューの表示非表示を制御しています。
他にも色んな方法はありますので、試してみると良いでしょう。

これで、本チュートリアルの制作は終了です。

最後に今回作ったプロジェクトをPublishして終わりにしたいと思います。

Publishして誰でも見れるように公開!

プロジェクトを作成してビルドまでやってくれるのもPlayCanvasのすごいところ。

ここまで作成したものをPlayCanvasの公開環境に公開してみましょう。

左のメニュー、またはシーンの左上のManage Scenesから以下のPublish画面を開きます。
B3EAE2C667F0D901564A3E07AA17C432.png

PUBLISH TO PLAYCANVASを選択して、一番下のPUBLISH NOWをクリックしてビルドは完了です。
URLでPC、スマホ、他ユーザーにもログインすることなく共有することができます。
6CC3E7B70E347147E79D8F137A479F5B.png

以上でチュートリアルの終了です。
おつかれさまでした!


PlayCanvasはゲームエンジンでありますが、こんな感じでwebサイト的なものとして使えちゃいます。
WebGLで3Dコンテンツを使いたいけどうまく扱えない人とかにはとても良いものな気がします。

PlayCanvas、使いましょう!

-


Viewing all articles
Browse latest Browse all 8925

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>