动态更改CSS关键帧值以创建时钟

时间:2015-08-31 17:42:33

标签: javascript css css-animations keyframe

这是我对关键帧动画的'第一次'尝试。由于无法通过JavaScript动态更改硬编码的CSS值,我之前被推迟了。

我用Google搜索了一下,发现它“可以”完成,但需要进行大量繁琐的工作,删除并更换部分或整个样式表。

无论如何,这是我的努力。这个特定剧本的最终目标是成为时钟之手的反弹。我已经可以用过渡和立方贝塞尔来做这个但只能得到一次反弹。我已经看到了这种效果使用各种js库等但你知道它是怎么回事 - 你喜欢自己动手。

我的问题是 - 我的方法下面有什么明显的错误。忽略琐事,这只是一个考验。我想看的是我的GenerateKeyFrames()函数和两种调用它的方法。

感谢您的任何信息。

    var d = document;
    var incr = 1;
    var step = -6; //Initial start pos.

    var coreCss = 'display: block;position: absolute;'
               +'left: 100px;top: 10px;height: 95px;'
               +'width: 4px;background-color: #000;'
               +'transform-origin: center bottom;';

    var initialAniCss = 'animation: reGen'+incr+' 1s 1 forwards;';
    coreCss += initialAniCss;

    var elementToAnimate = d.createElement('div');
    elementToAnimate.setAttribute('style', coreCss);
    d.body.appendChild(elementToAnimate);

    function GenerateKeyFrames() {

    /* Remove previous 'tmpSheet' stylesheet */
    var currSheet = (d.getElementById('tmpSheet'));
    if (currSheet) {
        //currSheet.parentNode.removeChild(currSheet);// Doesn't seem as smooth as other 2 below!
        //currSheet.remove(); - Not IE, shame.
        currSheet.outerHTML = '';
    }

    /* Movement in degrees */
    var p1 = step;
    var p2 = step+6;
    var p3 = step+4;
    var p4 = step+6;
    var p5 = step+5; 
    var p6 = step+6;

    /* Create new keyframe. Must have new name! Adding an incrementing var to name does ok */
    var frames = '@keyframes reGen'+incr+' { '
    +'0% { transform: rotate('+p1+'deg) translateZ(0); animation-timing-function: ease-in;}'
    +'25% { transform: rotate('+p2+'deg) translateZ(0); animation-timing-function: ease-out;}'
    +'45% { transform: rotate('+p3+'deg) translateZ(0); animation-timing-function: ease-in;}'
    +'65% { transform: rotate('+p4+'deg) translateZ(0); animation-timing-function: ease-out;}' 
    +'75% { transform: rotate('+p5+'deg) translateZ(0); animation-timing-function: ease-in;}'
    +'85%,100% { transform: rotate('+p6+'deg) translateZ(0);animation-timing-function: ease-out;}}';

    /* Create new tmpSheet style sheet to head */
    var s = document.createElement( 'style' );
    s.setAttribute("id", "tmpSheet");
    s.innerHTML = frames;
    document.getElementsByTagName('head')[0].appendChild(s);

    /* Put it all together and it's ready to go */ 
    var newAni = 'animation: reGen'+incr+' 1s 1 forwards;';
    coreCss += newAni;
    elementToAnimate.setAttribute('style', coreCss);
    d.body.appendChild(elementToAnimate);
}
GenerateKeyFrames();

/* Can be called on animation end - or timed function rep().
elementToAnimate.addEventListener("animationend",function(e) {
    incr++;
    step += 6;
    elementToAnimate.removeAttribute("style");
    GenerateKeyFrames();
    },false);
*/

function rep() {
    incr++;
    step += 6;
    elementToAnimate.removeAttribute("style");
    GenerateKeyFrames();
setTimeout(rep, 2000);
}
rep();

5 个答案:

答案 0 :(得分:2)

我真的不喜欢用唯一名称动态插入所有这些关键帧的想法。如果我这样做并尝试使用CSS关键帧动画,我会创建两个动画,一个提供“双反弹”效果,另一个旋转包装围绕中心。

只使用HTML和CSS,你可以几乎创建一个完整的工作时钟,虽然没有任何方法可以在没有JavaScript的情况下在适当的时间启动它。

这是一个有趣的练习,我能够使用关键帧动画和一小部分JavaScript重新创建整个时钟效果,以确定动画的开始时间并提供负animation-delay来抵消动画到适当的时间范围。

时间可以稍微徘徊,但实际上没有你想象的那么多。我让动画片在Chrome,FF和IE中一夜之间运行,并允许我的电脑进入睡眠状态,9小时后,时钟仍保持完美时间。然而,当我让它在我的手机的背景标签中运行一夜之后,时钟在早上完全被打破了。虽然看到整个目的是如何在网页上显示时钟,但页面不太可能长时间停留以使时钟明显关闭。

无论如何,这是片段:

window.addEventListener("load", function() {
  var now = new Date();
  var secondsDelay = now.getSeconds();
  var minutesDelay = now.getMinutes() * 60 + secondsDelay;
  var hoursDelay = (now.getHours() % 12) * 3600 + minutesDelay;
  var minuteHand = document.querySelector(".minute .hand");
  var minuteWrapper = document.querySelector(".minute");
  var secondWrapper = document.querySelector(".second");
  var hourWrapper = document.querySelector(".hour");

  //set animation offsets with negative delay
  minuteHand.style.animation = "minuteTick 60s -" + secondsDelay + "s infinite";
  secondWrapper.style.animation = "rotateHolder steps(60) 60s -" + secondsDelay + "s infinite";
  minuteWrapper.style.animation = "rotateHolder steps(60) 3600s -" + minutesDelay + "s infinite";
  hourWrapper.style.animation = "rotateHolder steps(43200) 43200s -" + hoursDelay + "s infinite";

  //start running
  document.querySelector(".clock").classList.add("running");
});
.clock {
  width: 200px;
  height: 200px;
  background-color: gray;
  border-radius: 50%;
}
.sectionWrapper {
  width: 200px;
  height: 200px;
  position: absolute;
  transform: rotate(0deg);
}
.clock.running .second {
  animation: rotateHolder 60s steps(60) infinite;
}
.clock.running .second .hand {
  animation: secondTick 1s 0s infinite;
}
.clock.running .minute {
  animation: rotateHolder 3600s steps(60) infinite;
}
.clock.running .minute .hand {
  animation: minuteTick 60s 0s infinite;
}
.clock.running .hour {
  animation: rotateHolder 43200s steps(43200) infinite;
}
.hand {
  display: block;
  position: absolute;
  background-color: #000;
  transform-origin: center bottom;
}
.second .hand {
  left: 99px;
  top: 5px;
  height: 95px;
  width: 2px;
  background-color: red;
}
.minute .hand {
  left: 98px;
  top: 15px;
  height: 85px;
  width: 4px;
}
.hour .hand {
  left: 97px;
  top: 45px;
  height: 55px;
  width: 6px;
}
@keyframes secondTick {
  0% { transform: rotate(0deg); animation-timing-function: ease-in; }
  25% { transform: rotate(6deg); animation-timing-function: ease-out; }
  45% { transform: rotate(4deg); animation-timing-function: ease-in; }
  65% { transform: rotate(6deg); animation-timing-function: ease-out; } 
  75% { transform: rotate(5deg); animation-timing-function: ease-in; }
  85%,100% { transform: rotate(6deg);animation-timing-function: ease-out; }				
}
@keyframes minuteTick {
  0%,98.3% { transform: rotate(0deg); animation-timing-function: ease-in; }
  98.8% { transform: rotate(6deg); animation-timing-function: ease-out; }
  99.1% { transform: rotate(4deg); animation-timing-function: ease-in; }
  99.4% { transform: rotate(6deg); animation-timing-function: ease-out; } 
  99.6% { transform: rotate(5deg); animation-timing-function: ease-in; }
  99.8%,100% { transform: rotate(6deg);animation-timing-function: ease-out; }				
}
@keyframes rotateHolder {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
<div class="clock">
  <div class="hour sectionWrapper">
    <div class="hand"></div>
  </div>
  <div class="minute sectionWrapper">
    <div class="hand"></div>
  </div>
  <div class="second sectionWrapper">
    <div class="hand"></div>
  </div>
</div>

答案 1 :(得分:1)

这似乎太复杂了。每当我使用复杂的动画时,我都会使用GSAP。 Here's a simplied demo that I made。它使用基本的JQuery和GSAP动画引擎TweenMax。

您可以通过ease visualizer

轻松地使用GSAP调整宽松度
$(document).ready(function() {
  var clock = $('.clock'); // clock container
  var arm = $('.arm'); // seconds arm
  var log = $('.log'); // log beneath clock
  var position =  90; // starting position at 0 seconds
  var time = 0; 

setInterval(function(){
  position += 6; // 360 / 60 = +6 deg per second
  time ++; 
  TweenLite.to(arm, 0.3, {rotation:position, transformOrigin:"right bottom", ease: Back.easeOut.config(2), y: 0 });
  log.text(time + " seconds and " + position +  " degs");
 }, 1000);

});

答案 2 :(得分:1)

只关注代码,我发现它非常好。

我唯一关心的是

/* Put it all together and it's ready to go */ 
var newAni = 'animation: reGen'+incr+' 1s 1 forwards;';
coreCss += newAni;

请注意,coreCss最终会有很多动画(在开发工具中验证)

你应该清除它。

但鉴于动画是通过前锋设置位置,可能会出现问题......

如果是这种情况,可能只玩2个动画??

如果您想获得有关如何获得该效果的建议,我将设置2个嵌套元素,一个具有您精心设计的关键帧,并且每秒运行一次。而另一个完整的圆圈,步了60次......

答案 3 :(得分:1)

完成时钟。

(function () {

    /* Station Style Clock - kurt.grigg@yahoo.co.uk */

    /* ^^^^^^^^^^^^^^^ Config below ^^^^^^^^^^^^^^^ */

    var clockSize = 400;
    var clockColour = 'rgb(255,255,255)';
    var secHandColour = 'rgb(255,255,255)';

    /* ^^^^^^^^^^^^^^^^^ End config ^^^^^^^^^^^^^^^^ */

    var d = document;
    var mcon = [];
    var mrkrs = [];
    var e = 360/60;
    var degr = -6;
    var mls = 100;
    var prev = performance.now();
    var radi = Math.PI / 180;
    var offs = 90 * radi;
    var rndId = 'id'+Math.random() * 1;
    var secSpan = '.8s';
    var minSpan = '1s';
    var houSpan = '1s';
    var secIncr = 0;
    var minIncr = 0;
    var houIncr = 0;
    var secDeg, minDeg, houDeg, preSec, preMin, preHou;
    var idx = d.getElementsByTagName('div').length;
    var shdcol = 'rgba(0,0,0,0.6)';
    var eiatf = ' translateZ(0); animation-timing-function: ease-in';
    var eoatf = ' translateZ(0); animation-timing-function: ease-out';

    d.write('<div id = "'+rndId+'" style="display:inline-block;line-height:0px;"></div>');

    function xy (a) {
        return (a * (clockSize * 2) / 100);
    }

    function shdw(s, h) {
        var depth = xy(h);
        var angle = s * radi;
        var vsa = depth * Math.cos(angle);
        var hsa = depth * Math.sin(angle);
        return {vsa:vsa, hsa:hsa}
    }

    var dial = d.createElement('div');
    dial.setAttribute('style', 'display: inline-block;'
        +'position: relative;'
        +'height: '+xy(100)+'px;'
        +'width: '+xy(100)+'px;'
        +'background-color:transparent;'
        +'border-radius: 50%;'
        +'margin: -'+xy(24)+'px -'+xy(24)+'px -'+xy(24)+'px -'+xy(24)+'px;');

    d.getElementById(rndId).style.transform = 'scale3d(.5,.5,1)';
    d.getElementById(rndId).appendChild(dial); 

    for (var i = 0; i < 60; i++) {

        var mky = shdw(i * 6, 0.5).vsa;
        var mkx = shdw(i * 6, 0.5).hsa;

        var len = (i % 5) ? 4 : 8;
        var wid = (i % 5) ? .8 : 4;

        mcon[i] = d.createElement('div');
        mcon[i].setAttribute('style', 'display: block;'
            +'position: absolute;'
            +'width: '+xy(4)+'px;'
            +'height: '+xy(8)+'px;'
            +'margin: auto; top: 0;bottom: 0;left: 0;right: 0;'
            +'font-size: 0px;line-height: 0px;padding: 0;'
            +'color: '+clockColour+';');

        mrkrs[i] = d.createElement('div');
        mrkrs[i].setAttribute('style', 'display: block;'
            +'position: absolute;'
            +'width: '+xy(wid)+'px;'
            +'height: '+xy(len)+'px;'
            +'margin: auto; top: 0;left: 0;right: 0;'
            +'font-size: 0px;line-height: 0px;padding: 0;'
            +'box-shadow:'+mkx+'px '+mky+'px 0px 0px rgba(0,0,0,0.7);'
            +'background-color:'+clockColour+';');
        mcon[i].appendChild(mrkrs[i]);
        dial.appendChild(mcon[i]);
        degr += 6;
        mcon[i].style.top = xy(0) + xy(86) * Math.sin(-offs + e * i * radi) + 'px';
        mcon[i].style.left= xy(0) + xy(86) * Math.cos(-offs + e * i * radi) + 'px';
        mcon[i].style.transform = 'rotate(' + (degr) + 'deg)';
        mcon[i].style.transformOrigin = 'center center';
    }

    /* Generic container div for all hands */

    var handContainers = 'display: block;'
        +'position: absolute;'
        +'height: '+xy(100)+'px;'
        +'width: '+xy(16)+'px;'
        +'font-size: 0px; line-height: 0px; padding: 0;'
        +'margin: auto; top: 0;bottom: 0; left: 0; right: 0;'
        +'transform-origin: center center;';
    

    /* Hour hand CSS */

    var houClone = handContainers;
    var houHand = d.createElement('div');
    houHand.setAttribute('style', houClone);
    
    dial.appendChild(houHand);

    var hh = d.createElement('div');
    hh.setAttribute('style', 'display: block;'
        +'position: absolute;'
        +'height: '+xy(48)+'px;'
        +'width: '+xy(5)+'px;'
        +'top: '+xy(15)+'px;'
        +'margin: auto; left: 0; right: 0;'
        +'outline: 1px solid transparent;'
        +'background-color: '+clockColour+';');
    houHand.appendChild(hh);

    var houShad = houHand.cloneNode(true);
    houShad.childNodes[0].style.backgroundColor = shdcol;

    /* Minute hand CSS */

    var minClone = handContainers;
    var minHand = d.createElement('div');
    minHand.setAttribute('style', minClone);

    dial.appendChild(minHand);

    var mh = d.createElement('div');
    mh.setAttribute('style', 'display:block;'
        +'position: absolute;'
        +'height: '+xy(58)+'px;'
        +'width: '+xy(3)+'px;'
        +'top: '+xy(5)+'px;'
        +'margin: auto; left: 0; right: 0;'
        +'outline: 1px solid transparent;'
        +'background-color: '+clockColour+';');
    minHand.appendChild(mh);

    var minShad = minHand.cloneNode(true);
    minShad.childNodes[0].style.backgroundColor = shdcol;

    /* Seconds hand CSS */

    var secClone = handContainers;
    var secHand = d.createElement('div');
    secHand.setAttribute('style', secClone);
    dial.appendChild(secHand);

    var sh = d.createElement('div');
    var svgsec = '<svg height="'+xy(100)+'" width="'+xy(16)+'">'
    +'<g>'
    +'<rect id="hd" x="'+xy(7.45)+'" y="'+xy(3)+'" width="'+xy(1)+'" height="'+xy(60)+'" stroke-width="0" fill="'+secHandColour+'"/>'
    +'<circle id="cw" cx="50%" cy="'+xy(67)+'" r="'+xy(4)+'" stroke-width="0" stroke="'+secHandColour+'" fill="'+secHandColour+'"/>'
    +'</g>'
    +'</svg>';
    sh.innerHTML = svgsec;
    secHand.appendChild(sh);

    var secShad = secHand.cloneNode(true);
    var newColor = '"'+shdcol+'"';
    var clnshd = svgsec.split(secHandColour).join("");
    clnshd = clnshd.replace(/""/g, newColor);
    secShad.innerHTML = clnshd;

    var nut = d.createElement('div');
    nut.setAttribute('style', 'display: block;'
        +'position: absolute;'
        +'height: '+xy(4)+'px;'
        +'width: '+xy(4)+'px;'
        +'border-radius: 50%;'
        +'margin: auto;top: 0;bottom: 0;left: 0;right: 0;'
        +'background-color: '+secHandColour+';'
        +'box-shadow:'+xy(0)+'px '+xy(0.5)+'px 0px 0px rgba(0,0,0,0.7);'
        +'z-index: 105;');
    dial.appendChild(nut);

    function houKeyFrames() {
        var houSheet = (d.getElementById('tmphouSheet'+idx));
        if (houSheet) {
            houSheet.parentNode.removeChild(houSheet);
        }

        houClone = handContainers;
 
        var p1 = houDeg;
        var p2 = houDeg+1;
        var p3 = houDeg+0.4;
        var p4 = houDeg+1;
        var p5 = houDeg+0.5; 
        var p6 = houDeg+1; 

        var houframes = '@keyframes hou'+idx+'gen'+houIncr+' { '
        +'0% { transform: rotate('+p1+'deg) '+eiatf+';}'
        +'30% { transform: rotate('+p2+'deg) '+eoatf+';}'
        +'45% { transform: rotate('+p3+'deg) '+eiatf+';}'
        +'60% { transform: rotate('+p4+'deg) '+eoatf+';}' 
        +'70% { transform: rotate('+p5+'deg) '+eiatf+';}'
        +'80%,100% { transform: rotate('+p6+'deg) '+eoatf+';}}';

        var hs = document.createElement( 'style' );
        hs.setAttribute('id', 'tmphouSheet'+idx);
        hs.innerHTML = houframes;
        d.getElementsByTagName('head')[0].appendChild(hs);

        var houAni = 'animation: hou'+idx+'gen'+houIncr+' '+houSpan+' 1 forwards;';
        houClone += houAni;
        houHand.setAttribute('style', houClone);
        houHand.style.zIndex = 100;
        dial.appendChild(houHand);

        houShad.setAttribute('style', houClone);
        houShad.style.top = xy(2.5)+'px';
        houShad.style.zIndex = 99;
        dial.appendChild(houShad);
    }

    function minKeyFrames() {
        var minSheet = (d.getElementById('tmpMinSheet'+idx));
        if (minSheet) {
            minSheet.parentNode.removeChild(minSheet);
        }

        minClone = handContainers;

        var p1 = minDeg;
        var p2 = minDeg+6;
        var p3 = minDeg+4;
        var p4 = minDeg+6;
        var p5 = minDeg+5; 
        var p6 = minDeg+6;

        var minframes = '@keyframes min'+idx+'gen'+minIncr+' { '
        +'0% { transform: rotate('+p1+'deg) '+eiatf+';}'
        +'30% { transform: rotate('+p2+'deg) '+eoatf+';}'
        +'45% { transform: rotate('+p3+'deg) '+eiatf+';}'
        +'60% { transform: rotate('+p4+'deg) '+eoatf+';}' 
        +'70% { transform: rotate('+p5+'deg) '+eiatf+';}'
        +'80%,100% { transform: rotate('+p6+'deg) '+eoatf+';}}';

        var ms = document.createElement( 'style' );
        ms.setAttribute('id', 'tmpMinSheet'+idx);
        ms.innerHTML = minframes;
        d.getElementsByTagName('head')[0].appendChild(ms);

        var minAni = 'animation: min'+idx+'gen'+minIncr+' '+minSpan+' 1 forwards;';
        minClone += minAni;
        minHand.setAttribute('style', minClone);
        minHand.style.zIndex = 102;
        dial.appendChild(minHand);

        minShad.setAttribute('style', minClone);
        minShad.style.top = xy(3)+'px';
        minShad.style.zIndex = 101;
        dial.appendChild(minShad);
    }

    function secKeyFrames() {
        var secSheet = (d.getElementById('tmpSecSheet'+idx));
        if (secSheet) {
            secSheet.parentNode.removeChild(secSheet);
        }
        
        secClone = handContainers;
 
        var p1 = secDeg;
        var p2 = secDeg+6;
        var p3 = secDeg+4;
        var p4 = secDeg+6;
        var p5 = secDeg+5; 
        var p6 = secDeg+6; 

        var secframes = '@keyframes sec'+idx+'gen'+secIncr+' { '
        +'0% { transform: rotate('+p1+'deg) '+eiatf+';}'
        +'30% { transform: rotate('+p2+'deg) '+eoatf+';}'
        +'45% { transform: rotate('+p3+'deg) '+eiatf+';}'
        +'60% { transform: rotate('+p4+'deg) '+eoatf+';}' 
        +'70% { transform: rotate('+p5+'deg) '+eiatf+';}'
        +'80%,100% { transform: rotate('+p6+'deg) '+eoatf+';}}';

        var ss = document.createElement( 'style' );
        ss.setAttribute('id', 'tmpSecSheet'+idx);
        ss.innerHTML = secframes;
        document.getElementsByTagName('head')[0].appendChild(ss);

        var secAni = 'animation: sec'+idx+'gen'+secIncr+' '+secSpan+' 1 forwards;';
        secClone += secAni;
        secHand.setAttribute('style', secClone);
        secHand.style.zIndex = 104;
        dial.appendChild(secHand);

        secShad.setAttribute('style', secClone);
        secShad.style.top = xy(3.5)+'px';
        secShad.style.zIndex = 103;
        dial.appendChild(secShad);
    }

    function clock() {
        var x = new Date();
        var seconds = x.getSeconds();
        var minutes = x.getMinutes();
        var hours = (x.getHours() * 30) + (x.getMinutes() / 2);
        
        if (seconds !== preSec) {
            secIncr++;
            secDeg = (seconds-1) * 6;
            secHand.removeAttribute('style');
            secKeyFrames();
            if (secIncr > 59) {
                secIncr = 0;
            }
        }

        if (minutes !== preMin) {
            minIncr++;
            minDeg = (minutes-1) * 6;
            minHand.removeAttribute('style');
            minKeyFrames();
            if (minIncr > 59) {
                minIncr = 0;
            }
        }

        if (hours !== preHou) {
            houIncr++;
            houDeg = (hours-1) * 1;
            houHand.removeAttribute('style');
            houKeyFrames();
            if (houIncr > 59) {
                houIncr = 0;
            }  
        }

        preSec = seconds;
        preMin = minutes;
        preHou = hours;
    }

    function cyc() {
        var pres = performance.now(); 
        if ((pres - prev) > mls) {
            clock();
            prev = performance.now();
        }
        window.requestAnimationFrame(cyc);
    } 

    window.addEventListener('load', cyc, false);
})();
<!doctype html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Clock</title>

    <style type="text/css">
        html {
            height: 100%;
        }
        
        body {
            background-color: #ffff00;
            text-align: center;
        }
    </style>
</head>

<body>
  
  
  
</body>
</html>  

答案 4 :(得分:0)

Dave的BBC时钟示例。

&#13;
&#13;
(function () {

/* The BBC Analogue Clock - kurt.grigg@yahoo.co.uk */

/* ^^^^^^^^^^^^^^^^^^^ Config below ^^^^^^^^^^^^^^^^^^^ */

var clockSize = 300;
var dialcol = 'rgba(0,0,255,0.9)';
var handcol = 'rgb(230,230,230)';

/* ^^^^^^^^^^^^^^^^^^^ End config ^^^^^^^^^^^^^^^^^^^ */

var d = document;
var mrkrs = [];
var e = (360 / 12);
var degr = 0;
var mls = 100;
var prev = performance.now();
var radi = Math.PI / 180;
var offs = 60 * radi;
var rndId = 'id'+Math.random() * 1;
var sSpan = '.9s';
var mSpan = '1s';
var hSpan = '1s';
var sIncr = 0;
var mIncr = 0;
var hIncr = 0;
var sDeg, mDeg, hDeg, sPre, mPre, hPre;
var idx = d.getElementsByTagName('div').length;
d.write('<div id = "'+rndId+'" style="display:inline-block;line-height:0px;"></div>');

function xy(a) {
    return (a * clockSize / 100);
}

var dial = d.createElement('div');
dial.setAttribute('style', 'display: inline-block;'
    +'position: relative;'
    +'height: '+clockSize+'px;'
    +'width: '+clockSize+'px;'
    +'margin: 0px;padding: 0px;'
    +'border-radius: 5%;z-index: 1;'
    +'background-color: '+dialcol+';');
d.getElementById(rndId).appendChild(dial);

for (var i = 0; i < 12; i++) {

    var incr = xy(2.0) + (i * xy(0.2));

    mrkrs[i] = d.createElement('div');
    mrkrs[i].setAttribute('style', 'display: block;'
        +'position: absolute;'
        +'width: '+xy(14)+'px;'
        +'height: '+xy(14)+'px;'
        +'margin: auto; top: 0;bottom: 0;left: 0;right: 0;'
        +'font-size: 0px;line-height: 0px;padding: 0;'
        +'text-align: center !important;'
        +'background-color: transparent;');

    mrkrs[i].innerHTML = '<div style = "display: inline-block;'
    +'position: relative;width: '+incr+'px;height: '+xy(14)+'px;'
    +'font-size: 0px;background-color:'+handcol+';'
    +'margin-right: '+xy(0.6)+'px;"></div>'
    +'<div style = "display:inline-block;position: relative;'
    +'width: '+incr+'px;height: '+xy(14)+'px;font-size: 0px;'
    +'margin-left: '+xy(0.6)+'px;'
    +'background-color:'+handcol+';"></div>';

    dial.appendChild(mrkrs[i]);
    degr += 30;

    mrkrs[i].style.top = xy(0) + xy(77) * 
        Math.sin(-offs + e * i * radi) + 'px';
    mrkrs[i].style.left= xy(0) + xy(77) * 
        Math.cos(-offs + e * i * radi) + 'px';
    mrkrs[i].style.transform = 'rotate(' + (degr) + 'deg)';
    mrkrs[i].style.transformOrigin = 'center center';
}

/* Hour CSS */

var hCss = 'display: block;'
    +'position: absolute;'
    +'height: '+xy(56)+'px;'
    +'width: '+xy(6)+'px;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'margin: auto; top: 0;bottom: 0; left: 0; right: 0;'
    +'transform-origin: center center 0;'
    +'z-index: 2;';
var hClone = hCss;

var houHand = d.createElement('div');
houHand.setAttribute('style', hClone);
dial.appendChild(houHand);

var hh = d.createElement('div');
hh.setAttribute('style', 'display: block;'
    +'position: absolute;'
    +'height: '+xy(21)+'px;'
    +'width: '+xy(6)+'px;' 
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'margin: auto; top: 0; left: 0; right: 0;'
    +'background-color: '+handcol+';');
houHand.appendChild(hh);

/* Minute CSS */

var mCss = 'display: block;'
    +'position: absolute;'
    +'height: '+xy(86)+'px;'
    +'width: '+xy(4)+'px;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'margin: auto; top: 0; bottom: 0; left: 0; right: 0;'
    +'transform-origin: center center;'
    +'z-index: 3;';
var mClone = mCss;

var minHand = d.createElement('div');
minHand.setAttribute('style', mClone);
dial.appendChild(minHand);

var mh = d.createElement('div');
mh.setAttribute('style', 'display: block;'
    +'position: absolute;'
    +'height: '+xy(36)+'px;'
    +'width: '+xy(4)+'px;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'margin: auto; top: 0; left: 0; right: 0;'
    +'background-color: '+handcol+';');
minHand.appendChild(mh);

/* Second CSS */

var sCss = 'display: block;'
    +'position: absolute;'
    +'height: '+xy(90)+'px;'
    +'width: '+xy(2)+'px;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'margin: auto; top: 0;bottom: 0; left: 0; right: 0;'
    +'transform-origin: center center;'
    +'z-index: 4;';
var sClone = sCss;

var secHand = d.createElement('div');
secHand.setAttribute('style', sClone);
dial.appendChild(secHand);

var sh = d.createElement('div');
sh.setAttribute('style', 'display: block;'
    +'position: absolute;'
    +'height: '+xy(39)+'px;'
    +'width: '+xy(2)+'px;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'margin: auto; top: 0; left: 0; right: 0;'
    +'background-color: '+handcol+';');
secHand.appendChild(sh);

var sectail = d.createElement('div');
sectail.setAttribute('style', 'display: block;'
    +'position: absolute;'
    +'height: '+xy(12)+'px;'
    +'width: '+xy(2)+'px;'
    +'margin: auto; left: 0; right: 0;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'top: '+xy(52)+'px;'
    +'background-color: '+handcol+';');
secHand.appendChild(sectail);

/* Centre nut & optional glass front CSS */

var nut = d.createElement('div');
nut.setAttribute('style', 'display: inline-block;'
    +'position: absolute;'
    +'height: '+xy(10)+'px;'
    +'width: '+xy(10)+'px;'
    +'font-size: 0px;line-height: 0px;padding: 0;'
    +'border: '+xy(3)+'px solid '+handcol+';'
    +'border-radius: 50%;'
    +'margin: auto;top: 0;bottom: 0;left: 0;right: 0;'
    +'background-color: transparent;'
    +'z-index: 5;');
dial.appendChild(nut);

var glass = d.createElement('div');
glass.setAttribute('style', 'display: block;'
    +'height:'+clockSize+'px;'
    +'width: '+clockSize+'px;'
    +'border-radius:'+xy(5)+'px;'
    +'margin: auto;top: 0;bottom: 0;left: 0;right: 0;'
    +'z-index: 6;box-shadow:'
    +'0 '+xy(1)+'px '+xy(1)+'px rgba(0,0,0,0.5),'
    +'inset 0 '+xy(1)+'px rgba(255,255,255,0.3),'
    +'inset 0 '+xy(10)+'px rgba(255,255,255,0.2),'
    +'inset 0 '+xy(10)+'px '+xy(20)+'px rgba(255,255,255,0.25),'
    +'inset 0 -'+xy(15)+'px '+xy(30)+'px rgba(0,0,0,0.3);');
dial.appendChild(glass);

var eiatf = 'translateZ(0); animation-timing-function: ease-in';
var eoatf = 'translateZ(0); animation-timing-function: ease-out';

function secKeyFrames() {
    var secSheet = (d.getElementById('tmpSecSheet'+idx));
    if (secSheet) {
        secSheet.outerHTML = '';
    }
    
    sClone = sCss;
 
    var p1 = sDeg;
    var p2 = sDeg+6;
    var p3 = sDeg+4;
    var p4 = sDeg+6;
    var p5 = sDeg+5; 
    var p6 = sDeg+6; 

    var secframes = '@keyframes reGen'+sIncr+' { '
    +'0% { transform: rotate('+p1+'deg) '+eiatf+';}'
    +'30% { transform: rotate('+p2+'deg) '+eoatf+';}'
    +'45% { transform: rotate('+p3+'deg) '+eiatf+';}'
    +'60% { transform: rotate('+p4+'deg) '+eoatf+';}' 
    +'70% { transform: rotate('+p5+'deg) '+eiatf+';}'
    +'80%,100% { transform: rotate('+p6+'deg) '+eoatf+';}}';

    var ss = document.createElement( 'style' );
    ss.setAttribute('id', 'tmpSecSheet'+idx);
    ss.innerHTML = secframes;
    document.getElementsByTagName('head')[0].appendChild(ss);

    var secAni = 'animation: reGen'+sIncr+' '+sSpan+' 1 forwards;';
    sClone += secAni;
    secHand.setAttribute('style', sClone);
    dial.appendChild(secHand);
}

function minKeyFrames() {
    var minSheet = (d.getElementById('tmpMinSheet'+idx));
    if (minSheet) {
        minSheet.outerHTML = '';
    }

    mClone = mCss;
 
    var p1 = mDeg;
    var p2 = mDeg+6;
    var p3 = mDeg+4;
    var p4 = mDeg+6;
    var p5 = mDeg+5; 
    var p6 = mDeg+6;

    var minframes = '@keyframes minGen'+mIncr+' { '
    +'0% { transform: rotate('+p1+'deg) '+eiatf+';}'
    +'30% { transform: rotate('+p2+'deg) '+eoatf+';}'
    +'45% { transform: rotate('+p3+'deg) '+eiatf+';}'
    +'60% { transform: rotate('+p4+'deg) '+eoatf+';}' 
    +'70% { transform: rotate('+p5+'deg) '+eiatf+';}'
    +'80%,100% { transform: rotate('+p6+'deg) '+eoatf+';}}';

    var ms = document.createElement( 'style' );
    ms.setAttribute('id', 'tmpMinSheet'+idx);
    ms.innerHTML = minframes;
    d.getElementsByTagName('head')[0].appendChild(ms);

    var minAni = 'animation: minGen'+mIncr+' '+mSpan+' 1 forwards;';
    mClone += minAni;
    minHand.setAttribute('style', mClone);
    dial.appendChild(minHand);
}

function houKeyFrames() {
    var houSheet = (d.getElementById('tmphouSheet'+idx));
    if (houSheet) {
        houSheet.outerHTML = '';
    }

    hClone = hCss;
 
    var p1 = hDeg;
    var p2 = hDeg+1;
    var p3 = hDeg+0.4;
    var p4 = hDeg+1;
    var p5 = hDeg+0.5; 
    var p6 = hDeg+1; 

    var houframes = '@keyframes houGen'+hIncr+' { '
    +'0% { transform: rotate('+p1+'deg) '+eiatf+';}'
    +'30% { transform: rotate('+p2+'deg) '+eoatf+';}'
    +'45% { transform: rotate('+p3+'deg) '+eiatf+';}'
    +'60% { transform: rotate('+p4+'deg) '+eoatf+';}' 
    +'70% { transform: rotate('+p5+'deg) '+eiatf+';}'
    +'80%,100% { transform: rotate('+p6+'deg) '+eoatf+';}}';

    var hs = document.createElement( 'style' );
    hs.setAttribute('id', 'tmphouSheet'+idx);
    hs.innerHTML = houframes;
    d.getElementsByTagName('head')[0].appendChild(hs);

    var houAni = 'animation: houGen'+hIncr+' '+hSpan+' 1 forwards;';
    hClone += houAni;
    houHand.setAttribute('style', hClone);
    dial.appendChild(houHand);
}

function animate() {
    var x = new Date();
    var seconds = x.getSeconds();
    var minutes = x.getMinutes();
    var hours = (x.getHours() * 30) + (x.getMinutes() / 2);
    
    if (seconds !== sPre) {
        sIncr++;
        sDeg = (seconds-1) * 6;
        secHand.removeAttribute('style');
        secKeyFrames();
        if (sIncr > 59) {
            sIncr = 0;
        }
    }

    if (minutes !== mPre) {
        mIncr++;
        mDeg = (minutes-1) * 6;
        minHand.removeAttribute('style');
        minKeyFrames();
        if (mIncr > 59) {
            mIncr = 0;
        }
    }

    if (hours !== hPre) {
        hIncr++;
        hDeg = (hours-1) * 1;
        houHand.removeAttribute('style');
        houKeyFrames();
        if (hIncr > 59) {
            hIncr = 0;
        }    
    }

    sPre = seconds;
    mPre = minutes;
    hPre = hours;
}

function cyc() {
    var pres = performance.now(); 
    if ((pres - prev) > mls) {
        animate();
        prev = performance.now();
    }
    window.requestAnimationFrame(cyc);
} 

window.addEventListener('load', cyc, false);
})();
&#13;
&#13;
&#13;