HTML
CSS
JavaScript

【意中のあの子をGET】javascriptでつくるデートスポットルーレット

はじめに

この記事をみなさんが見ているということは、、、
私は今頃、長期休暇に入る前の計画性のない小学生の如く大量の荷物を目の前に頭を抱えていることでしょう(本日最終出社日)

......てことはそう、
クリスマス!!!!!「クリスマス」が近いですね!!!!!!!

クリスマスとは

  • 12月25日のキリストの誕生日を祝う日
  • 今宵の日本ではなぜか、な ぜ か
    リア充が普段よりもリア充する日になっている
  • 祝日の23日と連続し、暗黙の了解で23,24,25が絶賛クリスマス期間になっています
  • この期間にデートすることをクリスマスデートと言う。
  • クリスマスデートを成功させれば、勝つ......らしい。保証はしない。

クリスマスデートの計画を立てる手順

みなさんはもうデートの予定や計画は決定しておりますでしょうか
筆者の周囲では一例ではありますが、以下のように進めているようです

  1. デートに誘う
  2. メインのデートスポットを決める
  3. レストランの予約

これが決まってなかったら、寒空の中
2人で街中を歩くことになるでしょう

ぐだぐだなデートはしたくない...でもどこに行けばいいか一人じゃ決められない...

そんなあなたに今回は2番目の手順である「どこに行くか」を決めてくれるルーレットを
提供しましょう!

デートを成功させる第一歩はまず、メインで「どこに行くか」を決めることです!

どんなものを作るの?

デモはこちら

illumination.gif

  • スタートボタンを押したらルーレット開始
  • ルーレットが開始されたらデートスポットがランダムに三└(┐卍^o^)卍ドゥルルルルルルルとシャッフルされる
  • ストップボタンを押したらルーレットが終了
  • 画面に行くべきデートスポットを表示する

以上です

使用するもの

  • javascript
  • HTML
  • CSS

本当は全部解説したいですが、文章がかなり長くなってしまうので、
今回の解説はjavascriptのみに絞ります。

javascript

スタートボタンを複数回クリックできないようにする

disabled

index.js
// スタートボタンを押したときの処理
function clickedStart() {
    'use strict';
    isStart = true;
    startBtn.disabled = true;
  • 指定した要素を2度クリックできないようにします。
  • 今回はスタートボタンを連打されると、だんだんものすごいスピードでデートスポットがシャッフルされるのでそれを防止するためにしました。

乱数をつくる

Math.random,Math.floor

index.js
        if(isStart === true) {
            place = spotList[Math.floor( Math.random() * spotList.length )];
            roulette.className = 'name';
            document.getElementById("isPlace").innerHTML = place;
        }
  • Math.random()で、0~1までの浮動小数点の乱数を発生させます。整数がいい場合はMath.floorを使ったほうがよいです。
  • 今回はMath.floorを使用し、spotListに入っている配列の数分だけ乱数を取得したいので、Math.random()で取得した数値と、配列の要素数をかけたものをMath.floorでランダムに表示させます。

要素を取得する

document.getElementById

  • HTMLのidを振ったDOMの要素を取得します。
    • 今回はHTMLにisPlaceというidを振っていて、その中身のHTMLの要素を取得しています。
    • javascriptでDOM操作をするときはclassよりもidを使った方がいいかもしれないです。
    • 実際に取得されるものはこちら、console.logで確認します

スクリーンショット 2017-12-18 10.55.18.png
isPlaceの要素の中身が取得できていることがわかります。
※こちらの関数、getElementByClassNameにすると返り値が全く違ってきますので注意が必要です。

初期表示から文言の内容を変える

inner.HTML

  • 要素の中身を変更します。
  • 今回は初期表示でpタグで「どこに行こうか?」と表示しているものをaタグでデートスポットの場所のリンクを表示させるように書き換えてあげましょう

こいつが
スクリーンショット 2017-12-18 11.35.43.png

こうなる
スクリーンショット 2017-12-18 11.35.30.png

pタグの中身を変えるのに成功しました!!!!

スタートボタンを押したらシャッフルし始める

setInterval

index.js
    intervalID = setInterval(function() {

    }, 100);
  • 一定時間、指定した処理を繰り返します。
  • 今回はランダムで画面にデートスポットを表示することを繰り返したいので、この関数を使いました。
  • これによって、三└(┐卍^o^)卍ドゥルルルルルルルが成功します

ストップボタンを押したらシャッフルをやめる

clearTimeout

index.js
function clickedStop() {
    'use strict';
    clearTimeout(intervalID);
  • 繰り返し処理を停止します。
  • 今回はストップボタンを押したら、三└(┐卍^o^)卍ドゥルルルルルルルをやめたいのでストップボタンを押下したときの処理の最初にこちらの処理を加えました。

まとめ

最終的なコードはこちらです。

javascript

index.js
// 変数宣言
var startBtn = document.getElementById('start');
var isStart = false;
var roulette = document.getElementById('roulette');
var place = '';
var intervalID = -1;
var spotList = [];

// 行きたい場所を配列にぶち込む
spotList = [
                    '<a href="http://colopl.co.jp/news/pressrelease/2017103001.php" target="_blank">恵比寿「コロプラキャナルウォーク」:イルミネーション</a>',
                    '<a href="http://www.tokyo-odaiba.net/rainbow/hanabi2017.html" target="_blank">お台場「レインボー花火」:花火</a>',
                    '<a href="https://www.enjoytokyo.jp/museum/event/1372777/" target="_blank">浅草橋「まるっと小動物展」:動物</a>',
                    '<a href="https://gardenplace.jp/special/2017christmas/" target="_blank">恵比寿「ガーデンプレイス」:イルミネーション</a>',
                    '<a href="http://www.toshimaen.co.jp/winter_fantasia2017-2018/" target="_blank">豊島園「ウィンターファンタジア」:イルミネーション</a>',
                    '<a href="http://shibuya-aonodokutsu.jp/" target="_blank">渋谷「青の洞窟」:イルミネーション</a>',
                    '<a href="https://sp.jorudan.co.jp/illumi/spot_0114.html" target="_blank">汐留「カノン・ダジュール」:イルミネーション</a>',
                    '<a href="http://www.tokyo-midtown.com/jp/event/3766/" target="_blank">六本木「ミッドタウンイルミネーション」:イルミネーション</a>',
                    '<a href="http://omotesando.or.jp/illumi/" target="_blank">表参道「表参道 イルミネーション」:イルミネーション</a>',
                    '<a href="http://www.ozmall.co.jp/xmas/date/11338/" target="_blank">押上「リサとガスパールと過ごすフランスのクリスマス」:イルミネーション</a>',
                    '<a href="https://tokyochristmas.net/" target="_blank">日比谷「クリスマスマーケット」:クリスマスマーケット</a>',
                    '<a href="http://www.ozmall.co.jp/xmas/date/11644/" target="_blank">元町・中華街「世界のクリスマス2017」:クリスマス体験</a>',
                    '<a href="http://www.yomiuriland.com/jewellumination/" target="_blank">京王よみうりランド「よみうりランド」:イルミネーション</a>'
                ];

// スタートボタンを押したときの処理
function clickedStart() {
    'use strict';
    isStart = true;
    startBtn.disabled = true;
    intervalID = setInterval(function() {
        if(isStart === true) {
            place = spotList[Math.floor( Math.random() * spotList.length )];
            roulette.className = 'name';
            document.getElementById("isPlace").innerHTML = place;
        }
    }, 100);
}

// ストップボタンを押した時の処理
function clickedStop() {
    'use strict';
    clearTimeout(intervalID);
    startBtn.disabled = "";
    isStart = false;
    if(place === '') {
        alert("スタートボタンを押してからストップボタンを押してね!");
    } else {
// 結果を画面に表示
    roulette.className = 'name';
    document.getElementById("isPlace").innerHTML = place;
    }
}

HTML

index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <link rel="stylesheet" type="text/css" href="css/style.css">
        <title>ランダムで行きたい場所を探す</title>
    </head>
    <body>
        <header>
            <h1><span class="span1"></span><span class="span2"></span>クリスマスルーレット<span class="span2"></span><span class="span1"></span></h1>
        </header>
        <article class="wapper">
            <div class="main">
                <div id="roulette">
                    <p id="isPlace">どこに行こうか?</p>
                </div>
                <div class="buttons">
                    <button id="start" onClick="clickedStart()">start</button>
                    <button id="stop" onClick="clickedStop()">stop</button>
                </div>
            </div>
        </article>
        <footer>
            <img src="image/footer.png">
        </footer>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

CSS

style.css
@charset "UTF-8";
@import url(https://fonts.googleapis.com/earlyaccess/sawarabigothic.css);

html {
    overflow: auto;
    height: 100vh;
}

body {
    position: relative;
    text-align: center;
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    margin: 0 auto;
    line-height: normal;
    -webkit-text-size-adjust:100%
}

header {
    position:absolute;
    top: 0;
    width: 100%;
}

footer {
    position:absolute;
    bottom: 0;
    width: 100%;
}

h1{
    position: relative;
    display: inline-block;
    padding: 0 55px;
    margin-top: 100px;
    font-size: 15px;
}

h1:before, h1:after {
    content: '';
    position: absolute;
    top: 50%;
    display: inline-block;
    width: 45px;
    height: 2px;
    border-top: solid 1px #808080;
    border-bottom: solid 1px #808080;
}

h1:before {left:0;}
h1:after {right: 0;}

h1 , p , a:link {
    color: #808080
}

img {
    width: auto;
    max-height: 90px;
}

a:visited {
    color: #FFB6C1
}

h1, p , a {
    font-family: "Sawarabi Gothic";
}

span {
    font-size: 8px;
}

.wapper {
    position: absolute;
    margin: auto;
    padding-top: 10px;
    padding-bottom: 10px;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
    height: 65%;
    width: 100vw;
}

.span1 {
    color: red;
}

.span2 {
    color: green;
}

.main {
    margin: 0 auto;
    width: 100%;
    height: 80%;
    position: relative;
}

.content {
    width: 100%;
}

.buttons {
    width: 100%;
    height: 33%;
    position: absolute;
    bottom: 0;
}

#start {
    float: left;
}

#stop {
    float: right;
}

#roulette {
    font-size: 28px;
    font-weight: bold;
    width: 100%;
    height: 50%;
    display: table;
    margin-right: auto;
    margin-left: auto;
}

#roulette p {
    margin: 30px;
    word-wrap:break-word;
}

#isPlace {
    position: absolute;
    top: 30px;
    right: 0;
    left: 0;
}

.buttons {
    width: 100%;
    height: 50%;
    text-align:center;
    display: block;
}

#start , #stop {
    display: block;
    text-decoration: none;
    height:50px;
    width: 120px;
    text-align: center;
    color: #2bb6c1;
    outline:none;
    border:solid 1px #2bb6c1;
    border-radius: 20px;
    background-color: #fff;
    -webkit-transition: 0.3s;
    -moz-transition: 0.3s;
    -o-transition: 0.3s;
    -ms-transition: 0.3s;
    transition: 0.3s;
    font-size: 23px;
    font-weight: bold;
}

#start:hover , #stop:hover {
    background: #2bb6c1;
    color: #fff;
    opacity: 1;
    cursor : pointer;
}

/* iPhone 3G/3GS CSS */
@media only screen and (max-device-width: 480px) and (-webkit-device-pixel-ratio: 1) {
    a {
        font-size: 15px;
    }
}

/* iPhone 4 CSS */
@media only screen and (max-device-width: 480px) and (-webkit-device-pixel-ratio: 2) {
    a {
        font-size: 15px;
    }
}

/* スマホ横長の場合 */
@media only screen and (max-device-width: 812px) and (orientation:landscape) {
    img {
        line-height: 60px;
        max-height: 50px;
    }
    h1 {
        margin: 0 auto;
    }
    #roulette p {
        margin: 0;
        padding-right: 20px;
        padding-left: 20px;
        vertical-align: middle;
    }
    #roulette {
        height: 30%;
        display: table;
    }
    .main {
        height: 100%;
    }
    .buttons {
        height: 70%;
    }
    #isPlace {
        top: 20px;
    }
}

@media screen and (max-width: 1200px) {
    #stop , #start {
        float: none;
        margin: 0 auto;
        margin-top: 20px;
        width: 250px;
    }
    p {
        font-size: 20px;
    }
    img {
        width: auto;
        max-height: 50px;
    }
}

@media screen and (min-width: 1200px) {
    .main {
        width: 40%;
    }
}

クリスマス直前まとめ

なるべくこのルーレットを使わないように早めの段階で計画しておいた方がゲストは喜びます。
ご利用は計画的に。
食事等は、もうこの日なので空いてないと思って諦めてください。

おわりに

これまでバックエンドでサイト改修やテストを主にやっていたのですが、
1月から別の会社でフロントエンドエンジニアとして働くのでHTML,CSS,javascriptを触りました。
まだまだ未熟ではありますし、特にjavascriptは初心者なので、何か動くものを...!という意思だけで作りました。
配列に愚直に入れているところはもっとどうにかしてスマートにできないもんかなとは思っております。

何はともあれ、これで今日・明日・明後日のクリスマスデートは完璧☆
あとはゲストに喜んでもらうだけ
みなさんもいいクリスマスを!
メリークリスマスイヴイヴイヴ!