さぁ!検索しよう!

HTML,CSS,JavaScriptによる簡易電卓の作り方です。

DEMO

HTMLを書く

始めに以下のHTMLを書きます。

<div class="calculator">
    <div class="display__wrap">
        <aside class="display">
            <div id="displaySym" class="display__sym"></div>
            <div id="displayNum" class="display__num"></div>
        </aside>
    </div>
    <nav class="nav">
        <div class="nav__inner nav__inner--left">
            <div class="nav__erase">
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--erase" data-value="ce" href="#">CE</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--erase" data-value="ca" href="#">CA</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--erase" data-value="del" href="#">DEL</a></div>
            </div>
            <div class="nav__num">
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="7" href="#">7</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="8" href="#">8</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="9" href="#">9</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="4" href="#">4</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="5" href="#">5</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="6" href="#">6</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="1" href="#">1</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="2" href="#">2</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="3" href="#">3</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="0" href="#">0</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="00" href="#">00</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--num" data-value="." href="#">.</a></div>
            </div>
        </div>
        <div class="nav__inner nav__inner--right">
            <div class="nav__operator">
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--operator" data-value="/" href="#">÷</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--operator" data-value="*" href="#">×</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--operator" data-value="-" href="#">-</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--operator" data-value="+" href="#">+</a></div>
                <div class="nav__btn__wrap"><a class="nav__btn nav__btn--operator" data-value="=" href="#">=</a></div>
            </div>
        </div>
    </nav>
</div>

HTMLの構成は以下の通りです。

ディスプレイ

ディスプレイ.display内の.display__symには演算子を、.display__numには数値や小数点を出力します。

ボタン

ボタンのグループを、.nav__inner--left.nav__inner--rightの2つに分けています。

また、各ボタンにはJavaScriptで入力値を判別するために、data-valueを設定しています。

CSSを書く

次に以下のCSSを書きます。

@import url(https://fonts.googleapis.com/css?family=Righteous);
* {
    box-sizing: border-box;
}

html {
    font-size: 24px;
    font-size: 4vw;
}

@media screen and (min-width: 600px) {
    html {
        font-size: 1.5em;
    }
}

body {
    background: #180052;
    font-family: 'Righteous', cursive;
    margin: 0;
    padding: 0;
    text-shadow: -1px -1px #cc6600;
}

.nav,
.nav__inner,
.nav__erase,
.nav__num {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
}

.display,
.nav__btn {
    background: -webkit-gradient(linear, left top, left bottom, from(#B39DDB), color-stop(50%, #673AB7), color-stop(51%, #512DA8), to(#311B92));
}

.calculator {
    position: absolute;
    top: 50%;
    left: 50%;
    -webkit-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
    width: 12em;
}

.display {
    position: relative;
    z-index: 30;
    border-radius: 0.5em;
    color: #fff;
    display: block;
    padding: 1em;
    -webkit-transition: color 0.3s ease;
    transition: color 0.3s ease;
    text-align: right;
    text-decoration: none;
}

.display__wrap {
    border-radius: 0.5em;
    padding: 0.1em;
}

.display__sym {
    height: 1em;
}

.nav__inner--left {
    width: 9em;
}

.nav__inner--right {
    -ms-flex-flow: column-reverse;
    flex-flow: column-reverse;
    width: 3em;
}

.nav__btn {
    border-radius: 0.5em;
    color: #fff;
    display: block;
    height: 3em;
    line-height: 3em;
    -webkit-transition: color 0.3s ease;
    transition: color 0.3s ease;
    text-align: center;
    text-decoration: none;
}

.nav__btn:hover {
    color: #fff;
}

.nav__btn__wrap {
    padding: 0.1em;
    width: 3em;
}

主にCSSで行っていることは以下の通りです。

flexboxによるボタンの配置

各ボタンを敷き詰めるためにそれぞれの親要素にdisplay:flex;を指定しています。更に、ボタンを複数行に折り返すために、flex-wrap:wrap;を指定しています。

.nav,
.nav__inner,
.nav__erase,
.nav__num {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-wrap: wrap;
    flex-wrap: wrap;
}

JavaScriptを書く

最後に以下のJavaScriptを書きます。

(function() {
    var displayNum = document.getElementById('displayNum');
    var displaySym = document.getElementById('displaySym');
    var btn = document.querySelectorAll('a');
    var operators = ['+', '-', '*', '/', '='];
    var btnVal;
    var calc = '+';
    var formula;
    var total = 0;
    var flag = true; //true:演算子,false:整数か小数点
    var currentVal = '';
    displayNum.innerHTML = total;
    for (var i = 0; i < btn.length; i++) {
        btn[i].addEventListener('click', function(e) {
            e.preventDefault();
            btnVal = this.getAttribute('data-value');
            //btnValが0~9または.だったら
            if (btnVal.match(/[0-9]/) || btnVal == '.') {
                currentVal += btnVal;
                displayNum.innerHTML = currentVal;
                flag = false;
            }
            //['+', '-', '*', '/','=']内に入力値があれば
            if (operators.indexOf(btnVal) > -1) {
                //演算子が押され且つ前に数字があれば
                if (!flag) {
                    formula = total + calc + currentVal;
                    total = eval(formula);
                    //console.log(total);
                    displayNum.innerHTML = total;
                    currentVal = '';
                    flag = true;
                }
                //入力値が['+', '-', '*', '/','=']内にあって、それがイコールだったら
                if (btnVal == '=') {
                    //イコールの前が演算子だったら
                    if (flag) {
                        btnVal = '';
                        flag = true;
                        //イコールの前が数字だったら
                    } else {
                        displaySym.innerHTML = '';
                        calc = '+';
                        flag = false;
                    }
                    //入力値が['+', '-', '*', '/','=']内にあって、それがイコールではなかったら
                } else {
                    displaySym.innerHTML = btnVal;
                    calc = btnVal;
                    flag = true;
                }
            }
            if (btnVal == 'del') {
                var delResult = displayNum.innerHTML.substr(0, displayNum.innerHTML.length - 1);
                displayNum.innerHTML = delResult;
                //console.log(delResult);
                //console.log(currentVal);
                //ディスプレイの文字数が0以下になったら
                if (displayNum.innerHTML.length <= 0) {
                    delResult = 0;
                    displayNum.innerHTML = delResult;
                    currentVal = '';
                }
            }
            if (btnVal == 'ca') {
                total = 0;
                calc = '+';
                currentVal = '';
                displayNum.innerHTML = total;
                displaySym.innerHTML = '';
            }
            if (btnVal == 'ce') {
                currentVal = 0;
                displayNum.innerHTML = currentVal;
                currentVal = '';
            }
        });
    }
})();

JavaScriptで行っていることは以下の通りです。

変数を定義

定義されている変数の詳細は下記の通りです。

変数名 説明
btnVal 押されたボタンのdata-valueが代入される変数
calc ディスプレイに表示される文字列の結合や、演算子を代入するための変数
formula 計算式が代入される変数
total 合計値が代入される変数
flag 整数・小数点が入力されたか、演算子が入力されたかを判断するための真偽値。trueならば演算子、falseならば整数・小数点と判断される。
currentVal 結合された値が代入される変数

ボタンが押されると

各ボタンを押すと、data-valueの値がbtnValに代入され、どのボタンが押されたかをif文で判定します。

for (var i = 0; i < btn.length; i++) {
    btn[i].addEventListener('click', function(e) {//どれかのボタンが押されたら
        e.preventDefault();
        btnVal = this.getAttribute('data-value');//押されたボタンのdata-valueをbtnValに代入し、btnValを入力値とする

0~9の整数か小数点が入力されたら

入力値btnValが0~9の整数か小数点だったときの処理は以下の通りです。

 if (btnVal.match(/[0-9]/) || btnVal == '.') {///0~9の整数か小数点が入力されたら
    currentVal += btnVal;///押されたボタンの値を連結していく
    displayNum.innerHTML = currentVal;///連結された値をディスプレイに出力
    flag = false;///整数か小数点が入力されたのでflagをfalseに切り替える
 }

演算子が入力され且つ、一つ前に入力した値が整数か少数点だったら

入力値btnValが演算子且つ、一つ前に入力した値が整数か小数点だったときの処理は以下の通りです。

if (operators.indexOf(btnVal) > -1) { ///入力値btnValが演算子且つ
    if (!flag) { ///一つ前に入力した値が整数か小数点だったら
        formula = total + calc + currentVal; ///計算式を作る
        total = eval(formula); ///合計値を算出
        displayNum.innerHTML = total; ///合計値をディスプレイに出力
        currentVal = ''; ///次の入力値を確保するために空にする
        flag = true; ///最後尾は演算子なので、flagをtrueに切り替える
    }

上記の計算式formulaですが、例えば、入力した演算子がカケルで、一つ前に入力した値が2だった場合の計算式は、total(0) + calc(*) + currentVal(2)となります。

演算子が入力され且つ、その演算子がイコールだったら

入力値btnValが演算子且つ、その演算子がイコールだったときの処理は以下の通りです。

if (btnVal == '=') { ///入力値btnValがイコールだったら
    if (flag) { ///イコールの前が演算子だったら
        btnVal = ''; ///イコールを取り消す
        flag = true; ///最後尾は演算子なのでflagはtrueのまま
    } else { ///イコールの前が演算子以外だったら
        displaySym.innerHTML = ''; ///ディスプレイに出力されている演算子を削除
        calc = '+'; ///calcを初期状態に戻す
        flag = false; ///最後尾は整数か小数点なのでflagをfalseに切り替える
    }
}

演算子が入力され且つ、その演算子がイコール以外だったら

入力値btnValが演算子且つ、その演算子がイコール以外だったときの処理は以下の通りです。

else { // 入力値btnValがイコール以外の演算子だったら
    displaySym.innerHTML = btnVal; ///入力したイコール以外の演算子をディスプレイに出力
    calc = btnVal; ///入力した演算子をcalcに代入
}

delが入力されたら

入力値btnValdelだったときの処理は以下の通りです。delはディスプレイに出力されている数値の最後尾を削除します。

if (btnVal == 'del') { ///入力値btnValがdelだったら
    var delResult = displayNum.innerHTML.substr(0, displayNum.innerHTML.length - 1); ///ディスプレイに出力されている値の最後尾を削除
    displayNum.innerHTML = delResult; ///ディスプレイを更新
    if (displayNum.innerHTML.length <= 0) { ///delを連打しているときに、ディスプレイに出力されている値が無くなったら
        delResult = 0; ///0を代入
        displayNum.innerHTML = delResult; ///ディスプレイに0を出力させる
        currentVal = ''; ///ディスプレイに出力されている値が無くなった後に再び値を入力したときに、直前まで保存していたcurrentValの値が出力されるのを防ぐため、currenValを空にする
    }
}

caが入力されたら

入力値btnValcaだったときの処理は以下の通りです。caはディスプレイを初期状態に戻します。

/* 合計値、演算子、現在の入力値、ディスプレイを初期状態に戻す */
if (btnVal == 'ca') {///入力値btnValがcaだった
    total = 0;
    calc = '+';
    currentVal = '';
    displayNum.innerHTML = total;
    displaySym.innerHTML = '';
}

ceが入力されたら

入力値btnValceだったときの処理は以下の通りです。ceは、イコールを押していないときのみ、現在の入力値を取り消します。

if (btnVal == 'ce') {///入力値btnValがceだったら
    currentVal = 0; ///現在の入力値を0に
    displayNum.innerHTML = currentVal; ///ディスプレイに0を出力
    currentVal = ''; ///次の入力値を確保するために、現在の入力値を空に
}

以上で、HTML+CSS+JavaScriptによる簡易電卓の作り方を終わります。

参考文献