質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.33%

  • JavaScript

    17609questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

JSで指定した日時までカウントダウンする処理を画像で表示したい

受付中

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 99

前提・実現したいこと

指定した日時までカウントダウンする処理を画像で表示するJSを実装しました。
参考サイト
http://cly7796.net/wp/javascript/countdown-image-timer/

下記のソースで1つはカウンターが設置されるのですが、別の日付をもう一つカウンターを表示させたいと思っています。
どのようにしたらもう一つ別の日付でカウンターが作れるでしょうか?

追記

日付の違う2つのイベントがあり、HPを開いたときに、それぞれのイベントまで●日というカウンターを出したいと思います。
時間・秒数は必要なく日付のみ表示させたいと思います。

Javascript

// 期限の設定
var gYear = 2020, // 年
    gMonth = 7, // 月
    gDay = 24, // 日
    gHour = 0, // 時
    gMinute = 0, // 分
    gSecond = 0; // 秒

var goal = new Date(gYear, gMonth-1, gDay, gHour, gMinute, gSecond);

// 画像の高さの設定
var numHeight = 22;

// 使用する変数
var currentTime, period,
    cDay, cDayHundred, cDayTen, cDayOne,
    cHour, cHourTen, cHourOne,
    cMinute, cMinuteTen, cMinuteOne,
    cSecond, cSecondTen, cSecondOne,
    cFlame, cFlameTen, cFlameOne,
    insert = "";

// カウント用画像の指定
var dayThousand = document.getElementById('day-thousand'),
    dayHundred = document.getElementById('day-hundred'),
    dayTen = document.getElementById('day-ten'),
    dayOne = document.getElementById('day-one'),
    hourTen = document.getElementById('hour-ten'),
    hourOne = document.getElementById('hour-one'),
    minuteTen = document.getElementById('minute-ten'),
    minuteOne = document.getElementById('minute-one'),
    secondTen = document.getElementById('second-ten'),
    secondOne = document.getElementById('second-one'),
    flameTen = document.getElementById('flame-ten'),
    flameOne = document.getElementById('flame-one');

// カウントダウンの処理
function countdown() {

    // 現在から期限日までの差を取得
    currentTime = new Date();
    period = goal.getTime() - currentTime.getTime();

    // 期限を過ぎていない時
    if(period >= 0) {
        // 日数を取得
        cDay = Math.floor(period / (1000 * 60 * 60 * 24));
        period -= (cDay * (1000 * 60 * 60 * 24));
        // 桁数を4桁に揃える
        cDay = String(cDay);
        while(cDay.length < 4) {
            cDay = '0' + cDay;
        }
        // 画像の切り替え
        dayThousand.style.top = (- cDay.substr(0, 1) * numHeight) + 'px';
        dayHundred.style.top = (- cDay.substr(1, 1) * numHeight) + 'px';
        dayTen.style.top = (- cDay.substr(2, 1) * numHeight) + 'px';
        dayOne.style.top = (- cDay.substr(3, 1) * numHeight) + 'px';

        // 時間を取得
        cHour = Math.floor(period / (1000 * 60 * 60));
        period -= (cHour * (1000 * 60 * 60));
        // 桁数を2桁に揃える
        cHour = String(cHour);
        while(cHour.length < 2) {
            cHour = '0' + cHour;
        }
        // 画像の切り替え
        hourTen.style.top = (- cHour.substr(0, 1) * numHeight) + 'px';
        hourOne.style.top = (- cHour.substr(1, 1) * numHeight) + 'px';

        // 分を取得
        cMinute = Math.floor(period / (1000 * 60));
        period -= (cMinute * (1000 * 60));
        // 桁数を2桁に揃える
        cMinute = String(cMinute);
        while(cMinute.length < 2) {
            cMinute = '0' + cMinute;
        }
        // 画像の切り替え
        minuteTen.style.top = (- cMinute.substr(0, 1) * numHeight) + 'px';
        minuteOne.style.top = (- cMinute.substr(1, 1) * numHeight) + 'px';

        // 秒を取得
        cSecond = Math.floor(period / (1000));
        period -= (cSecond * (1000));
        // 桁数を2桁に揃える
        cSecond = String(cSecond);
        while(cSecond.length < 2) {
            cSecond = '0' + cSecond;
        }
        // 画像の切り替え
        secondTen.style.top = (- cSecond.substr(0, 1) * numHeight) + 'px';
        secondOne.style.top = (- cSecond.substr(1, 1) * numHeight) + 'px';

        // フレーム
        cFlame = Math.floor(period / (10));
        // 桁数を2桁に揃える
        cFlame = String(cFlame);
        while(cFlame.length < 2) {
            cFlame = '0' + cFlame;
        }
        // 画像の切り替え
        flameTen.style.top = (- cFlame.substr(0, 1) * numHeight) + 'px';
        flameOne.style.top = (- cFlame.substr(1, 1) * numHeight) + 'px';

        // カウントダウンの処理を再実行
        setTimeout(countdown, 10);

    // 期限を過ぎた時
    } else {

    }
}

// 処理の実行
countdown();

HTML

<div id="countdown-unit">
    <div><img src="num.gif" width="20" height="220" id="day-thousand"></div>
    <div><img src="num.gif" width="20" height="220" id="day-hundred"></div>
    <div><img src="num.gif" width="20" height="220" id="day-ten"></div>
    <div><img src="num.gif" width="20" height="220" id="day-one"></div>
    <div><img src="day.gif" width="20" height="22"></div>
    <div><img src="num.gif" width="20" height="220" id="hour-ten"></div>
    <div><img src="num.gif" width="20" height="220" id="hour-one"></div>
    <div><img src="time.gif" width="20" height="22"></div>
    <div><img src="num.gif" width="20" height="220" id="minute-ten"></div>
    <div><img src="num.gif" width="20" height="220" id="minute-one"></div>
    <div><img src="time.gif" width="20" height="22"></div>
    <div><img src="num.gif" width="20" height="220" id="second-ten"></div>
    <div><img src="num.gif" width="20" height="220" id="second-one"></div>
    <div><img src="time.gif" width="20" height="22"></div>
    <div><img src="num.gif" width="20" height="220" id="flame-ten"></div>
    <div><img src="num.gif" width="20" height="220" id="flame-one"></div>
</div>

CSS

#countdown-unit div {
    position: relative;
    float: left;
    width: 20px;
    height: 22px;
    overflow: hidden;
}
#countdown-unit div img {
    position: absolute;
    top: 0;
    left: 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2018/12/06 08:57

    了解です。ただ、本当に全てそのままコピペで動くコードを提示してしまうと質問者さんのためにもなりませんし、ヒント回答にコードと解説をつけるような形で提示しようと思います。(ロジック部分はある程度使いまわせるかなあと)

    キャンセル

  • niwaka_design

    2018/12/06 08:59

    ありがとうございます。しっかり勉強いたします!

    キャンセル

  • mts10806

    2018/12/06 10:30

    あとすみません。回答はしているのですが、「初心者」は要件とも違いますし、質問編集画面から「初心者アイコン」がつけられるので、それだけにとどめていただけますか?

    キャンセル

回答 2

+2

ちょっとコードの調整と文章の準備に時間がかかってしまいましたが、回答します。

まず元々のコードについて。

「画像の使い方」はCSSスプライトと言う技法を用いています。(リンク先参照)
ざっくり言うと画像を個数分用意するのではなく1つにまとめ、必要な領域だけをCSSで制御して表示させる技法ですね。
今回は全て数字で0から始まっていて1つ1つの高さ・幅が決まっているので
あてられた数字が決まればその画像の最上部から何pxの位置から表示させればいいか決まるので、その分styleのtopの位置をずらして数字がさも入れ替わったように見せています。

あと、複数設置したい場合ですが、
同じHTML内に同じIDは1つのみというルールがあります(idはidentification の略。つまり唯一であることが証明されている情報と言うことです)
そのためには「HTML構造はそのままで別IDを用意する」が一点。

また、getElementById()でそれぞれを取得してきて変数におさめていますが、
これも「別の変数を用意する」必要が出てきますね。
「別の変数を用意する」となると、countdown()の中で使われている変数は全て最初のものですから、処理も倍用意する必要が出てきます。

つまり、速攻で実現したいのでしたら
「HTMLも処理も倍準備する」という風になります。

コメントで「ヒント回答のみだと一言」というのは上記のように単純に実現したいならHTMLも処理も倍準備するということになります。

でもちょっと待ってください。

処理内容はほぼ同じ内容で、結局違うのは「止めたい位置(今回は日付)」だけですよね。
もしこれで何個もカウントダウンタイマーを設置したいとなったら何個もHTMLと処理を用意しなければならないのか、それって増えれば増えるほど重たくなるじゃん!
となれば、実はそこからがスタートです。

JavaScriptにはcreateElementというものがあり、HTMLタグを生成する機能があります。
配列や配列のループで同じ内容の処理を別の値に対して行うこともできます。

つまり、JavaScriptで配列をループさせて動的にHTMLを作るようにし、countdown()処理もループで処理すれば、何個に増えたとしても対応可能ということになります。

下記、日付ではありませんが、別々の開始点を以て、数字をカウントダウンさせる処理をざっと作ってみました。
配列部分の数値をかえたり要素を追加すれば、とりあえず何個でも何桁でも関係なくできるようになっています。
0になったら「完」と表示してそれ以上カウントダウンしないようにしてあります。
参考にしてみてください。

<div id="countdown_timer"></div>
div#countdown_timer div div {
    position: relative;
    float: left;
    width: 20px;
    height: 22px;
    overflow: hidden;
}
div#countdown_timer div div img {
    position: absolute;
    top: 0;
    left: 0;
}
var countdown_timer = document.getElementById("countdown_timer");

//タイマー用
var timer_set = [10,26,349];
// 画像の高さの設定    
var numHeight = 22;

//画面load時にタイマーを設置
window.onload = function(){
    for(var i=0;i<timer_set.length;i++){//タイマー設定分ループ
        var timer_div = document.createElement("div");
        timer_div.setAttribute("id","countdown-unit_"+i);
        timer_div.setAttribute("data-seconds",timer_set[i]);//現在の秒数を保管
        timer_div.style.clear = "both"; //タイマーごとに改行

        var set_timer_arr = String(timer_set[i]).split(''); //設定値を分割してimg作る
        for(set_i=0;set_i<set_timer_arr.length;set_i++){
            var timer_img_div = document.createElement("div");//画像を生成
            var timer_img = document.createElement("img");//画像を生成
            timer_img.setAttribute("id","unit_"+i+"_"+set_i);//画像のラッパー
            timer_img.setAttribute("width","20px");
            timer_img.setAttribute("height","220px");
            timer_img.src = "num.gif";
            timer_img.style.top = -(numHeight*parseInt(set_timer_arr[set_i]))+"px";//表示位置

            //タイマーimg追記
            timer_img_div.appendChild(timer_img);
            timer_div.appendChild(timer_img_div);
        }
        //タイマーi生成
        countdown_timer.appendChild(timer_div);
    }
    // 処理の実行
    countdown();
};
// カウントダウンの処理
function countdown() {
    for(var i=0;i<timer_set.length;i++){//タイマー設定分ループ
        var timer_div = document.getElementById("countdown-unit_"+i);
        var timer_seconds = timer_div.dataset.seconds;
        if(parseInt(timer_div.dataset.seconds) != 0){//完了していないタイマーのみ処理を行う
            var count_down_seconds = parseInt(timer_div.dataset.seconds) - 1;
            timer_div.dataset.seconds = count_down_seconds;
            timer_div.innerHTML = "";//いったんクリア
            var set_timer_arr = String(count_down_seconds).split(''); //設定値を分割してimg作る
            for(set_i=0;set_i<set_timer_arr.length;set_i++){
                var timer_img_div = document.createElement("div");//画像を生成
                var timer_img = document.createElement("img");//画像を生成
                timer_img.setAttribute("id","unit_"+i+"_"+set_i);//画像のラッパー
                timer_img.setAttribute("width","20px");
                timer_img.setAttribute("height","220px");
                timer_img.src = "num.gif";
                timer_img.style.top = -(numHeight*parseInt(set_timer_arr[set_i]))+"px";//表示位置

                //タイマーimg追記
                timer_img_div.appendChild(timer_img);
                timer_div.appendChild(timer_img_div);
            }
            if(count_down_seconds === 0){ //0の場合は完了
                var timer_end_div = document.createElement("div");//画像を生成
                timer_end_div.innerHTML = "完";
                timer_div.appendChild(timer_end_div);
            }
        }
    }
    setTimeout(countdown, 1000);//毎秒実行
}

補足

setTimeout()の第2引数はミリ秒で指定します。1000で1秒です。
10ということは1/100秒ですね。
日付のみのカウントダウンにするのであれば、1/100秒毎に実行する意味あまりないように思います。
TWENTY FOURみたいにするのであれば1/100秒でも見栄えがしますが、数字が切り替わるのが日付の切り替わりと同時なので1秒(設定値:1000)で充分かなと。

「時間・秒数は必要なく日付のみ」なのであれば時・分・秒に関するHTMLとJavaScriptの記述を削除するだけすね。これは自分でもやってみてください。

つまり、実現のためのステップが必要になります。

  1. 質問に提示されている単体のタイマーから時分秒を取り除いた状態のものを作って動作確認
  2. 1.のHTML部分をcreateElementで生成するように修正する
  3. 2.の状態でタイマーが動くか動作確認
  4. 配列で日付を定義してループし、HTMLを生成するように修正する(タイマーはまだ仕掛けない)
  5. タイマーで配列で定義した日付をループし、それぞれカウントダウンを行う

※日付のカウントダウンですが、1日毎にしかカウントダウンを確認できないので、動作確認のため秒の部分は残しておいて出来上がったあとに削除のほうが良いかも・・・。

参考:

蛇足:
日付を扱うのであればmoment.jsというのが非常に楽です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/06 19:24

    丁寧に解説いただきありがとうございました!1個づつやってみます。

    キャンセル

  • 2018/12/06 20:09

    私の視点での手順なのでイメージ難しいところありましたらもう少し細分化してみてください。

    キャンセル

+2

ざっくりした回答
命題:カウンタで1箇所書き換えていたものを2箇所書き換えにしたい

対策としては3つの内のどれかでやればよいでしょう

  • ほぼ同じ内容の関数を2つ作ってそれぞれ回転させる
  • 1つの関数の中に2箇所書き換える処理をいれる
  • 1つの関数を使うが引数を指定して2回まわす

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/06 19:25

    ありがとうございます。やってみますね。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    17609questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。