JavaScriptで文字がはみ出している時に自動横スクロールする

#目標
コレ↓ を作ります。
![コンポ 1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635641/e56818ad-c1e2-ce07-1972-2360fe7c8793.gif)

#完成形
```javascript
function StartScroll(target_id){
    const ele = document.getElementById(target_id);
    var style = ele.style;
    style.overflowY = "scroll";//横スクロールする
    style.whiteSpace = "nowrap";//改行しない
    style.setProperty("-ms-overflow-style","none");
    style.setProperty("scrollbar-width","none");
    style.setProperty("-webkit-scrollbar","none");

    /**
     * この値がno以外になったらスクロールを終了する
     */
    let scroll_exit = "no";
    
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                        setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                            ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す
                            setTimeout(scroll,2000);//一番左に戻してから2000ms(2秒)後にスクロールを再開する
                        },1000);//1000ms(1秒)後に一番左に戻す
                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                    };
                };
                move_left();//最初の一回を実行
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
    
    new Promise(() => {//非同期で
        scroll();//最初のスクロールを開始する
    });

    return function(){
        scroll_exit = "yes";
    };
};
```

#作り方

複数の要素をスクロールできるように関数を作ります。

```javascript
function scroll(target_id){

}
```

まず `` getElementById`` をします。

```javascript
function scroll(target_id){
    const ele = document.getElementById(target_id);
}
```
次に``style``を設定します。

```javascript
function scroll(target_id){
    const ele = document.getElementById(target_id);
    var style = ele.style;
    style.overflowY = "scroll";//横スクロールする
    style.whiteSpace = "nowrap";//改行しない
    style.setProperty("-ms-overflow-style","none");
    style.setProperty("scrollbar-width","none");
    style.setProperty("-webkit-scrollbar","none");
}
```
## 自動でスクロール
ここから自動でスクロールできるようにします。


まず、スクロールを終了できるようにします。

```javascript
function scroll(target_id){
    const ele = document.getElementById(target_id);
    var style = ele.style;
    style.overflowY = "scroll";//横スクロールする
    style.whiteSpace = "nowrap";//改行しない
    style.setProperty("-ms-overflow-style","none");
    style.setProperty("scrollbar-width","none");
    style.setProperty("-webkit-scrollbar","none");


    /**
     * この値がno以外になったらスクロールを終了する
     */
    let scroll_exit = "no";
}
```

スクロールする関数を作ります。

```javascript
function scroll(target_id){
    const ele = document.getElementById(target_id);
    var style = ele.style;
    style.overflowY = "scroll";//横スクロールする
    style.whiteSpace = "nowrap";//改行しない
    style.setProperty("-ms-overflow-style","none");
    style.setProperty("scrollbar-width","none");
    style.setProperty("-webkit-scrollbar","none");


    /**
     * この値がno以外になったらスクロールを終了する
     */
    let scroll_exit = "no";

    function scroll(){
       
    };
}
```
``scroll_exit`` が ``no`` の時以外実行しないようにします。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
 
        };
    };

```
スクロール可能な横幅が``0``になっているか確認して、スクロールが必要か確認します。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
               
            }else{//スクロールが不要な場合

            };
        };
    };
```
スクロールが不要な場合２秒後にもう一度スクロールが不要か確認します。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
               
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```

###スクロールが必要な場合の処理
ここからスクロールが必要な場合の処理です。

初めに、現在どのくらいスクロールしているか取得しておきます。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合

                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録

            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```
左にスクロールする関数を作ります。

```javascript
   function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録

                function move_left(){//実際にスクロールする関数

                };

            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```

左に1スクロールします。

```javascript
   function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数

                    ele.scrollLeft++;//1スクロールする

                };
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```
現在のスクロール位置を取得して、事前に取得しておいた位置と同じか比較する事で最後までスクロールしたか確認します。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする

                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認

                    }else{//最後までスクロールしていない場合

                    };

                };
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```

#### 最後までスクロールしていない場合

次のスクロールを開始する前に、現在のスクロール位置を事前に取得しておきます。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                    }else{//最後までスクロールしていない場合

                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新

                    };
                };
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```

``20ms``待機してからもう一度スクロールします。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新

                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）

                    };
                };
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```

#### 最後までスクロールできた時

一番右で``1000ms``待機してから一番左に移動します。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認



                        setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                            ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す
                        },1000);//1000ms(1秒)後に一番左に戻す



                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                    };
                };
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
```

``2000ms``(2秒)待機してからスクロールを再び開始します。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                        setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                            ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す



                            setTimeout(scroll,2000);//2000ms(2秒)後にスクロールを再開する



                        },1000);//1000ms(1秒)後に一番左に戻す
                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                    };
                };
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
    

```

### 関数の``1回目``を実行する

関数の中から関数を実行していますが、最初の1回は関数の外から実行しないといけないので最初の一回を実行します。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                        setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                            ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す
                            setTimeout(scroll,2000);//一番左に戻してから2000ms(2秒)後にスクロールを再開する
                        },1000);//1000ms(1秒)後に一番左に戻す
                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                    };
                };



                move_left();//最初の一回を実行



            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };

```

同じように``scroll()``も最初の一回を外から実行します。
これは非同期で実行します。

```javascript

    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                        setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                            ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す
                            setTimeout(scroll,2000);//一番左に戻してから2000ms(2秒)後にスクロールを再開する
                        },1000);//1000ms(1秒)後に一番左に戻す
                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                    };
                };
                move_left();//最初の一回を実行
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
    




    new Promise(() => {//非同期で
        scroll();//最初のスクロールを開始する
    });
```

## スクロールを終了する
最後にスクロールを止められるようにします。

```javascript
    function scroll(){
        if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
            if(!ele.scrollWidth == 0){//スクロールが必要な場合
                let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                function move_left(){//実際にスクロールする関数
                    ele.scrollLeft++;//1スクロールする
                    if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                        setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                            ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す
                            setTimeout(scroll,2000);//一番左に戻してから2000ms(2秒)後にスクロールを再開する
                        },1000);//1000ms(1秒)後に一番左に戻す
                    }else{//最後までスクロールしていない場合
                        lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                        setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                    };
                };
                move_left();//最初の一回を実行
            }else{//スクロールが不要な場合
                setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
            };
        };
    };
    
    new Promise(() => {//非同期で
        scroll();//最初のスクロールを開始する
    });






    return function(){
        scroll_exit = "yes";//スクロールを止める
    };
```

#実際に使ってみる
今作成した関数を実行する事でスクロールを開始できます。

```javascript
StartScroll("display");//スクロールを開始する
StartScroll("ココはスクロール対象のid");//スクロールを開始する
```

スクロールを終了するには、関数実行時に取得した関数を実行する事で、一番左に戻ったタイミングでスクロールが終了します。

```javascript
        var end = StartScroll("display");//スクロールを開始する



        //終了ボタンが押されたときの処理
        document.getElementById("exit").onclick = function(){
            end();
        };
```


## 例

[今すぐ試す](https://lp0ql.github.io/html_auto_scroll/index.html)

```html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id='display'>
        ああああああああああああああああああああああああああああああああ
    </div>
    
    <button id="exit">
        スクロール終了
    </button>

    <style>
        #display{
            width: 100px;
        }
    </style>
    <script>
        function StartScroll(target_id){
            const ele = document.getElementById(target_id);
            var style = ele.style;
            style.overflowY = "scroll";//横スクロールする
            style.whiteSpace = "nowrap";//改行しない
            style.setProperty("-ms-overflow-style","none");
            style.setProperty("scrollbar-width","none");
            style.setProperty("-webkit-scrollbar","none");

            /**
             * この値がno以外になったらスクロールを終了する
             */
            let scroll_exit = "no";
            
            function scroll(){
                if(scroll_exit == "no"){//スクロールが終了に設定されていない事を確認
                    if(!ele.scrollWidth == 0){//スクロールが必要な場合
                        let lastLeft = ele.scrollLeft;//現在のスクロール位置を記録
                        function move_left(){//実際にスクロールする関数
                            ele.scrollLeft++;//1スクロールする
                            if(lastLeft == ele.scrollLeft){//最後までスクロールした事を確認
                                setTimeout(function(){//1000ms(1秒)後に一番左に戻す
                                    ele.scrollLeft = 0;//1000ms(1秒)後に一番左に戻す
                                    setTimeout(scroll,2000);//一番左に戻してから2000ms(2秒)後にスクロールを再開する
                                },1000);//1000ms(1秒)後に一番左に戻す
                            }else{//最後までスクロールしていない場合
                                lastLeft = ele.scrollLeft;//現在のスクロール位置を更新
                                setTimeout(move_left,20)//20はスクロール速度（値が小さい方が早くスクロール）
                            };
                        };
                        move_left();//最初の一回を実行
                    }else{//スクロールが不要な場合
                        setTimeout(scroll,2000)//2000ms(2秒)後にもう一度スクロールが必要か確認
                    };
                };
            };
            
            new Promise(() => {//非同期で
                scroll();//最初のスクロールを開始する
            });

            return function(){
                scroll_exit = "yes";
            };
        };




        var end = StartScroll("display");//スクロールを開始する



        //終了ボタンが押されたときの処理
        document.getElementById("exit").onclick = function(){
            end();
        };
    </script>
</body>
</html>
```