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

チュートリアル - 3D空間を使った簡単webサイト 4/5

$
0
0

前回

3Dオブジェクトに応じたHTMLのページを表示させる

マウスからイベントが取得できたので、クリックしたらHTMLを表示するようにします。

予めAssetsにmarkupというディレクトリ内に使用されるhtmlとcssのサンプルがあります。
事前にサンプルを用意していますが、作る際には自分のローカルで作成する必要があるのでご注意ください。

今回は3つの3Dオブジェクトと3つのhtmlを関係を持たせて、
「3Dオブジェクトがクリックされたら、それにリンクするhtmlが表示される」 までを作ります。

ここで使用するscriptはaddhtml.jsですが、これもまたEntityにADD SCRIPTする必要があります。
使用するaddhtml.jsは特定のEntityにADD SCRIPTする必要はありません。
今回はcharaというグループのEntityにADD SCRIPTします。

スクリーンショット 2019-07-10 20.13.04.png

addhtml.jsをADD SCRIPTしたら、コードエディターを開きます。

以下のコードを追加します。

Addhtml.attributes.add("css",{type:'asset',assetType:'css',title:'CSS Style'});// アセットのcss読み込みAddhtml.attributes.add("header",{type:'asset',assetType:'html',title:'HTML Header'});// アセットのhtmlのheader読み込みAddhtml.attributes.add("scene1",{type:'asset',assetType:'html',title:'HTML Scene1'});// アセットのhtmlのscene1読み込みAddhtml.attributes.add("scene2",{type:'asset',assetType:'html',title:'HTML Scene2'});// アセットのhtmlのscene2読み込みAddhtml.attributes.add("scene3",{type:'asset',assetType:'html',title:'HTML Scene3'});// アセットのhtmlのscene3読み込み

早速、markupディレクトリのファイルを登録していきます。

下のアセットからmarkupというディレクトリに登録するファイルがあります。

スクリーンショット 2019-07-10 20.16.05.png

スクリーンショット 2019-07-31 12.19.50.png

htmlとcssを登録していきます。

登録したコードを追加するために

とのエレメントを取得する必要があります。
なぜ取得するのかというと、取得したheadやbodyに対して、appendChild()やinnerHTML、insertAdjacentHTML()などでhtmlを追加するからです。

以下のコードを追加していきます。

varcontainer;Addhtml.prototype.initialize=function(){// initvarhtmlNameArr=[];// attributesのデータの名前を配列にしますvararrIndex=Addhtml.attributes.index;for(vari=0;i<Object.keys(arrIndex).length;i++){// attributesのデータを取得してfor文で回すif(!Object.keys(arrIndex)[i].indexOf("scene")){// 名前にhtmlが入っているデータをif文htmlNameArr.push(Object.keys(arrIndex)[i]);// htmlデータの名前だけ配列化する}}varhead=document.getElementsByTagName("head")[0];// headタグ取得varbody=document.getElementsByTagName("body")[0];// bodyタグ取得varwrapper=document.createElement("div");// DOMを囲う要素を作成wrapper.className="wrapper";// クラス名指定body.appendChild(wrapper);// bodyタグの最後に要素を追加container=document.createElement("main");// DOMを囲う要素を作成container.className="container";// クラス名指定wrapper.appendChild(container);// bodyタグの最後に要素を追加varstyle=document.createElement("style");// cssのstyleタグwrapper.insertAdjacentHTML("afterbegin",this.header.resource);// attrで追加したヘッダーを追加style.append(this.css._resources[0]);head.appendChild(style);// headの最後にstyleを追加for(vari=0;i<htmlNameArr.length;i++){// htmlのアセットを配列管理するためにfor文でattrの名前の配列を回すcontainer.insertAdjacentHTML("beforeend",this[htmlNameArr[i]].resource);// アセットから取得したhtmlを追加}};

これでhtmlとcssの情報を追加できました。
headの中にcssのスタイルが入り()、bodyの中にhtmlの要素が入っています。

スクリーンショット 2019-06-20 18.05.48.png

次にオブジェクトをクリックしたらそれに連動したhtmlを表示するやり方です。

attributesで登録したhtmlでscene1、scene2、scene3とありました。
この数字を3Dオブジェクトとの関係性に使います。

Editorから3DオブジェクトのModelを選択し、インスペクターからTagsを登録します。
tagの名前は任意のもので大丈夫です。数字をそれぞれに入れるのを忘れないように。

スクリーンショット 2019-06-20 18.11.03.png

登録したtagをクリックした時に取得できるか確認します。
hotspot.jsのdoRayCastでtagを確認します。

Hotspot.prototype.doRayCast=function(screenPosition){// レイキャスト処理(ある地点から特定方向に直線で線を引いて、その線上で物体があるか検知する処理)if(this.hitArea.intersectsRay(this.ray)){// ヒットエリアとレイが交差した場合console.log("click!! : ",this.entity.tags._list[0]);}};

クリックした3Dオブジェクトから各々のtagが取得できたと思います。
これを使ってhtmlとリンクさせます。

addhtml.jsに以下を追加します。

globalPc={};// グローバルな変数(オブジェクト)Addhtml.prototype.update=function(dt){// updateif(Number(globalPc.scene)>0){// いずれかのsceneが選択されている場合if(!container.classList.contains("is-open")){// 追加したアセットのhtmlにis-openのclassが追加されていない場合(どのhtmlも表示されていない)container.classList.add("is-open");// is-openのclass名をcontainerに追加varsectionElements=document.getElementsByClassName("section");// sectionを取得for(vari=0;i<sectionElements.length;i++){// sectionをループ処理if(sectionElements[i].classList.contains("is-current")){// sectionにis-currentのclass名を持つかif処理sectionElements[i].classList.remove("is-current");// is-currentを削除}}sectionElements[globalPc.scene-1].classList.add("is-current");// 選択されたsceneにis-currentのclass名を追加document.getElementsByClassName("section_close")[globalPc.scene-1].addEventListener("click",btnClose,false);// 選択されたsceneの閉じるボタンにイベントをセット}}};functionbtnClose(e){// 閉じるボタンが押されたら発火e.preventDefault();globalPc.scene=0;// 閉じるボタンなので選択されたsceneはnullにするので、0を代入container.classList.remove("is-open");// containerのis-openのclass名を削除varsectionElements=document.getElementsByClassName("section");// sectionを取得for(vari=0;i<sectionElements.length;i++){// sectionをループ処理if(sectionElements[i].classList.contains("is-current")){// sectionにis-currentのclass名を持つかif処理sectionElements[i].classList.remove("is-current");// is-currentを削除}}}

リンクさせる方法として、global変数のglobalPcで今開いているページを管理できるようにします。

initializeには以下を追加します。

globalPc.scene=0;// どのシーンページを開いているか保管

先ほど確認したhotspot.jsのdoRayCastでもglobal変数に数字を与えます。
数字のみを代入するようにします。

Hotspot.prototype.doRayCast=function(screenPosition){// レイキャスト処理(ある地点から特定方向に直線で線を引いて、その線上で物体があるか検知する処理)if(this.hitArea.intersectsRay(this.ray)){// ヒットエリアとレイが交差した場合globalPc.scene=this.entity.tags._list[0].replace(/[^0-9]/g,'');// entityで設定したタグを取得し、scene1、scene2...の数字以外をreplaceで削除し数字のみ代入}};

Launch画面でリロードして3Dオブジェクトをクリックすると、それぞれ該当したhtmlが表示されるようになります。

これで簡単なwebの大枠はできました。

[ hotspot.jsのコード ]

varHotspot=pc.createScript('hotspot');// canvasのclickやhoverなどの処理を行うHotspot.attributes.add("cameraEntity",{type:"entity",title:"Camera Entity"});// カメラのentityを取得Hotspot.attributes.add("radius",{type:"number",title:"Radius"});// entityのヒットエリアの範囲を指定Hotspot.prototype.initialize=function(){// initthis.hitArea=newpc.BoundingSphere(this.entity.getPosition(),this.radius);// ヒットエリアを作成。BoundingSphereがentityの境界エリアを作成(Photoshopでいうバウンディングボックス的な)this.ray=newpc.Ray();// cameraからentityへ直進する線のデータを作成。(Rayは光線の意でstart pointからentityまでの距離を測ったりすることが可能)this.directionToCamera=newpc.Vec3();// Vector座標の型を取得this.app.mouse.on(pc.EVENT_MOUSEMOVE,this.onMouseHover,this);// マウスカーソルがホバーした時this.app.mouse.on(pc.EVENT_MOUSEDOWN,this.onMouseDown,this);// クリックが押された時};Hotspot.prototype.doRayCast=function(screenPosition){// レイキャスト処理(ある地点から特定方向に直線で線を引いて、その線上で物体があるか検知する処理)if(this.hitArea.intersectsRay(this.ray)){// ヒットエリアとレイが交差した場合globalPc.scene=this.entity.tags._list[0].replace(/[^0-9]/g,'');// entityで設定したタグを取得し、s1、s2...の数字以外をreplaceで削除し数字のみ代入}};Hotspot.prototype.onMouseHover=function(screenPosition){// マウスホバー時this.cameraEntity.camera.screenToWorld(screenPosition.x,screenPosition.y,this.cameraEntity.camera.farClip,this.ray.direction);// ポジションを2Dスクリーンから3D空間へ変換this.ray.origin.copy(this.cameraEntity.getPosition());// レイのオリジナルのポジションにカメラのポジションをコピーthis.ray.direction.sub(this.ray.origin).normalize();// 3次元ベクトルを他の場所から減算し、単位ベクトルに変換if(this.hitArea.intersectsRay(this.ray)){// ヒットエリアとレイが交差した場合console.log("hover");}};Hotspot.prototype.onMouseDown=function(event){// クリックが押されている時if(event.button==pc.MOUSEBUTTON_LEFT){// 左クリックが押された時this.doRayCast(event);// レイキャストを呼ぶ}};

[ addhtml.js のコード ]

varAddhtml=pc.createScript('addhtml');// htmlを追加などする処理を記入Addhtml.attributes.add("css",{type:'asset',assetType:'css',title:'CSS Style'});// アセットのcss読み込みAddhtml.attributes.add("header",{type:'asset',assetType:'html',title:'HTML Header'});// アセットのhtmlのheader読み込みAddhtml.attributes.add("scene1",{type:'asset',assetType:'html',title:'HTML Scene1'});// アセットのhtmlのscene1読み込みAddhtml.attributes.add("scene2",{type:'asset',assetType:'html',title:'HTML Scene2'});// アセットのhtmlのscene2読み込みAddhtml.attributes.add("scene3",{type:'asset',assetType:'html',title:'HTML Scene3'});// アセットのhtmlのscene3読み込みglobalPc={};// グローバルな変数(オブジェクト)varcontainer;Addhtml.prototype.initialize=function(){// initglobalPc.scene=0;// どのシーンページを開いているか保管varhtmlNameArr=[];// attributesのデータの名前を配列にしますvararrIndex=Addhtml.attributes.index;for(vari=0;i<Object.keys(arrIndex).length;i++){// attributesのデータを取得してfor文で回すif(!Object.keys(arrIndex)[i].indexOf("scene")){// 名前にhtmlが入っているデータをif文htmlNameArr.push(Object.keys(arrIndex)[i]);// htmlデータの名前だけ配列化する}}varhead=document.getElementsByTagName("head")[0];// headタグ取得varbody=document.getElementsByTagName("body")[0];// bodyタグ取得varwrapper=document.createElement("div");// DOMを囲う要素を作成wrapper.className="wrapper";// クラス名指定body.appendChild(wrapper);// bodyタグの最後に要素を追加container=document.createElement("main");// DOMを囲う要素を作成container.className="container";// クラス名指定wrapper.appendChild(container);// bodyタグの最後に要素を追加varstyle=document.createElement("style");// cssのstyleタグwrapper.insertAdjacentHTML("afterbegin",this.header.resource);// attrで追加したヘッダーを追加style.append(this.css._resources[0]);head.appendChild(style);// headの最後にstyleを追加for(vari=0;i<htmlNameArr.length;i++){// htmlのアセットを配列管理するためにfor文でattrの名前の配列を回すcontainer.insertAdjacentHTML("beforeend",this[htmlNameArr[i]].resource);// アセットから取得したhtmlを追加}};Addhtml.prototype.update=function(dt){// updateif(Number(globalPc.scene)>0){// いずれかのsceneが選択されている場合if(!container.classList.contains("is-open")){// 追加したアセットのhtmlにis-openのclassが追加されていない場合(どのhtmlも表示されていない)container.classList.add("is-open");// is-openのclass名をcontainerに追加varsectionElements=document.getElementsByClassName("section");// sectionを取得for(vari=0;i<sectionElements.length;i++){// sectionをループ処理if(sectionElements[i].classList.contains("is-current")){// sectionにis-currentのclass名を持つかif処理sectionElements[i].classList.remove("is-current");// is-currentを削除}}sectionElements[globalPc.scene-1].classList.add("is-current");// 選択されたsceneにis-currentのclass名を追加document.getElementsByClassName("section_close")[globalPc.scene-1].addEventListener("click",btnClose,false);// 選択されたsceneの閉じるボタンにイベントをセット}}};functionbtnClose(e){// 閉じるボタンが押されたら発火e.preventDefault();globalPc.scene=0;// 閉じるボタンなので選択されたsceneはnullにするので、0を代入container.classList.remove("is-open");// containerのis-openのclass名を削除varsectionElements=document.getElementsByClassName("section");// sectionを取得for(vari=0;i<sectionElements.length;i++){// sectionをループ処理if(sectionElements[i].classList.contains("is-current")){// sectionにis-currentのclass名を持つかif処理sectionElements[i].classList.remove("is-current");// is-currentを削除}}}

次はここまで作成したSceneをPublishして公開します。

次回


Viewing all articles
Browse latest Browse all 8576

Trending Articles



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