PlayCanvasでDOMを扱う手引き [装飾つけちゃお編]

[前回はDOMを追加しました](https://qiita.com/sutobu000/items/79aa414a1352474386e5)
しかし、DOM追加しただけで、CSSによるstyleがついていません…

PlayCanvasだけではないですが、canvas要素などのコンテンツの上にDOMを乗せていきます！


#Projectを用意
[前回のDOMを追加したProject](https://qiita.com/sutobu000/items/79aa414a1352474386e5)を使っていきます。

前回のProjectではcontentというclass名のDOMが追加しました。
<img width="585" alt="スクリーンショット 2019-12-15 23.13.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/20628201-34c2-dfb1-156f-138e584787f7.png">


#CSSの付与の仕方
DOMにstyleを付けますが、方法はいくつかあります。

今回は前回作った`addHTML.js`に追記する形でいきます。

```js
var AddHtml = pc.createScript('addHtml');

AddHtml.prototype.initialize = function() {
    var domContent = document.createElement("div");
    domContent.classList.add("content");
    
    document.body.appendChild(domContent);    
};
```

##JavaScriptからDOMごとにstyleを付与

ここでは`domContent`が大事になってきます。
domContentはHTMLElementというインターフェースで、これはDOM要素のことを言っていると思ってもらえれば良いかなと。
これにはstyleプロパティがあり、これを使ってstyleをJavaScriptから指定することができます。
例えば以下のようにする。

```js
var AddHtml = pc.createScript('addHtml');

AddHtml.prototype.initialize = function() {
    var domContent = document.createElement("div");
    domContent.classList.add("content");
    
    document.body.appendChild(domContent);
    
    domContent.style.width = "500px";
    domContent.style.height = "500px";
    domContent.style.background = "#ffffff";
    
};
```

すると、幅と高さが500x500の白い正方形ができるはずですが、見えませんね…
Developerツールで見ると存在はしているようです。
また、styleもちゃんと当たっているのがわかります。

<img width="1679" alt="スクリーンショット 2019-12-20 12.58.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/806b671f-34a8-9c3a-8a04-7079b250ae89.png">

なぜ見えていないのか、という話は後ほどします。


##JavaScriptからCSSを書く
先ほどは、domContentstyleにstyleプロパティを使ってstyleをつけましたが、
直接JavaScriptsにCSSの記述でstyleを書くこともできます。

```js
var AddHtml = pc.createScript('addHtml');

AddHtml.prototype.initialize = function() {
    var domContent = document.createElement("div");
    domContent.classList.add("content");
    
    document.body.appendChild(domContent);
    
    var createCss = function () {
        var css = [
            '.content {',
            '    width: 500px;',
            '    height: 500px;',
            '    background: #ffffff;',
            '}',
        ].join('\n');

        var style = document.createElement('style');
        style.type = 'text/css';
        if (style.styleSheet) {
          style.styleSheet.cssText = css;
        } else {
          style.appendChild(document.createTextNode(css));
        }
        document.head.appendChild(style);
    };

};
```

実はこの書き方は個人的に好きではないです。
ですが、PlayCanvasのLoading Screenを構成している`__loading.js`には、この書き方でcssを追記していますね。
class名で指定したいとか、hoverとかのCSSアニメーションなんかもつけたい場合には使える手段です。


##CSSを属性から読み込む
先ほどまではJavaScriptからstyleを指定していましたが、
WebならCSSでstyleを指定するのがいいですよね。私はその方が良いです。

CSSファイルを新規作成します。
jsファイルを新規作成するのと同じ手法ですが、今回はコードエディターから。

上部メニューのCreate NewからCSS Assetを作成。
<img width="797" alt="スクリーンショット 2019-12-20 14.38.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/ad964651-49f6-6655-c0a1-f7e0eb629556.png">

名前も変えておきましょう
<img width="566" alt="スクリーンショット 2019-12-20 14.39.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/468545cd-64fb-0312-13f8-d397812b3ec2.png">

ビジュアルエディターからでも新規作成・名前変更は可能です。
<img width="838" alt="スクリーンショット 2019-12-20 14.39.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/a2e45da8-83bd-e358-ced8-c5add91180e6.png">


CSSファイルを作ったら、これをweb上に反映させます。
作っただけではダメなんです。ちゃんと配置させます。

AddHtml.jsで先ほど作ったstyle.cssを読み込ませていきます。
外部ファイルであるstyle.cssをAddHtml.jsで使うために、`attributes`を使います。
これはAddHtml.jsに属性を追加することができ、AssetやEntityも属性として登録してスクリプトで操作することが容易になります。
ここでは`stylesheet`という属性名でAssetsのstyle.cssを呼び出しています。
HTML5においてCSSファイルはlink要素のhrefプロパティから参照することでstyleを読み込むことができます。
そのlink要素をheadタグに追加することで完了です。

```js
var AddHtml = pc.createScript('addHtml');

AddHtml.attributes.add("stylesheet",{type:"asset",assetType:"css"});

AddHtml.prototype.initialize = function() {
    var domContent = document.createElement("div");
    domContent.classList.add("content");
    
    document.body.appendChild(domContent);

    var link = document.createElement('link');
    link.rel = "stylesheet";
    
    link.href = this.stylesheet.getFileUrl();
    
    document.head.appendChild(link);
};
```

`attributes`で追加した属性は以下のように登録ができます。
スクリプトを更新するだけでは反映されませんが、Parseを押すことで解消されます。
<img width="383" alt="スクリーンショット 2019-12-20 15.13.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/7f04c5e4-27e2-28f2-e838-0d8f27b4b6f7.png">


#作ったDOM要素が見えなかった件について

```css
.content {
  width: 500px;
  height: 500px;
  background: #fff;
}
```
これは先ほど作ったstyleですが、白い正四角形が見えていたはずですが見えませんでしたね。

一体なぜなのか。

##Positionのせいなのね
canvas要素にある`position: absolute;`というプロパティがその原因です。
positionは要素の配置方法を指定することができます。

[HTMLリファレンス](http://www.htmq.com/style/position.shtml)の解説を引用しながら解説してみます。
positionには4つの値があります。

- static
    - 配置方法は指定無し。positionの初期値。
- relative
    - 相対位置への配置。
- absolute
    - 絶対位置への配置。
    - 親ボックスにpositionプロパティのstatic以外の値が指定されている場合には、親ボックスの左上が基準位置となる。
    - 親ボックスにpositionプロパティのstatic以外の値が指定されていない場合には、ウィンドウ全体の左上が基準位置となる。
- fixed
    - 絶対位置への配置となるのはabsoluteと同様だが、スクロールしても位置が固定されたままとなる。

この配置で大事なのは**static**なのか、**static以外**なのかというところです。

staticは平面上にぺったりくっついている感じです。
それに対して、static以外のrelative、absolute、fixedは、staticの平面の更に上に乗っかっている感じです。

**レイヤー層**がpositionによって違ってきますね。
そのため、canvas要素がレイヤーが上に来てしまって、AddHtml.jsから追加した要素が見えなくなってしまっていたんですね。

ここまで来たらどうしたら良いか、わかってきますね。

```css
.content {
    position: absolute;
    width: 500px;
    height: 500px;
    background: #ffffff;
}
```

<img width="1568" alt="スクリーンショット 2019-12-20 15.55.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109168/955f68f4-c138-1501-decf-a7b47fc359a2.png">

おーレイヤーが上に来ましたね！
これでDOMが追加できましたし、styleを理解し操作することでレイヤーも分けられました。


###Positionのいろんな使い方
####左上（初期位置）

```css
.content {
    position: absolute;
    top: 0;
    left: 0;
}
```

####右上

```css
.content {
    position: absolute;
    top: 0;
    right: 0;
}
```

####左下

```css
.content {
    position: absolute;
    bottom: 0;
    left: 0;
}
```

####右下

```css
.content {
    position: absolute;
    bottom: 0;
    right: 0;
}
```

####中央配置
私はこれが一番理屈に合った中央配置なので使っているだけですが、
中央配置には色んなやり方がありますので、検索してみましょう

```css
.content {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%)
}
```

配置以外にも、`z-index`というz軸の値を使うこともできます。
top,bottomがy軸で、left,rightがx軸といえば、わかりやすいですね。
z軸はレイヤーの順番を任意で変えることができるので色々活用していきましょう。

```css
.content {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
}
```


---

そんなこんなで今回はstyleで装飾つけるまでやりました…

え？

「装飾というかpositionの話しかしてないじゃん」

そうですね…
確かにpositionしかやっていないですね……

~~もちろん、CSSでは色んなstyleを指定することができます！~~
~~ですが、今回の解説は少し長くなったのできたのでここまで。~~
~~もっと装飾をつけていく話は、次回の記事で！~~

~~お楽しみに〜！~~

[次回記事はこちら！！](https://qiita.com/sutobu000/items/3f5f0dae4e17a5f2374e)