年末まで毎日webサイトを作り続ける大学生 〜39日目 JavaScriptで要素の位置を取得して、スクロールに合わせて動かす〜

##はじめに
こんにちは！@70days_jsです。

JavaScriptで要素の位置を取得して、スクロールに合わせて動かしてみました。

今日は39日目。(2019/11/26)
よろしくお願いします。

##サイトURL
https://sin2cos21.github.io/day39.html

##やったこと
JavaScriptで要素の位置を取得して、スクロールに合わせて動かしました。↓
![test2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/10dfd739-2747-71d2-ba8a-4caeaf867ca9.gif)


要素をスクロールに合わせてバラバラに動かすパララックスを作ってみようと思い、今日はその原理を確認しました。
ポイントはpositionをabsolute、fixed、relativeのどれかにすること、要素の現在位置、スクロール量を取得することです。

html全体↓

```html
<body>
    <div id="box1" class="box"></div>
    <div id="box2" class="box"></div>
    <div id="box3" class="box"></div>
    <div id="display">
        スクロール量: <span id="data1"></span><br>
        box1 Top: <span id="box1-top"></span><br>
        box2 Top: <span id="box2-top"></span> box2 Left: <span id="box2-left"></span><br>
        box3 Top: <span id="box3-top"></span>
    </div>
</body>
```

今回は要素をfixedにしました。absoluteでもrelativeでもokです。

```css
  .box {
    position: fixed;
 }
```

次はJavaScriptを紹介しますが、ここからが本題です。
まずそれぞれのboxの位置を取得します。↓

```javascript
// box1のY軸の最初の位置
let box1TopPosition = box1.offsetTop;

// box2のX軸Y軸の最初の位置
let box2TopPosition = box2.offsetTop;
let box2LeftPosition = box2.offsetLeft;

// box3のY軸の最初の位置
let box3TopPosition = box3.offsetTop;
```

box2だけは横移動も加えたのでleftの値も取得しています。

次にwindowにスクロールで発火するイベントリスナーをつけます。


```javascript

window.addEventListener('scroll', function () {
    // スクロール量
    let scroll = window.pageYOffset;

    // スクロールに合わせてbox1を移動させる
    let b1Top = box1TopPosition + (scroll / 2) + 'px';
    box1.style.top = b1Top;
    // box1のY軸の現在の位置
    let box1TopPositionNow = box1.offsetTop;
    // htmlにbox1の現在の位置を描画
    data1.innerHTML = scroll;
    box1Top.innerHTML = box1TopPositionNow;


    // box2の現在の位置
    let box2TopPositionNow = box2.offsetTop;
    let box2LeftPositionNow = box2.offsetLeft;
    // スクロールに合わせてbox2を移動させる
    let b2Top = box2TopPosition + (scroll / 3) + 'px';
    let b2Left = box2LeftPosition + (scroll / 4) + 'px';
    box2.style.top = b2Top;
    box2.style.left = b2Left;

    // htmlに値を描画
    box2Top.innerHTML = box2TopPositionNow;
    box2Left.innerHTML = box2LeftPositionNow;

    // box3のY軸の現在の位置
    let box3TopPositionNow = box3.offsetTop;
    // スクロールに合わせてbox3を移動させる
    let b3Top = box3TopPosition + (scroll / 4) + 'px';
    box3.style.top = b3Top;
    // htmlに値を描画
    box3Top.innerHTML = box3TopPositionNow;
})
```

これでスクロールされると自動でfunctionを実行してくれます。

スクロール量の取得はこれです。↓
>  let scroll = window.pageYOffset;

boxの移動はこの一行です。↓
>    let b1Top = box1TopPosition + (scroll / 2) + 'px';

ここで(scroll/2）の/2の部分を変えていけば様々な速度にできます。
今回は、スクロール量を2で割っているので、スクロールに対して半分しか動かないようにしています。

##おまけ
- コンテンツ y軸の位置 取得方法
 - offsetTop・・borderの位置から（marginは無視）
- コンテンツ 高さ 取得方法
 - clientHeight・・・paddingまで含む
 - offsetHeight・・・borderまで含む

- スクロール量 Y軸 取得方法
 - window.pageYOffset
 - document.documentElement.scrollTop


##感想
調べているとブラウザの互換性がうんたら、返すオブジェクトがうんたらとweb業界の闇を覗いてしまいました。
統一してくれればいいのにと思うのですが、そこらへんは大人の事情があるんでしょうか・・・？
とはいえ、今日はスクロールで要素が動く謎を解明できてよかったです。これもブラウザを作ってくれた人が使いやすいプロパティやメソッドを用意してくれたからですね。

最後までお読みいただきありがとうございます。明日も投稿しますのでよろしくお願い致します。

##参考
1. JavaScriptでスクロール量を取得する方法 (https://lab.syncer.jp/Web/JavaScript/Snippet/1/)

とても分かりやすかったです。ありがとうございます！