

下記のコードは、アナログの目覚まし時計で、設定した”目安針(=時計の逆回りのライム色の針)”に“時間針(=シルバー色の短い針)”が接触したら、BGSOUND(＊IEの独自仕様です)を使ってアラームが鳴るように試みた(*質問のコードでは、アラームは鳴りません)のですが、”目安針”に“時間針”が接触していなくても『設定ボタン』を押すと、すぐにアラームが鳴ります。  
設定した”目安針”に“時間針”が接触した場合に、アラームが鳴るようにするには、どのように書けばいいでしょうか。

関連個所は `function timeCheck(){}` と `function changeFlg(){}` ，及び `function
ClockAndAssign(){}` の３カ所です。

なお、大元のコードは、下記のサイト内にあります。

<https://gist.github.com/timw4mail/2637218>

[code]

    <html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    
             <bgsound id="bgm" src="〇〇〇.mid" loop="-1">
    
    <style>
       body { background-color:black; }
    </style>
    
    </head>
    
    <body>
    
    <div id="clock">
        <div id="Od" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Of" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Oh" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Om" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Os" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Oa" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
    </div>
    
    <script type="text/javascript">
    
     var alarm = "解除"; //アラームフラグを初期化する。
    
     function timeCheck(){
    
    
     AL1=document.getElementById('Oa').style.top;
     AL2=document.getElementById('Oa').style.left;
     HL1=document.getElementById('Oh').style.top;
     HL2=document.getElementById('Oh').style.left;
    
            if((alarm == "設定") && ((HL1 == AL1) && (HL2 == AL2))){
                            alarm = "鳴る";
    　　　　　　　　        document.sampleForm.setAlarm.value="  Reset  ";
                            bgm.src="△△△.wav";
              }
    }
    
     function changeFlg(){
    
    
        if(alarm == "解除"){ //アラーム未設定時、
            alarm = "設定";
    　　　　　　　　document.sampleForm.setAlarm.value="  Reset  ";
                    bgm.src="";
        }else if(alarm == "設定"){ //アラーム設定済み時
    　　　　    alarm = "解除";
            document.sampleForm.setAlarm.value=" Set Alarm！";
                    bgm.src="〇〇〇.mid";
        }else{ //アラームが鳴っている時
    　　　　    alarm = "解除";
            document.sampleForm.setAlarm.value=" Set Alarm！";
                    bgm.src="〇〇〇.mid";
         }
    }
    
    　　//次の更新をセットする。
         setInterval(timeCheck,100);
                  window.onload = timeCheck;
    
    
    (function(){
        "use strict";
        
    function $(sel)
    {
        return document.getElementById(sel);
    }
        
    function $$(sel)
    {
        if (typeof document.getElementsByClassName === 'undefined')
        {
            return document.getElementsByName(sel);
        }
        
        return document.getElementsByClassName(sel);
    }
    
    
    var dCol = '00ff00', //date colour.
        fCol = '0000ff', //face color,
        sCol = 'ff0000', //seconds colour,
        mCol = 'silver', //minutes colour,
        hCol = 'silver', //hours colour,
        aCol = 'lime', //alarm color,
        ClockHeight = 40,
        ClockWidth = 40,
        ClockFromMouseY = -100,
        ClockFromMouseX = 0;
    
    
    var TodaysDate = "                            ";
    
      /*最大文字数を28文字に設定(""内に半角で28文字分スペースを作る)。
         ・最大曜日:Wednesday(９文字)
         ・最大月日:September(９文字),２桁(２文字)
         ・西暦:１千年代(４文字)
         ・スペース:４個(４文字)*/
    
    var D = TodaysDate.split('');
    var H = '...';
        H = H.split('');
    var M = '....';
        M = M.split('');
    var S = '.....';
        S = S.split('');
    var A = '.....';
        A = A.split('');
    var Face = '1 2 3 4 5 6 7 8 9 10 11 12',
        font = 'Helvetica, Arial, sans-serif',
        size = 1,
        speed = 0.6;
        Face = Face.split(' ');
    var n = Face.length;
    var a = size * 10;
    var ymouse = 0,
        xmouse = 0,
        scrll = 0,
        props = '<span style="font-family:' + font + ';font-size:' + size + 'em; color:#' + fCol + '">',
        props2 = '<span style="font-family:' + font + ';font-size:' + size + 'em; color:#' + dCol + '">';
    var Split = 360 / n;
    var Dsplit = 360 / D.length;
    var HandHeight = ClockHeight / 4.5; 
    var HandWidth = ClockWidth / 4.5;
    var HandY = -7,
        HandX = -2.5,
        step = 0.02, // 外周の回転速度
        currStep = 0,
            step2 = 0.02, // 目安針の回転速度
        currStep2 = 0,
        y = [],
        x = [],
        Y = [],
        X = [],
        Dy = [],
        Dx = [],
        DY = [],
        DX = [];
    
    var i;
        
    for (i = 0; i < n; i++) 
    {
        y[i] = 0;
        x[i] = 0;
        Y[i] = 0;
        X[i] = 0;
    }
    
    for (i = 0; i < D.length; i++) 
    {
        Dy[i] = 0;
        Dx[i] = 0;
        DY[i] = 0;
        DX[i] = 0;
    }
    
    var wrapper = $('clock');
    var html = '';
    
    
    // Date wrapper
    html = '';
    for (i = 0; i < D.length; i++)
    {
        html += '<div class="Date" name="Date" style="position:absolute;top:0px;left:0;height:' + a + ';width:' + a + ';text-align:center">' + props2 + D[i] + '</span></div>';
    }
    $('Od').children[0].innerHTML = html;
    
    // Face wrapper
    html = '';
    for (i = 0; i < n; i++) 
    {
        html += '<div class="Face" name="Face" style="position:absolute;top:0px;left:0;height:' + a + ';width:' + a + ';text-align:center">' + props + Face[i] + '</span></div>';
    }
    $('Of').children[0].innerHTML = html;
    
    // Hours wrapper
    html = '';
    for (i = 0; i < H.length; i++)
    {
        html += '<div class="Hours" name="Hours" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + hCol + ';text-align:center;font-weight:bold">' + H[i] + '</div>';
    } 
    $('Oh').children[0].innerHTML = html;
    
    // Minute wrapper
    html = '';
    for (i = 0; i < M.length; i++)
    {
        html += '<div class="Minutes" name="Minutes" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + mCol + ';text-align:center;font-weight:bold">' + M[i] + '</div>';
    } 
    $('Om').children[0].innerHTML = html;
    
    // Seconds wrapper
    html = '';
    for (i = 0; i < S.length; i++)
    {
        html += '<div class="Seconds" name="Seconds" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + sCol + ';text-align:center;font-weight:bold">' + S[i] + '</div>';
    } 
    $('Os').children[0].innerHTML = html;
    
    // Alarm wrapper
    html = '';
    for (i = 0; i < A.length; i++)
    {
        html += '<div class="Alarm" name="Alarm" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + aCol + ';text-align:center;font-weight:bold">' + A[i] + '</div>';
    } 
    $('Oa').children[0].innerHTML = html;
    
    // Mouse move event handler
    function Mouse(evnt) 
    {
        if (typeof evnt === 'undefined')
        {
            ymouse = event.Y + ClockFromMouseY;
            xmouse = event.X + ClockFromMouseX;
        }
        else
        {
            ymouse = evnt.clientY + ClockFromMouseY;
            xmouse = evnt.clientX + ClockFromMouseX;
        }
    
        
    }
    document.onmousemove = Mouse;
    
    
     function ClockAndAssign() 
     {
      var   d = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
        m = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
        date = new Date(),
        day = date.getDate(),
        year = date.getYear() + 1900;
      var   TodaysDate = " " + d[date.getDay()] + " " + day + " " + m[date.getMonth()] + " " + year;
    
      var D = TodaysDate.split('');
      var Dsplit = 360 / D.length;
      var props2 = '<span style="font-family:' + font + ';font-size:' + size + 'em; color:#' + dCol + '">';
    
     // Date wrapper
      html = '';
       for (i = 0; i < D.length; i++)
      {
        html += '<div class="Date" name="Date" style="position:absolute;top:0px;left:0;height:' + a + ';width:' + a + ';text-align:center">' + props2 + D[i] + '</span></div>';
      }
       $('Od').children[0].innerHTML = html;
    
    
        if(alarm == "解除"){ //アラーム未設定時、
                step=0.02; step2=0.01;
        }else if(alarm == "設定"){ //アラーム設定済み時
                step=0; step2=0;
        }else{ //アラームが鳴っている時
                step=0.02; step2=0;
            }
    
        var time = new Date();
        var secs = time.getSeconds();
        var sec = -1.57 + Math.PI * secs / 30;
        var mins = time.getMinutes();
        var min = -1.57 + Math.PI * mins / 30;
        var hr = time.getHours();
        var hrs = -1.575 + Math.PI * hr / 6 + Math.PI * parseInt(time.getMinutes(), 10) / 360;
    
        $('Od').style.top = window.document.body.scrollTop;
        $('Of').style.top = window.document.body.scrollTop;
        $('Oh').style.top = window.document.body.scrollTop;
        $('Om').style.top = window.document.body.scrollTop;
        $('Os').style.top = window.document.body.scrollTop;
        $('Oa').style.top = window.document.body.scrollTop;
    
        for (i = 0; i < n; i++)
        {
            var F = $$('Face')[i].style;
            F.top = y[i] + ClockHeight * Math.sin(-1.0471 + i * Split * Math.PI / 180) + scrll;
            F.left = x[i] + ClockWidth * Math.cos(-1.0471 + i * Split * Math.PI / 180);
        }
        for (i = 0; i < H.length; i++)
        {
            var HL = $$('Hours')[i].style;
            HL.top = y[i] + HandY + (i * HandHeight) * Math.sin(hrs) + scrll;
            HL.left = x[i] + HandX + (i * HandWidth) * Math.cos(hrs);
        }
        for (i = 0; i < M.length; i++)
        {
            var ML = $$('Minutes')[i].style;
            ML.top = y[i] + HandY + (i * HandHeight) * Math.sin(min) + scrll;
            ML.left = x[i] + HandX + (i * HandWidth) * Math.cos(min);
        }
        for (i = 0; i < S.length; i++)
        {
            var SL = $$('Seconds')[i].style;
            SL.top = y[i] + HandY + (i * HandHeight) * Math.sin(sec) + scrll;
            SL.left = x[i] + HandX + (i * HandWidth) * Math.cos(sec);
        }
        for (i = 0; i < A.length; i++)
        {
            var AL = $$('Alarm')[i].style;
            AL.top = y[i] + HandY + (i * HandHeight) * Math.sin(currStep2 ) + scrll;
            AL.left = x[i] + HandX + (i * HandWidth) * Math.cos(currStep2 );
        }
        for (i = 0; i < D.length; i++)
        {
            var DL = $$('Date')[i].style;
            DL.top = Dy[i] + ClockHeight * 1.5 * Math.sin(currStep + i * Dsplit * Math.PI / 180) + scrll;
            DL.left = Dx[i] + ClockWidth * 1.5 * Math.cos(currStep + i * Dsplit * Math.PI / 180);
        }
        currStep -= step;
        currStep2 -= step2;
    }
    
    function Delay() 
    {
        scrll = 0;
        Dy[0] = Math.round(DY[0] += ((ymouse) - DY[0]) * speed);
        Dx[0] = Math.round(DX[0] += ((xmouse) - DX[0]) * speed);
        for (i = 1; i < D.length; i++) {
            Dy[i] = Math.round(DY[i] += (Dy[i - 1] - DY[i]) * speed);
            Dx[i] = Math.round(DX[i] += (Dx[i - 1] - DX[i]) * speed);
        }
        y[0] = Math.round(Y[0] += ((ymouse) - Y[0]) * speed);
        x[0] = Math.round(X[0] += ((xmouse) - X[0]) * speed);
        for (i = 1; i < n; i++) {
            y[i] = Math.round(Y[i] += (y[i - 1] - Y[i]) * speed);
            x[i] = Math.round(X[i] += (x[i - 1] - X[i]) * speed);
        }
        ClockAndAssign();
        setTimeout(Delay, 20);
    }
    
    Delay();
    }());
    </script>
    
       <FORM NAME="sampleForm">
         <INPUT id="sAlarm" type="button" name="setAlarm" style="position:absolute;left:50%; top:50%;" value=" Set Alarm！" onClick="changeFlg();">
    </form>
    
    </body>
    </html>
    
[/code]


CC BY-SA 4.0
2021-07-16T09:23:46.103
78229
2021-08-06T09:45:47.250
2021-07-17T07:34:23.463
3060
44018
question
javascript
アナログの目覚まし時計で、設定した”目安針”に“時間針”が接触したら、アラームが鳴るようにしたい。


まず、なぜすぐにアラームが鳴ってしまうか確認してみましょう。

ブラウザには、開発者ツールと強力なデバッグツールがあるので、 `timeCheck` 関数の所にブレークポイントを置いてみて、  
`if((alarm == "設定") && ((HL1 == AL1) && (HL2 == AL2)))`  
の評価がどのように行われているのか確認してみます。  
[![開発者ツールの状態](https://i.stack.imgur.com/LuUns.png)](https://i.stack.imgur.com/LuUns.png)

すると、 HL1 も AL1 も HL2 も AL2 も 全部 0px であることがわかりますね。

ここで、あなたはハッと気づくはずです。  
回転している針は、 `id="Oh"` や `id="Oa"` の div 要素ではなく、 その下に動的に作られている `<div
class="Hours" ... />` や `<div class="Alarm" ... />` の要素であると。

* * *

では、回転している div 要素の座標で比較すれば良いのか？ …というと、それも **違います。**

なぜなら、 **短針と目安針が完全に重なることはまず無い** からです。

現実のアナログ時計を古典物理の世界で見た場合、 短針は連続的に動くので、どこかの一瞬のタイミングでは必ず針が重なります。

しかし、このブラウザで動くアナログ時計は、 100ms 毎に針の位置が更新され 針の動きが離散的（連続的ではない）うえに、
針の座標の計算もかなりざっくりとした近似値です。  
このため、 一見針が重なっているように見えても、実際には小数点単位でのズレがほぼ確実に発生します。

* * *

では、どうやって目安針と短針が交差した事を検出すれば良いでしょうか？

針の位置が **「前回位置をチェックしたときは目安針の前にあったけど、今回は目安針と同じか後ろにある」** ことを条件にすれば良さそうですね。

このような比較は、 1次元的な値で確認する方がやりやすいので、 2次元的な値であるXY座標による条件チェックは適切ではなさそうです。

「時間の値そのもの」 か、 「針の角度」 あたりが良さそうです。  
今回はアナログ時計らしく、後者の「針の角度」でやってみましょう。

座標の計算にサイン・コサインの三角関数を取り扱うため、角度は 0°～360° の度数法ではなく、 0～2π のラジアン法で扱います。  
また、元のコードに倣って、時計の 12時 の位置から時計回りに値が増えていくようになっています。

[code]

    <html>
    <head>
        <meta charset="utf-8" />
        <title></title>
    
             <bgsound id="bgm" src="〇〇〇.mid" loop="-1">
    
    <style>
       body { background-color:black; }
    </style>
    
    </head>
    
    <body>
    
    <div id="clock">
        <div id="Od" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Of" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Oh" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Om" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Os" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
        <div id="Oa" style="position:absolute;top:0px;left:0px">
            <div style="position:relative">
            </div>
        </div>
    </div>
    
    <form NAME="sampleForm">
      <input id="sAlarm" type="button" name="setAlarm" style="position:absolute;left:50%; top:50%;" value=" Set Alarm！">
    </form>
    
    <script type="text/javascript">
    
    (function(){
        "use strict";
        
    function $(sel)
    {
        return document.getElementById(sel);
    }
        
    function $$(sel)
    {
        if (typeof document.getElementsByClassName === 'undefined')
        {
            return document.getElementsByName(sel);
        }
        
        return document.getElementsByClassName(sel);
    }
    
    // Number.isNaN polyfill for IE11
    Number.isNaN = Number.isNaN || function isNaN(input) {
        return typeof input === 'number' && input !== input;
    }
    
    // ラジアン角度を、 0～2π (0°～360°) の間に正規化（ノーマライズ）する
    function normalizeRadian(rad) {
        return rad - 2 * Math.PI * Math.floor(rad / (2 * Math.PI));
    }
    
    let alarm = "解除"; //アラームフラグを初期化する。
    let normalizedLastRadian = Number.NaN;
    let normalizedAlarmRadian = Number.NaN;
    
    // 針の角度を引数に受け取り、 アラームの目安針と交差したからアラームを鳴らす関数
    function timeCheck (curRadian) {
        let normalizedCurRadian = normalizeRadian(curRadian);
    
        // 前回 (lastRadian) より 今回 (curRadian) の方が正規化した角度が小さい場合、現在の針の角度が 2π に達して 0 に戻ったということなので、
        // 目安針の位置が、 12時 (0rad) より手前に存在する場合と、 12時 (0rad) より後ろに存在する場合の 2パターン考えなければならない。
        let handIsOverflowed = normalizedCurRadian < normalizedLastRadian;
        if ( 
            (alarm == "設定")
         && (
                (normalizedLastRadian < normalizedAlarmRadian && normalizedAlarmRadian <= normalizedCurRadia)
             || (handIsOverflowed && normalizedLastRadian - 2 * Math.PI < normalizedAlarmRadian && normalizedAlarmRadian <= normalizedCurRadia)
             || (handIsOverflowed && normalizedLastRadian < normalizedAlarmRadian && normalizedAlarmRadian <= normalizedCurRadia + 2 * Math.PI)
            )
        ) {
            console.log("アラーム再生開始");
            alarm = "鳴る";
            document.sampleForm.setAlarm.value="  Reset  ";
            bgm.src="△△△.wav";
        }
        normalizedLastRadian = normalizedCurRadian;
    }
    
    // ボタンを押したときのイベントハンドラ
    function changeFlg () {
        switch (alarm) {
            case "解除":
                alarm = "設定";
                document.sampleForm.setAlarm.value="  Reset  ";
                bgm.src="";
                break;
            case "設定":
            default:
                alarm = "解除";
                normalizedAlarmRadian = Number.NaN;
                document.sampleForm.setAlarm.value=" Set Alarm！";
                bgm.src="〇〇〇.mid";
                break;
        }
    }
    $("sAlarm").addEventListener('click', changeFlg);
    
    
    var dCol = '00ff00', //date colour.
        fCol = '0000ff', //face color,
        sCol = 'ff0000', //seconds colour,
        mCol = 'silver', //minutes colour,
        hCol = 'silver', //hours colour,
        aCol = 'lime', //alarm color,
        ClockHeight = 40,
        ClockWidth = 40,
        ClockFromMouseY = -100,
        ClockFromMouseX = 0;
    
    
    var TodaysDate = "                            ";
    
      /*最大文字数を28文字に設定(""内に半角で28文字分スペースを作る)。
         ・最大曜日:Wednesday(９文字)
         ・最大月日:September(９文字),２桁(２文字)
         ・西暦:１千年代(４文字)
         ・スペース:４個(４文字)*/
    
    var D = TodaysDate.split('');
    var H = '...';
        H = H.split('');
    var M = '....';
        M = M.split('');
    var S = '.....';
        S = S.split('');
    var A = '.....';
        A = A.split('');
    var Face = '1 2 3 4 5 6 7 8 9 10 11 12',
        font = 'Helvetica, Arial, sans-serif',
        size = 1,
        speed = 0.6;
        Face = Face.split(' ');
    var n = Face.length;
    var a = size * 10;
    var ymouse = 0,
        xmouse = 0,
        scrll = 0,
        props = '<span style="font-family:' + font + ';font-size:' + size + 'em; color:#' + fCol + '">',
        props2 = '<span style="font-family:' + font + ';font-size:' + size + 'em; color:#' + dCol + '">';
    var Split = 360 / n;
    var Dsplit = 360 / D.length;
    var HandHeight = ClockHeight / 4.5; 
    var HandWidth = ClockWidth / 4.5;
    var HandY = -7,
        HandX = -2.5,
        step = 0.02, // 外周の回転速度
        currStep = 0,
            step2 = 0.02, // 目安針の回転速度
        currStep2 = 0,
        y = [],
        x = [],
        Y = [],
        X = [],
        Dy = [],
        Dx = [],
        DY = [],
        DX = [];
    
    var i;
        
    for (i = 0; i < n; i++) 
    {
        y[i] = 0;
        x[i] = 0;
        Y[i] = 0;
        X[i] = 0;
    }
    
    for (i = 0; i < D.length; i++) 
    {
        Dy[i] = 0;
        Dx[i] = 0;
        DY[i] = 0;
        DX[i] = 0;
    }
    
    var wrapper = $('clock');
    var html = '';
    
    
    // Date wrapper
    html = '';
    for (i = 0; i < D.length; i++)
    {
        html += '<div class="Date" name="Date" style="position:absolute;top:0px;left:0;height:' + a + ';width:' + a + ';text-align:center">' + props2 + D[i] + '</span></div>';
    }
    $('Od').children[0].innerHTML = html;
    
    // Face wrapper
    html = '';
    for (i = 0; i < n; i++) 
    {
        html += '<div class="Face" name="Face" style="position:absolute;top:0px;left:0;height:' + a + ';width:' + a + ';text-align:center">' + props + Face[i] + '</span></div>';
    }
    $('Of').children[0].innerHTML = html;
    
    // Hours wrapper
    html = '';
    for (i = 0; i < H.length; i++)
    {
        html += '<div class="Hours" name="Hours" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + hCol + ';text-align:center;font-weight:bold">' + H[i] + '</div>';
    } 
    $('Oh').children[0].innerHTML = html;
    
    // Minute wrapper
    html = '';
    for (i = 0; i < M.length; i++)
    {
        html += '<div class="Minutes" name="Minutes" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + mCol + ';text-align:center;font-weight:bold">' + M[i] + '</div>';
    } 
    $('Om').children[0].innerHTML = html;
    
    // Seconds wrapper
    html = '';
    for (i = 0; i < S.length; i++)
    {
        html += '<div class="Seconds" name="Seconds" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + sCol + ';text-align:center;font-weight:bold">' + S[i] + '</div>';
    } 
    $('Os').children[0].innerHTML = html;
    
    // Alarm wrapper
    html = '';
    for (i = 0; i < A.length; i++)
    {
        html += '<div class="Alarm" name="Alarm" style="position:absolute;width:16px;height:16px;font-family:Arial;font-size:16px;color:' + aCol + ';text-align:center;font-weight:bold">' + A[i] + '</div>';
    } 
    $('Oa').children[0].innerHTML = html;
    
    // Mouse move event handler
    function Mouse(evnt) 
    {
        if (typeof evnt === 'undefined')
        {
            ymouse = event.Y + ClockFromMouseY;
            xmouse = event.X + ClockFromMouseX;
        }
        else
        {
            ymouse = evnt.clientY + ClockFromMouseY;
            xmouse = evnt.clientX + ClockFromMouseX;
        }
    
        
    }
    document.onmousemove = Mouse;
    
    
     function ClockAndAssign() 
     {
      var   d = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
        m = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
        date = new Date(),
        day = date.getDate(),
        year = date.getYear() + 1900;
      var   TodaysDate = " " + d[date.getDay()] + " " + day + " " + m[date.getMonth()] + " " + year;
    
      var D = TodaysDate.split('');
      var Dsplit = 360 / D.length;
      var props2 = '<span style="font-family:' + font + ';font-size:' + size + 'em; color:#' + dCol + '">';
    
     // Date wrapper
      html = '';
       for (i = 0; i < D.length; i++)
      {
        html += '<div class="Date" name="Date" style="position:absolute;top:0px;left:0;height:' + a + ';width:' + a + ';text-align:center">' + props2 + D[i] + '</span></div>';
      }
       $('Od').children[0].innerHTML = html;
    
    
        if(alarm == "解除"){ //アラーム未設定時、
                step=0.02; step2=0.01;
        }else if(alarm == "設定"){ //アラーム設定済み時
                step=0; step2=0;
        }else{ //アラームが鳴っている時
                step=0.02; step2=0;
            }
    
        var time = new Date();
        var secs = time.getSeconds();
        var sec = -1.57 + Math.PI * secs / 30;
        var mins = time.getMinutes();
        var min = -1.57 + Math.PI * mins / 30;
        var hr = time.getHours();
        var hrs = -1.575 + Math.PI * hr / 6 + Math.PI * parseInt(time.getMinutes(), 10) / 360;
    
        $('Od').style.top = window.document.body.scrollTop;
        $('Of').style.top = window.document.body.scrollTop;
        $('Oh').style.top = window.document.body.scrollTop;
        $('Om').style.top = window.document.body.scrollTop;
        $('Os').style.top = window.document.body.scrollTop;
        $('Oa').style.top = window.document.body.scrollTop;
    
        for (i = 0; i < n; i++)
        {
            var F = $$('Face')[i].style;
            F.top = y[i] + ClockHeight * Math.sin(-1.0471 + i * Split * Math.PI / 180) + scrll;
            F.left = x[i] + ClockWidth * Math.cos(-1.0471 + i * Split * Math.PI / 180);
        }
        for (i = 0; i < H.length; i++)
        {
            var HL = $$('Hours')[i].style;
            HL.top = y[i] + HandY + (i * HandHeight) * Math.sin(hrs) + scrll;
            HL.left = x[i] + HandX + (i * HandWidth) * Math.cos(hrs);
        }
        for (i = 0; i < M.length; i++)
        {
            var ML = $$('Minutes')[i].style;
            ML.top = y[i] + HandY + (i * HandHeight) * Math.sin(min) + scrll;
            ML.left = x[i] + HandX + (i * HandWidth) * Math.cos(min);
        }
        for (i = 0; i < S.length; i++)
        {
            var SL = $$('Seconds')[i].style;
            SL.top = y[i] + HandY + (i * HandHeight) * Math.sin(sec) + scrll;
            SL.left = x[i] + HandX + (i * HandWidth) * Math.cos(sec);
        }
        for (i = 0; i < A.length; i++)
        {
            var AL = $$('Alarm')[i].style;
            AL.top = y[i] + HandY + (i * HandHeight) * Math.sin(currStep2 ) + scrll;
            AL.left = x[i] + HandX + (i * HandWidth) * Math.cos(currStep2 );
        }
        for (i = 0; i < D.length; i++)
        {
            var DL = $$('Date')[i].style;
            DL.top = Dy[i] + ClockHeight * 1.5 * Math.sin(currStep + i * Dsplit * Math.PI / 180) + scrll;
            DL.left = Dx[i] + ClockWidth * 1.5 * Math.cos(currStep + i * Dsplit * Math.PI / 180);
        }
    
        if (alarm === "設定" && Number.isNaN(normalizedAlarmRadian)) {
            normalizedAlarmRadian = normalizeRadian(currStep2);
        }
        timeCheck(hrs);
    
        currStep -= step;
        currStep2 = normalizeRadian(currStep2 - step2);
    }
    
    function Delay() 
    {
        scrll = 0;
        Dy[0] = Math.round(DY[0] += ((ymouse) - DY[0]) * speed);
        Dx[0] = Math.round(DX[0] += ((xmouse) - DX[0]) * speed);
        for (i = 1; i < D.length; i++) {
            Dy[i] = Math.round(DY[i] += (Dy[i - 1] - DY[i]) * speed);
            Dx[i] = Math.round(DX[i] += (Dx[i - 1] - DX[i]) * speed);
        }
        y[0] = Math.round(Y[0] += ((ymouse) - Y[0]) * speed);
        x[0] = Math.round(X[0] += ((xmouse) - X[0]) * speed);
        for (i = 1; i < n; i++) {
            y[i] = Math.round(Y[i] += (y[i - 1] - Y[i]) * speed);
            x[i] = Math.round(X[i] += (x[i - 1] - X[i]) * speed);
        }
        ClockAndAssign();
        setTimeout(Delay, 20);
    }
    
    Delay();
    }());
    </script>
    </body>
    </html>
    
[/code]

`timeCheck` 関数は、現在の針の角度を使う必要があるので、 `ClockAndAssign` 関数の最後の方で呼び出す形に変更しています。

目安針の角度を示す `normalizedAlarmRadian` の設定を、ボタンをクリックしたときに呼び出される `changeFlg`
関数内で計算するのは難しいです。  
このため、 `changeFlg` 関数で `alarm = "設定"` に設定した後、最初に `ClockAndAssign` 関数が実行されたときに
`normalizedAlarmRadian` を更新するようにしています。

ちなみに、 この書き方だと、 timeCheck の引数 (`hrs`) を長針の角度 (`min`) や秒針の角度 (`sec`)
を示す変数に書き換えてみても、期待通りに動くので、汎用性があります。  
実際に動かして検証しようとすると、短針が目安針と交差するまで待つのに時間がかかって骨が折れるので、秒針に置き換えてみると動作確認がしやすくなります。

なお、 JavaScript でコードを書く場合、やむを得なく外部から呼び出す必要がある場合を除き、 `"use strict"`
と先頭に書かれている無名関数の **中** に全てのロジックを書いた方が良いです。  
詳しくは "use strict" で調べてみてください。  
この変更のため、 `<input ...>` 要素の onClick 属性から、 `changeFlg` 関数が参照できない（スコープ外）になっているため、
`addEventListener` メソッドを使って JavaScript 内から click イベントハンドラの関数 (`changeFlg`)
の登録を行っています。

* * *

正直言うと、大本のコード自体が雑(ｹﾞﾌﾝｹﾞﾌﾝ  
書き方がかな～り古いです。

修正例として書いたコードも、今の時代ではふさわしくないコードになっています。

三角関数やロジックの勉強が目的であればこれでも良いのですが、これから JavaScript
学んでいく上では、もう少し最近に書かれたものにした方が良いと思います。  
JavaScript も、 HTML DOM も、この 10年で大きく書き方が変わってきているので。


CC BY-SA 4.0
2021-07-16T18:40:43.910
78238
2021-07-17T14:13:43.707
2021-07-17T14:13:43.707
8237
8237
78229
answer


"角度"では難しいようですので、時間と分を入力するテキストボックスを作り、  
そこにそれぞれ数値を入力して時間と分に一致させて、アラームを鳴らせる，  
とすれば簡単なようですが、目安針とリンクさせてもできるようです。  
まず、目安針の速度(step)を秒速で計測し(ｰ0.003148)、60秒のカウントダウンで  
1秒下がるごとに、それに当てはまる時間と分がテキストボックスに入力され、  
目覚ましを設定するのです。連続して設定すると誤差が生じますが、１回の設定では  
不満はありません。

＊なお、質問のコードでは、clearTimeoutが効かず、時間と分の表示がランダムに  
なってうまくいきません。分かる方は、改良点を示していただけたら、幸いです。

[code]

    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta http-equiv="Content-type" content="text/html; charset=Shift_JIS">
    <meta http-equiv="Content-Script-Type" content="text/javascript">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <title>kurt.grigg６-２■文字■　動く時計-日本語</title>
    
    <style type="text/css"><!--
    body{background:#000;}/*★背景色指定。黒色。不要なら削除*/
    #clockcontrol{position:fixed; top:100px; left:20px;}/*★時計用ボタンの固定位置指定。不要なら削除*/
    --></style>
    
    <bgsound id="bgm" src="〇〇〇.mid" loop="-1">
    
    </head>
    <body>
    
     <div style="position:relative;">
       <FORM NAME="sampleForm">
         <INPUT type="text" name="alarmH1" style="position:absolute;left:49%;top:450px; width:4%;" value="" disabled>
         <span style="position:absolute; left:53%; top:450px; color:gold; font-weight:bold;">：</span>
         <INPUT type="text" name="alarmM1" style="position:absolute;left:54%;top:450px; width:4%;" value="" disabled>
         <br>
         <INPUT id="sAlarm" type="button" name="setAlarm" style="position:absolute;left:50%; top:500px;" value="   Ready ？   " onClick="countdown();">
       </form>
     </div>
    
    <script type="text/javascript"><!--
    
    
    /*===================================================================
    動く時計　Silly Clock - http://www.btinternet.com/~kurt.grigg/javascript（閉鎖済）
    掲載サイト：http://www.kurtsdhtml.talktalk.net/　　　　★ソースを簡略化。日本語バージョンへ2017/02/15
    ====================================================================*/
    
     // 目安針の現在位置を、時間と分に換算する。
    
     var count1 = 59;
     var count2 = 0;
    
      function countdown() {
    
        if(count1 == count2){
              count1=59;}
        else{
              count1-=1;}
    
    if(count1 == 59){
     document.sampleForm.alarmH1.value = "2";
     document.sampleForm.alarmM1.value = "48";
     }
    else if(count1 == 58){
     document.sampleForm.alarmH1.value = "2";
     document.sampleForm.alarmM1.value = "36";
     }
    else if(count1 == 57){
     document.sampleForm.alarmH1.value = "2";
     document.sampleForm.alarmM1.value = "24";
     }
    else if(count1 == 56){
     document.sampleForm.alarmH1.value = 2;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 55){
     document.sampleForm.alarmH1.value = 2;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 54){
     document.sampleForm.alarmH1.value = 1;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 53){
     document.sampleForm.alarmH1.value = 1;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 52){
     document.sampleForm.alarmH1.value = 1;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 51){
     document.sampleForm.alarmH1.value = 1;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 50){
     document.sampleForm.alarmH1.value = 1;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 49){
     document.sampleForm.alarmH1.value = 12;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 48){
     document.sampleForm.alarmH1.value = 12;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 47){
     document.sampleForm.alarmH1.value = 12;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 46){
     document.sampleForm.alarmH1.value = 12;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 45){
     document.sampleForm.alarmH1.value = 12;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 44){
     document.sampleForm.alarmH1.value = 11;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 43){
     document.sampleForm.alarmH1.value = 11;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 42){
     document.sampleForm.alarmH1.value = 11;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 41){
     document.sampleForm.alarmH1.value = 11;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 40){
     document.sampleForm.alarmH1.value = 11;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 39){
     document.sampleForm.alarmH1.value = 10;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 38){
     document.sampleForm.alarmH1.value = 10;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 37){
     document.sampleForm.alarmH1.value = 10;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 36){
     document.sampleForm.alarmH1.value = 10;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 35){
     document.sampleForm.alarmH1.value = 10;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 34){
     document.sampleForm.alarmH1.value = 9;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 33){
     document.sampleForm.alarmH1.value = 9;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 32){
     document.sampleForm.alarmH1.value = 9;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 31){
     document.sampleForm.alarmH1.value = 9;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 30){
     document.sampleForm.alarmH1.value = 9;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 29){
     document.sampleForm.alarmH1.value = 8;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 28){
     document.sampleForm.alarmH1.value = 8;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 27){
     document.sampleForm.alarmH1.value = 8;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 26){
     document.sampleForm.alarmH1.value = 8;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 25){
     document.sampleForm.alarmH1.value = 8;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 24){
     document.sampleForm.alarmH1.value = 7;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 23){
     document.sampleForm.alarmH1.value = 7;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 22){
     document.sampleForm.alarmH1.value = 7;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 21){
     document.sampleForm.alarmH1.value = 7;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 20){
     document.sampleForm.alarmH1.value = 7;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 19){
     document.sampleForm.alarmH1.value = 6;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 18){
     document.sampleForm.alarmH1.value = 6;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 17){
     document.sampleForm.alarmH1.value = 6;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 16){
     document.sampleForm.alarmH1.value = 6;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 15){
     document.sampleForm.alarmH1.value = 6;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 14){
     document.sampleForm.alarmH1.value = 5;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 13){
     document.sampleForm.alarmH1.value = 5;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 12){
     document.sampleForm.alarmH1.value = 5;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 11){
     document.sampleForm.alarmH1.value = 5;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 10){
     document.sampleForm.alarmH1.value = 5;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 9){
     document.sampleForm.alarmH1.value = 4;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 8){
     document.sampleForm.alarmH1.value = 4;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 7){
     document.sampleForm.alarmH1.value = 4;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 6){
     document.sampleForm.alarmH1.value = 4;
     document.sampleForm.alarmM1.value = 12;
     }
    else if(count1 == 5){
     document.sampleForm.alarmH1.value = 4;
     document.sampleForm.alarmM1.value = 0;
     }
    else if(count1 == 4){
     document.sampleForm.alarmH1.value = 3;
     document.sampleForm.alarmM1.value = 48;
     }
    else if(count1 == 3){
     document.sampleForm.alarmH1.value= 3;
     document.sampleForm.alarmM1.value = 36;
     }
    else if(count1 == 2){
     document.sampleForm.alarmH1.value = 3;
     document.sampleForm.alarmM1.value = 24;
     }
    else if(count1 == 1){
     document.sampleForm.alarmH1.value = 3;
     document.sampleForm.alarmM1.value = 12;
     }
    else {
     document.sampleForm.alarmH1.value = 3;
     document.sampleForm.alarmM1.value = 0;
     }
     timerID = setTimeout(countdown,1000);
    }
    
     (function (){  //即時関数で囲んでグローバル変数を消すため、この行はこのままで
    
       //Configure here... //Clock colours
    
       var dCol='#0f0'; //date colour.★一番外の円周の色
       var fCol='#fff'; //face colour.★内側の円周の色
       var sCol='#acf'; //seconds colour.★秒針の色
       var mCol='#f0f'; //minutes colour.★分針の色
       var hCol='#f00'; //hours colour.★時間針の色
       var aCol='white'; //alarm colour.★時間針の色
    
       //Controls
       var del=0.6;     //follow mouse speed.★原本0.6。マウスが変形する速度。1で円のままになり0で停止。数値が小さいほど遅い
       var rep=30;      //run speed (setTimeout).★原本30。マウスを追う速度。数値が大きいほど遅い
       var step1 = 0.02; // 外周の回転速度
       var currStep1 = 0;
       var step2 = 0; // 目安針の回転速度
       var currStep2 = 0;
    
    //End.指定ここまで---------------------------------------------------------------------------------------------------
    
       var theDays=["日曜日","月曜日","火曜日","水曜日","木曜日","金曜日","土曜日"];//★日本語に修正
       var theMonths=["１月","２月","３月","４月","５月","６月","７月","８月","９月","１０月","１１月","１２月"];//★日本語に修正
       var r,h,w;
       var my=10;
       var mx=10;
       var timer=null;
       var ofy=-7;
       var ofx=-3;
       var ofst=70;
       var date=new Date();
       var day=date.getDate();
       var year=date.getFullYear();//最新修正
       var dt=" "+theDays[date.getDay()]+" "+theMonths[date.getMonth()]+" "+day+"日 "+year+"年";//★日本語に修正
       var todaysDate=dt.split(""),
           tdlen=todaysDate.length;
       var clockFace="3 4 5 6 7 8 9 10 11 12 1 2",
           cfa=clockFace.split(" "),
           cflen=cfa.length;
       var _h="...",
            hourfin=_h.split(""),
            hlen=hourfin.length;
       var _m="....",
            minfin=_m.split(""),
            mlen=minfin.length;
       var _s=".....",
            secfin=_s.split(""),
            slen=secfin.length;
       var _a=".....",
            alafin=_a.split(""),
            alen = alafin.length;
       var dims = 40;
       var Q1 = 360/cflen;
       var Q2 = 360/todaysDate.length;
       var handlen = dims/5.5;
       var dy=new Array(),
           dx=new Array(),
           zy=new Array(),
           zx=new Array();
       var A=new Array(),
           S=new Array(),
           M=new Array(),
           H=new Array(),
           Da=new Array(),
           Dt=new Array();
       var sum = tdlen + cflen + hlen + mlen + slen + alen + 1;
           for (i=0; i<sum; i++){
              dy[i]=0;dx[i]=0;zy[i]=0;zx[i]=0;
          }
    
       var cssk='position:absolute; top:0; left:0; font-family:Arial,sans-serif;text-align:center;';//■時計の共通のCSS指定
       var css1=cssk+'width:16px; height:16px; font-size:16px; font-weight:bold;';//■色以外の時計の針のCSS指定
       var css2=cssk+'width:10px; height:10px; font-size:10px;';//■色以外の時計の数字のCSS指定
    
         for (i=0; i<tdlen; i++){document.write('<div id="_date'+i+'" style="color:'+dCol+';'+css2+'">'+todaysDate[i]+'<\/div>');
                                 Dt[i]=document.getElementById("_date"+i).style;
       }
         for (i=0; i<cflen; i++){document.write('<div id="_face'+i+'" style="color:'+fCol+';'+css2+'">'+cfa[i]+'<\/div>');
                                 Da[i]=document.getElementById("_face"+i).style; 
       }
         for (i=0; i<hlen; i++){document.write('<div id="_hours'+i+'" style="color:'+hCol+';'+css1+'">'+hourfin[i]+'<\/div>');
                                 H[i]=document.getElementById("_hours"+i).style;
       }
         for (i=0; i<mlen; i++){document.write('<div id="_minutes'+i+'" style="color:'+mCol+';'+css1+'">'+minfin[i]+'<\/div>');
                                 M[i]=document.getElementById("_minutes"+i).style; 
       }
         for (i=0; i<slen; i++){document.write('<div id="_seconds'+i+'" style="color:'+sCol+';'+css1+'">'+secfin[i]+'<\/div>');
                                 S[i]=document.getElementById("_seconds"+i).style;     
       }
         for (i=0; i<alen; i++){document.write('<div id="_alarm'+i+'" style="color:'+aCol+';'+css1+'">'+alafin[i]+'<\/div>');
                                 A[i]=document.getElementById("_alarm"+i).style;     
       }
    
     function winsize(){
         h = window.innerHeight-18;
         w = window.innerWidth-18;
      }
    
    
     function scrl(yx){
      var y,x;
        y=window.pageYOffset;
        x=window.pageXOffset;
      return (yx===0)?y:x;
      }
    
     function mouse(e){
      var msy=window.pageYOffset;
        my=e.pageY+ofst-msy;
        mx= e.pageX+ofst;
      }
       document.onmousemove=mouse;
    
     function theClock(){ 
    
      var time=new Date();
    
      var secs=time.getSeconds();
      var sec=Math.PI * ((secs-15)/30);
      var mins=time.getMinutes();
      var min=Math.PI * ((mins-15)/30);
      var hrs=time.getHours();
      var hr=Math.PI * ((hrs-3)/6)+Math.PI * time.getMinutes()/360;
    
      var hrs2 = time.getHours();
    
            if(hrs2 == 0) { // 午前0時を、午前12時としておく。
                    hrs2 = 12;
                }
    
            if(hrs2 > 12) { // 午後(13時以降)の数値を、午前の数値と同じにしておく。例)13時(－12)→1時
                    hrs2 = hrs2 - 12;
                }
    
           if((alarm == "設定(終了)") && (document.sampleForm.alarmH1.value == hrs2) &&  (document.sampleForm.alarmM1.value == mins)){
    
                    alarm = "鳴る";
                    bgm.src="△△△.wav";
                    step1=0.02;
              }
    
        for (i=0; i<alen; i++){
          A[i].top=dy[tdlen+cflen+hlen+mlen+slen+i]+ofy+(i*handlen) * Math.sin(currStep2)+scrl(0)+"px";
          A[i].left=dx[tdlen+cflen+hlen+mlen+i]+ofx+(i*handlen) * Math.cos(currStep2)+"px";
       }
        for (i=0; i<slen; i++){
          S[i].top=dy[tdlen+cflen+hlen+mlen+i]+ofy+(i*handlen) * Math.sin(sec)+scrl(0)+"px";
          S[i].left=dx[tdlen+cflen+hlen+mlen+i]+ofx+(i*handlen) * Math.cos(sec)+"px";
       }
        for (i=0; i<mlen; i++){
          M[i].top=dy[tdlen+cflen+hlen+i]+ofy+(i*handlen) * Math.sin(min)+scrl(0)+"px";
          M[i].left=dx[tdlen+cflen+hlen+i]+ofx+(i*handlen) * Math.cos(min)+"px";
       }
        for (i=0; i<hlen; i++){
          H[i].top=dy[tdlen+cflen+i]+ofy+(i*handlen) * Math.sin(hr)+scrl(0)+"px";
          H[i].left=dx[tdlen+cflen+i]+ofx+(i*handlen) * Math.cos(hr)+"px";
       }
        for (i=0; i<cflen; i++){
         Da[i].top=dy[tdlen+i]+dims * Math.sin(i*Q1*Math.PI/180)+scrl(0)+"px";
         Da[i].left=dx[tdlen+i]+dims * Math.cos(i*Q1*Math.PI/180)+"px";
       }
        for (i=0; i<tdlen; i++){
         Dt[i].top=dy[i]+dims*1.5 * Math.sin(currStep1+i*Q2*Math.PI/180)+scrl(0)+"px";
         Dt[i].left=dx[i]+dims*1.5 * Math.cos(currStep1+i*Q2*Math.PI/180)+"px";
       }
         currStep1 -= step1;
         currStep2 -= step2;
         winsize();
     }
    
    
     function Delay(){
    
      zy[0]=Math.round(dy[0]+=((my)-dy[0])*del);
      zx[0]=Math.round(dx[0]+=((mx)-dx[0])*del);
    
         for (i=1; i < sum; i++){
           zy[i]=Math.round(dy[i]+=(zy[i-1]-dy[i])*del); 
           zx[i]=Math.round(dx[i]+=(zx[i-1]-dx[i])*del);
    
           if (dy[i-1] >= h-80) dy[i-1]=h-80;
           if (dx[i-1] >= w-80) dx[i-1]=w-80;
        }
          setTimeout(Delay,rep);
          theClock();
     }
           Delay();
    
    
    var alarm = "解除"; //アラームフラグを初期化する。
    
     function changeFlg(){
    
    
        if(alarm == "設定(開始)"){ //アラーム設定開始の時
                 clearTimeout(timerID);
            alarm = "設定(終了)";
    　　　　　　　　document.sampleForm.setAlarm.value="  Reset  ";
                    bgm.src="";
                    step1=0; step2=0;
        }else if(alarm == "解除"){ //アラーム未設定時
                 timerID = setTimeout(countdown,1000);
    　　　　    alarm = "設定(開始)";
            document.sampleForm.setAlarm.value=" Set Alarm！";
                    step1=0.02; step2=0.003148; // 秒速に等しくなるように数値を調節する。
        }else if(alarm == "設定(終了)"){ //アラーム設定済み時
    　　　　    alarm = "解除";
            document.sampleForm.setAlarm.value="   Ready ？   ";
                    bgm.src="〇〇〇.mid";
                    step1=0.02; step2=0;
        }else{ //アラームが鳴っている時
    　　　　    alarm = "解除";
            document.sampleForm.setAlarm.value="   Ready ？   ";
                    bgm.src="〇〇〇.mid";
                    step1=0.02; step2=0;
         }
    }
       document.getElementById('sAlarm').onclick=changeFlg;
       theClock();
    }());//即時関数終了
    // --></script>
    <!--★コピーここまで-->
    
    </body>
    </html>
    
[/code]

追記

質問のコードでは、

[code]

     var timerID = null;
    
     var count1 = 59;
     var count2 = 0;
    
      function countdown() {
    
    if(count1 == count2){
    
      count1=59;}
    
    else{
          count1-=1;}
    
    if(count1 == 59){
     document.sampleForm.alarmH1.value = "3";
     document.sampleForm.alarmM1.value = "0";
     }
    
    else if(count1 == 58){
     document.sampleForm.alarmH1.value = "2";
     document.sampleForm.alarmM1.value = "48";
     }
    　～　　～　　～　　～　　～　　～
    else i
    
    f(count1 == 1){
     document.sampleForm.alarmH1.value = 3;
     document.sampleForm.alarmM1.value = 24;
     }
    else {
     document.sampleForm.alarmH1.value = 3;
     document.sampleForm.alarmM1.value = 12;
     }
       timerID = setTimeout(countdown,1000); 
    }
    
[/code]

と"var timerID = null;"が必要なようです。  
それと、時計本体のコードの

[code]

    var HandY = -5.5,
        HandX = -2.5,
    
[/code]

の数値を変えて、目安針の位置を調節する必要もあります。  
また、"function ClockAndAssign() {}" 内に目覚ましを鳴らせるコード

[code]

      var hrs2 = time.getHours();
    
            if(hrs2 == 0) { // 午前0時を、午前12時としておく。
                    hrs2 = 12;
                }
    
            if(hrs2 > 12) { // 午後(13時以降)の数値を、午前の数値と同じにしておく。例)13時(－12)→1時
                    hrs2 = hrs2 - 12;
                }
    
           if((alarm == "設定(終了)") && (document.sampleForm.alarmH1.value == hrs2) &&  (document.sampleForm.alarmM1.value == mins)){
    
                    alarm = "鳴る";
                    bgm.src="オバケ.wav";
                    step1=0.02; 
              }
    
[/code]

を入れ、スクリプトの最後に

[code]

    var alarm = "解除"; //アラームフラグを初期化する。
    
     function changeFlg(){
    
        if(alarm == "設定(開始)"){ //アラーム設定開始の時
                clearTimeout(timerID);
            alarm = "設定(終了)";
    　　　　　　　　document.sampleForm.setAlarm.value="  Reset  ";
                    bgm.src="";
                    step1=0; step2=0;
        }else if(alarm == "解除"){ //アラーム未設定時
                timerID = setTimeout(countdown,1000);
    　　　　    alarm = "設定(開始)";
                    step1=0.02; step2=0.002109; // 秒速に等しくなるように数値を調節する。
            document.sampleForm.setAlarm.value=" Set Alarm！"; 
    
    　　　～　～　～　～　～　～
        }else{ //アラームが鳴っている時
    　　　　    alarm = "解除";
            document.sampleForm.setAlarm.value="   Ready ？   ";
                    bgm.src="トルコ行進曲.mid";
                    step1=0.02;
                    currStep2 = null; // 目安針の位置を初期化する(＊"3時"の位置に戻す。)。
                    count1 = 59;  // カウントダウンを初期化する(＊"59"の位置の戻す)。
                    document.sampleForm.alarmH1.value = ""; // 時間のテキストボックスを初期化する。
                    document.sampleForm.alarmM1.value = ""; // 分の時間のテキストボックスを初期化する。
         }
    }
       document.getElementById('sAlarm').onclick=changeFlg;
    
[/code]

として置き、"alarm = '設定(開始)'"の時のstep2は、**”0.002109”**前後で秒針の速度と均衡が取れるようなので、調節が必要です。

追記

step2は、完全に秒速と"イコール"にならず、数分後に少しずつズレが生じるようです。そこで、目安針を外部のタイマー(setTimeout(countdown,1000);
)で回すようにすると、何時間経ってもズレは生じないようです。時計のスクリプト内の"step2"に関連する箇所を削除し、"function
ClockAndAssign() {}"内を以下のようにするだけでいいです。

[code]

        var time = new Date();
        var secs = time.getSeconds();
        var sec = -1.57 + Math.PI * secs / 30;
    　　　～　～　～
    　　　～　～　～
       var countDown = -1.57 + Math.PI * count1 / 30;
    　　　～　～　～
    　　　～　～　～
        for (i = 0; i < A.length; i++)
        {
            var AL = $$('Alarm')[i].style;
            AL.top = y[i] + HandY + (i * HandHeight) * Math.sin(countDown) + scrll;
            AL.left = x[i] + HandX + (i * HandWidth) * Math.cos(countDown);
        }
    
[/code]

追記  
"count1"の初期値は **59** になっていて、これでは1つズレます。 **60** が正解のようです。


CC BY-SA 4.0
2021-07-26T12:26:57.460
78417
2021-08-06T09:45:47.250
2021-08-06T09:45:47.250
44018
44018
78229
answer


時間と分のテキストボックスがあるとアナログ時計らしくないので、それを省いて  
みました。  
変更箇所は、時間と分を入力するそれぞれのinputタグを削除し、  
"function theClock(){}"内の"if((alarm == '設定(終了)') &&～～～"の  
箇所と、"function countdown() {}"内，及び"function changeFlg(){}"を  
下記のようにです。  
また、何度も目覚ましを設定すると目安針の位置に“ズレ”が生じる解決策と  
しまして、目安針を初期化するしか思い浮かびません。“local reload”は、  
ページ全体が更新されて見た感じが好みでないので、"目安針"のみを初期に  
位置(＊３時の地点)に戻るようにしてみました。

("function theClock(){}"内)

[code]

    if((alarm == "設定(終了)") && (numH == hrs2) &&  (numM == mins)){
    
[/code]

("function countdown() {}"内)

[code]

     // 目安針の現在位置を、時間と分に換算する。
    
     var count1 = 59;
     var count2 = 0;
    
     var numH = 3;
     var numM = 0;
    
      function countdown() {
    
          if(count1 == count2){
              count1=59;
         }
          else{
              count1 -= 1;
         }
    
         if(count1 == 59){
             numH = 3;
             numM = 0;
     }
    else if(count1 == 58){
             numH = 2;
             numM = 48
     }
    else if(count1 == 57){
             numH = 2;
             numM = 36;
     }
    else if(count1 == 56){
             numH = 2;
             numM = 24
     }
    else if(count1 == 55){
             numH = 2;
             numM = 12;
     }
    else if(count1 == 54){
             numH = 2;
             numM = 0;
     }
    else if(count1 == 53){
             numH = 1;
             numM = 48;
     }
    else if(count1 == 52){
             numH = 1;
             numM = 36;
     }
    else if(count1 == 51){
             numH = 1;
             numM = 24;
     }
    else if(count1 == 50){
             numH = 1;
             numM = 12;
     }
    else if(count1 == 49){
             numH = 1;
             numM = 0;
     }
    else if(count1 == 48){
             numH = 12;
             numM = 48;
     }
    else if(count1 == 47){
             numH = 12;
             numM = 36;
     }
    else if(count1 == 46){
             numH = 12;
             numM = 24;
     }
    else if(count1 == 45){
             numH = 12;
             numM = 12;
     }
    else if(count1 == 44){
             numH = 12;
             numM = 0;
     }
    else if(count1 == 43){
             numH = 11;
             numM = 48;
     }
    else if(count1 == 42){
             numH = 11;
             numM = 36;
     }
    else if(count1 == 41){
             numH = 11;
             numM = 24;
     }
    else if(count1 == 40){
             numH = 11;
             numM = 12;
     }
    else if(count1 == 39){
             numH = 11;
             numM = 0;
     }
    else if(count1 == 38){
             numH = 10;
             numM = 48;
     }
    else if(count1 == 37){
             numH = 10;
             numM = 36;
     }
    else if(count1 == 36){
             numH = 10;
             numM = 24;
     }
    else if(count1 == 35){
             numH = 10;
             numM = 12;
     }
    else if(count1 == 34){
             numH = 10;
             numM = 0;
     }
    else if(count1 == 33){
             numH = 9;
             numM = 48
     }
    else if(count1 == 32){
             numH = 9;
             numM = 36;
     }
    else if(count1 == 31){
             numH = 9;
             numM = 24;
     }
    else if(count1 == 30){
             numH = 9;
             numM = 12;
     }
    else if(count1 == 29){
             numH = 9;
             numM = 0;
     }
    else if(count1 == 28){
             numH = 8;
             numM = 48;
     }
    else if(count1 == 27){
             numH = 8;
             numM = 36;
     }
    else if(count1 == 26){
             numH = 8;
             numM = 24;
     }
    else if(count1 == 25){
             numH = 8;
             numM = 12;
     }
    else if(count1 == 24){
             numH = 8;
             numM = 0;
     }
    else if(count1 == 23){
             numH = 7;
             numM = 48;
     }
    else if(count1 == 22){
             numH = 7;
             numM = 36;
     }
    else if(count1 == 21){
             numH = 7;
             numM = 24;
     }
    else if(count1 == 20){
             numH = 7;
             numM = 12;
     }
    else if(count1 == 19){
             numH = 7;
             numM = 0;
     }
    else if(count1 == 18){
             numH = 6;
             numM = 48;
     }
    else if(count1 == 17){
             numH = 6;
             numM = 36;
     }
    else if(count1 == 16){
             numH = 6;
             numM = 24;
     }
    else if(count1 == 15){
             numH = 6;
             numM = 12;
     }
    else if(count1 == 14){
             numH = 6;
             numM = 0;
     }
    else if(count1 == 13){
             numH = 5;
             numM = 48;
     }
    else if(count1 == 12){
             numH = 5;
             numM = 36;
     }
    else if(count1 == 11){
             numH = 5;
             numM = 24;
     }
    else if(count1 == 10){
             numH = 5;
             numM = 12;
     }
    else if(count1 == 9){
             numH = 5;
             numM = 0;
     }
    else if(count1 == 8){
             numH = 4;
             numM = 48;
     }
    else if(count1 == 7){
             numH = 4;
             numM = 36;
     }
    else if(count1 == 6){
             numH = 4;
             numM = 24;
     }
    else if(count1 == 5){
             numH = 4;
             numM = 12;
     }
    else if(count1 == 4){
             numH = 4;
             numM = 0;
     }
    else if(count1 == 3){
             numH = 3;
             numM = 48;
     }
    else if(count1 == 2){
             numH = 3;
             numM = 36;
     }
    else if(count1 == 1){
             numH = 3;
             numM = 24;
     }
    else {
             numH = 3;
             numM = 12;
     }
         timerID = setTimeout(countdown,1000);
    }
    
[/code]

(" function changeFlg(){}"内)

[code]

          ～～～
    }else if(alarm == "設定(終了)"){ //アラーム設定済み時
    　　　　    alarm = "解除";
        document.sampleForm.setAlarm.value="   Ready ？   ";
                bgm.src="トルコ行進曲.mid";
                step1=0.02;
                currStep2 = null; // 目安針の位置を初期化する(＊"3時"の位置に戻す。)。
                count1 = 59;  // カウントダウンを初期化する(＊"59"の位置の戻す)。
                numH= 3; // 時間のテキストボックスを初期化する。
                numM = 0; // 分の時間のテキストボックスを初期化する。
    
    }else{ //アラームが鳴っている時
    　　　　    alarm = "解除";
        document.sampleForm.setAlarm.value="   Ready ？   ";
                bgm.src="トルコ行進曲.mid";
                step1=0.02;
                currStep2 = null; // 目安針の位置を初期化する(＊"3時"の位置に戻す。)。
                count1 = 59;  // カウントダウンを初期化する(＊"59"の位置の戻す)。
                numH= 3; // 時間のテキストボックスを初期化する。
                numM = 0; // 分の時間のテキストボックスを初期化する。
     }
    
[/code]


CC BY-SA 4.0
2021-07-27T09:25:53.387
78426
2021-07-29T10:18:20.570
2021-07-29T10:18:20.570
44018
44018
78229
answer