43861


下記のコードは、マウスポインターに追従する"(カレンダー機能付き)アナログ時計"のものですが、  
１点だけ気になるところがあるのです。  
それは、コード内にある"const SPEED = 0.6,"の値を0.6以下に設定すると、face(文字盤)の  
体裁が崩れるのです。コード全体を見ても、どこに原因があるのか分かりません。分かる方がいましたら、  
教えていただけませんでしょうか。  
ブラウザはIEで、バージョンは11.0.9600.8977です。クロームでも同様です。

[code]

    <!DOCTYPE html>
    <html>
    <head>
        <style>
            body {
      font-family: Helvetica, Arial, sans-serif;
    }
    
    .Face {
      position: absolute;
      height: 10;
      widdth: 10;
      text-align: center;
      font-size: 1em;
      color: #0000ff;
    }
    
    .Hours {
      position: absolute;
      width: 16px;
      height: 16px;
      font-family: Arial;
      font-size: 16px;
      color: #000000;
      text-align: center;
      font-weight: bold;
    }
    
    .Minutes {
      position: absolute;
      width: 16px;
      height: 16px;
      font-family: Arial;
      font-size: 16px;
      color: #000000;
      text-align: center;
      font-weight: bold;
    }
    
    .Seconds {
      position: absolute;
      width: 16px;
      height: 16px;
      font-family: Arial;
      font-size: 16px;
      color: #ff0000;
      text-align: center;
      font-weight: bold;
    }
    
    .Date {
      position: absolute;
      height: 10;
      width: 10;
      font-size: 1em;
      color: #00ff00;
    }
        </style>
        <script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
        </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>
        <script type="text/javascript">
            "use strict";
    
    function $(sel) {
      return document.getElementById(sel);
    }
    
    function $$(sel) {
      return document.getElementsByClassName(sel);
    }
    
    function setPosition(element, y, x) {
      element.style.top = y + 'px';
      element.style.left = x + 'px';
    }
    
    const CLOCK_HEIGHT = 40,
        CLOCK_WIDTH = 40,
        CLOCK_FROM_MOUSE_Y = 0,
        CLOCK_FROM_MOUSE_X = 100;
    
    const H = '...'.split('');
    const M = '....'.split('');
    const S = '.....'.split('');
    const SPEED = 0.6,
        FACES = '1 2 3 4 5 6 7 8 9 10 11 12'.split(' ');
    const HAND_HEIGHT = CLOCK_HEIGHT / 4.5; 
    const HAND_WIDTH = CLOCK_WIDTH / 4.5;
    const HAND_Y = -7,
        HAND_X = -2.5,
        STEP = 0.06;
    
    var ymouse = 0,
        xmouse = 0;
    var currStep = 0;
    var lastBasePositions = [];
    
    function initialize() {
      for (var i = 0; i < FACES.length; ++i) {
        lastBasePositions[i] = {x:0, y:0};
      }
    
      var html = '';
      // Face wrapper
      html = '';
      for (var i = 0; i < FACES.length; ++i) {
        html += '<div class="Face">' + FACES[i] + '</div>';
      }
      $('Of').children[0].innerHTML = html;
    
      // Hours wrapper
      html = '';
      for (var i = 0; i < H.length; ++i) {
        html += '<div class="Hours">' + H[i] + '</div>';
      } 
      $('Oh').children[0].innerHTML = html;
    
      // Minute wrapper
      html = '';
      for (var i = 0; i < M.length; ++i) {
        html += '<div class="Minutes">' + M[i] + '</div>';
      }
      $('Om').children[0].innerHTML = html;
    
      // Seconds wrapper
      html = '';
      for (var i = 0; i < S.length; ++i) {
        html += '<div class="Seconds">' + S[i] + '</div>';
      }
      $('Os').children[0].innerHTML = html;
    
      // Mouse move event handler
      document.onmousemove = function(evnt) {
        ymouse = evnt.clientY + CLOCK_FROM_MOUSE_Y;
        xmouse = evnt.clientX + CLOCK_FROM_MOUSE_X;
      };
    
      requestAnimationFrame(ClockAndAssign);
    }
    
    var lastYearPositions = [{x:0, y:0}];
    var lastYearString = ' ';
    var lastYearLocale = '';
    function updateYear(currentDate, scrll) {
      var yearString = lastYearString;
      if (currentDate.getMinutes() % 2 == 0) {
        if (lastYearLocale != 'ja')
          yearString = currentDate.toLocaleDateString("ja-JP-u-ca-japanese", { era: "long", year: "numeric" }).
              replace(/\u200e/g, "").replace(" ", "");
        lastYearLocale = 'ja';
      } else {
        if (lastYearLocale != 'en')
          yearString = currentDate.toLocaleDateString("en-US", { era: "long", year: "numeric" }).
              replace(/\u200e/g, "") + "年";
        lastYearLocale = 'en';
      }
    
      var yearLength = lastYearPositions.length;
      if (yearString != lastYearString) {
        lastYearString = yearString;        
        var yearCharacters = yearString.split('');
        yearLength = yearCharacters.length;
    
        // Date wrapper
        var html = '';
        for (var i = 0; i < yearLength; ++i) {
          html += '<div class="Date">' + yearCharacters[i] + '</div>';
        }
        $('Od').children[0].innerHTML = html;
      }
      var positions = [{}];
      var lastPosition = lastYearPositions[0];
      positions[0].y = lastPosition.y + ((ymouse) - lastPosition.y) * SPEED;
      positions[0].x = lastPosition.x + ((xmouse) - lastPosition.x) * SPEED;
      for (var i = 1; i < yearLength; ++i) {
        lastPosition = i < lastYearPositions.length ?
            lastYearPositions[i] :
            lastYearPositions[lastYearPositions.length - 1];
        positions[i] = {};
        positions[i].y = lastPosition.y + (positions[i-1].y - lastPosition.y) * SPEED;
        positions[i].x = lastPosition.x + (positions[i-1].x - lastPosition.x) * SPEED;
      }
      for (var i = 0; i < yearLength; ++i) {
        var radian = currStep + i * (360 / yearLength) * Math.PI / 180;
        setPosition($$('Date')[i],
                    Math.round(positions[i].y) + CLOCK_HEIGHT * 1.5 * Math.sin(radian) + scrll,
                    Math.round(positions[i].x) + CLOCK_WIDTH * 1.5 * Math.cos(radian));
      }
      lastYearPositions = positions;
      currStep -= STEP;
    }
    
    function ClockAndAssign() {
      var date = new Date();
      var secs = date.getSeconds();
      var sec = -1.57 + Math.PI * secs / 30;
      var mins = date.getMinutes();
      var min = -1.57 + Math.PI * mins / 30;
      var hr = date.getHours();
      var hrs = -1.575 + Math.PI * hr / 6 + Math.PI * parseInt(date.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;
      var scrll = 0;
    
      var positions = [{}];
      var lastPosition = lastBasePositions[0];
      positions[0].y = Math.round(lastPosition.y + (ymouse - lastPosition.y) * SPEED);
      positions[0].x = Math.round(lastPosition.x + (xmouse - lastPosition.x) * SPEED);
      for (var i = 1; i < FACES.length; ++i) {
        lastPosition = lastBasePositions[i];
        positions[i] = {};
        positions[i].y = Math.round(lastPosition.y + (positions[i - 1].y - lastPosition.y) * SPEED);
        positions[i].x = Math.round(lastPosition.x + (positions[i - 1].x - lastPosition.x) * SPEED);
      }
      lastBasePositions = positions;
    
      var split = 360 / FACES.length;
      for (var i = 0; i < FACES.length; ++i) {
        var radian = -1.0471 + i * split * Math.PI / 180;
        setPosition($$('Face')[i],
                    positions[i].y + CLOCK_HEIGHT * Math.sin(radian) + scrll,
                    positions[i].x + CLOCK_WIDTH * Math.cos(radian));
      }
      for (var i = 0; i < H.length; ++i) {
        setPosition($$('Hours')[i],
                    positions[i].y + HAND_Y + (i * HAND_HEIGHT) * Math.sin(hrs) + scrll,
                    positions[i].x + HAND_X + (i * HAND_WIDTH) * Math.cos(hrs));
      }
      for (var i = 0; i < M.length; ++i) {
        setPosition($$('Minutes')[i],
                    positions[i].y + HAND_Y + (i * HAND_HEIGHT) * Math.sin(min) + scrll,
                    positions[i].x + HAND_X + (i * HAND_WIDTH) * Math.cos(min));
      }
      for (var i = 0; i < S.length; ++i) {
        setPosition($$('Seconds')[i],
                    positions[i].y + HAND_Y + (i * HAND_HEIGHT) * Math.sin(sec) + scrll,
                    positions[i].x + HAND_X + (i * HAND_WIDTH) * Math.cos(sec));
      }
      updateYear(date, scrll);
      requestAnimationFrame(ClockAndAssign);
    }
    
    initialize();
        </script>
    </body>
    </html>
    
[/code]


CC BY-SA 4.0
2018-05-07T14:40:12.983
43848
2018-05-08T06:26:36.207
2018-05-07T16:08:37.260
28063
28063
question
javascript
マウスポインターに追従する『(カレンダー機能付き)アナログ時計』の体裁が崩れる原因について


`ClockAndAssign()`中で`Math.round`（四捨五入）を使用しているので,計算で得た値の0.５以下端数は切り捨てられています。  
`Math.round`を使用しなければ良いかと思います。

[code]

    <!DOCTYPE html>
    <html>
    <head>
        <style>
            body {
                font-family: Helvetica, Arial, sans-serif;
            }
    
            .Face {
                position: absolute;
                height: 10;
                widdth: 10;
                text-align: center;
                font-size: 1em;
                color: #0000ff;
            }
    
            .Hours {
                position: absolute;
                width: 16px;
                height: 16px;
                font-family: Arial;
                font-size: 16px;
                color: #000000;
                text-align: center;
                font-weight: bold;
            }
    
            .Minutes {
                position: absolute;
                width: 16px;
                height: 16px;
                font-family: Arial;
                font-size: 16px;
                color: #000000;
                text-align: center;
                font-weight: bold;
            }
    
            .Seconds {
                position: absolute;
                width: 16px;
                height: 16px;
                font-family: Arial;
                font-size: 16px;
                color: #ff0000;
                text-align: center;
                font-weight: bold;
            }
    
            .Date {
                position: absolute;
                height: 10;
                width: 10;
                font-size: 1em;
                color: #00ff00;
            }
        </style>
        <script src="/scripts/snippet-javascript-console.min.js?v=1"></script>
    </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>
    <script type="text/javascript">
        "use strict";
    
        function $(sel) {
            return document.getElementById(sel);
        }
    
        function $$(sel) {
            return document.getElementsByClassName(sel);
        }
    
        function setPosition(element, y, x) {
            element.style.top = y + 'px';
            element.style.left = x + 'px';
        }
    
        const CLOCK_HEIGHT = 40,
            CLOCK_WIDTH = 40,
            CLOCK_FROM_MOUSE_Y = 0,
            CLOCK_FROM_MOUSE_X = 100;
    
        const H = '...'.split('');
        const M = '....'.split('');
        const S = '.....'.split('');
        const SPEED = 0.4,
            FACES = '1 2 3 4 5 6 7 8 9 10 11 12'.split(' ');
        const HAND_HEIGHT = CLOCK_HEIGHT / 4.5;
        const HAND_WIDTH = CLOCK_WIDTH / 4.5;
        const HAND_Y = -7,
            HAND_X = -2.5,
            STEP = 0.06;
    
        var ymouse = 0,
            xmouse = 0;
        var currStep = 0;
        var lastBasePositions = [];
    
        function initialize() {
            for (var i = 0; i < FACES.length; ++i) {
                lastBasePositions[i] = {x:0, y:0};
            }
    
            var html = '';
            // Face wrapper
            html = '';
            for (var i = 0; i < FACES.length; ++i) {
                html += '<div class="Face">' + FACES[i] + '</div>';
            }
            $('Of').children[0].innerHTML = html;
    
            // Hours wrapper
            html = '';
            for (var i = 0; i < H.length; ++i) {
                html += '<div class="Hours">' + H[i] + '</div>';
            }
            $('Oh').children[0].innerHTML = html;
    
            // Minute wrapper
            html = '';
            for (var i = 0; i < M.length; ++i) {
                html += '<div class="Minutes">' + M[i] + '</div>';
            }
            $('Om').children[0].innerHTML = html;
    
            // Seconds wrapper
            html = '';
            for (var i = 0; i < S.length; ++i) {
                html += '<div class="Seconds">' + S[i] + '</div>';
            }
            $('Os').children[0].innerHTML = html;
    
            // Mouse move event handler
            document.onmousemove = function(evnt) {
                ymouse = evnt.clientY + CLOCK_FROM_MOUSE_Y;
                xmouse = evnt.clientX + CLOCK_FROM_MOUSE_X;
            };
    
            requestAnimationFrame(ClockAndAssign);
        }
    
        var lastYearPositions = [{x:0, y:0}];
        var lastYearString = ' ';
        var lastYearLocale = '';
        function updateYear(currentDate, scrll) {
            var yearString = lastYearString;
            if (currentDate.getMinutes() % 2 == 0) {
                if (lastYearLocale != 'ja')
                    yearString = currentDate.toLocaleDateString("ja-JP-u-ca-japanese", { era: "long", year: "numeric" }).
                    replace(/\u200e/g, "").replace(" ", "");
                lastYearLocale = 'ja';
            } else {
                if (lastYearLocale != 'en')
                    yearString = currentDate.toLocaleDateString("en-US", { era: "long", year: "numeric" }).
                    replace(/\u200e/g, "") + "年";
                lastYearLocale = 'en';
            }
    
            var yearLength = lastYearPositions.length;
            if (yearString != lastYearString) {
                lastYearString = yearString;
                var yearCharacters = yearString.split('');
                yearLength = yearCharacters.length;
    
                // Date wrapper
                var html = '';
                for (var i = 0; i < yearLength; ++i) {
                    html += '<div class="Date">' + yearCharacters[i] + '</div>';
                }
                $('Od').children[0].innerHTML = html;
            }
            var positions = [{}];
            var lastPosition = lastYearPositions[0];
            positions[0].y = lastPosition.y + ((ymouse) - lastPosition.y) * SPEED;
            positions[0].x = lastPosition.x + ((xmouse) - lastPosition.x) * SPEED;
            for (var i = 1; i < yearLength; ++i) {
                lastPosition = i < lastYearPositions.length ?
                    lastYearPositions[i] :
                    lastYearPositions[lastYearPositions.length - 1];
                positions[i] = {};
                positions[i].y = lastPosition.y + (positions[i-1].y - lastPosition.y) * SPEED;
                positions[i].x = lastPosition.x + (positions[i-1].x - lastPosition.x) * SPEED;
            }
            for (var i = 0; i < yearLength; ++i) {
                var radian = currStep + i * (360 / yearLength) * Math.PI / 180;
                setPosition($$('Date')[i],
                    Math.round(positions[i].y) + CLOCK_HEIGHT * 1.5 * Math.sin(radian) + scrll,
                    Math.round(positions[i].x) + CLOCK_WIDTH * 1.5 * Math.cos(radian));
            }
            lastYearPositions = positions;
            currStep -= STEP;
        }
    
        function ClockAndAssign() {
            var date = new Date();
            var secs = date.getSeconds();
            var sec = -1.57 + Math.PI * secs / 30;
            var mins = date.getMinutes();
            var min = -1.57 + Math.PI * mins / 30;
            var hr = date.getHours();
            var hrs = -1.575 + Math.PI * hr / 6 + Math.PI * parseInt(date.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;
            var scrll = 0;
    
            var positions = [{}];
            var lastPosition = lastBasePositions[0];
            positions[0].y = (lastPosition.y + (ymouse - lastPosition.y) * SPEED);
            positions[0].x = (lastPosition.x + (xmouse - lastPosition.x) * SPEED);
            for (var i = 1; i < FACES.length; ++i) {
                lastPosition = lastBasePositions[i];
                positions[i] = {};
                positions[i].y = (lastPosition.y + (positions[i - 1].y - lastPosition.y) * SPEED);
                positions[i].x = (lastPosition.x + (positions[i - 1].x - lastPosition.x) * SPEED);
            }
            lastBasePositions = positions;
    
            var split = 360 / FACES.length;
            for (var i = 0; i < FACES.length; ++i) {
                var radian = -1.0471 + i * split * Math.PI / 180;
                setPosition($$('Face')[i],
                    positions[i].y + CLOCK_HEIGHT * Math.sin(radian) + scrll,
                    positions[i].x + CLOCK_WIDTH * Math.cos(radian));
            }
            for (var i = 0; i < H.length; ++i) {
                setPosition($$('Hours')[i],
                    positions[i].y + HAND_Y + (i * HAND_HEIGHT) * Math.sin(hrs) + scrll,
                    positions[i].x + HAND_X + (i * HAND_WIDTH) * Math.cos(hrs));
            }
            for (var i = 0; i < M.length; ++i) {
                setPosition($$('Minutes')[i],
                    positions[i].y + HAND_Y + (i * HAND_HEIGHT) * Math.sin(min) + scrll,
                    positions[i].x + HAND_X + (i * HAND_WIDTH) * Math.cos(min));
            }
            for (var i = 0; i < S.length; ++i) {
                setPosition($$('Seconds')[i],
                    positions[i].y + HAND_Y + (i * HAND_HEIGHT) * Math.sin(sec) + scrll,
                    positions[i].x + HAND_X + (i * HAND_WIDTH) * Math.cos(sec));
            }
            updateYear(date, scrll);
            requestAnimationFrame(ClockAndAssign);
        }
    
        initialize();
    </script>
    </body>
    </html>
[/code]


CC BY-SA 4.0
2018-05-08T06:26:36.207
43861
2018-05-08T06:26:36.207
22793
43848
answer