CSS Transition不会影响变换旋转?

时间:2016-10-24 23:06:52

标签: javascript html css3 svg css-transitions

我正在尝试在时钟代码的秒数滴答中使用转换,使其像自动监视一样工作,如watch中的秒数滴答,这是codepen.io中的演示和代码

function setAttributes(el, attrs) {
  for(var key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}

function setAttrib(id, val) {
    // body...
    var v = 'rotate('+val+',220,220)';
    if(id==='sec') {
        setAttributes(document.getElementById(id), {"transform": v, "transition": "transform 13s ease"});
    } else {
        document.getElementById(id).setAttribute('transform', v);
    }
};

我试图在秒刻度上使用毫秒',但它不起作用。我只想设置动画秒刻度'以像自动时钟一样工作,我测试了其中的其他过渡,但我认为没有效果。我不知道这段代码有什么问题?帮助

1 个答案:

答案 0 :(得分:3)

使用CSS过渡(不推荐用于下面提到的原因)

正如我在评论中提到的那样,您使用https://jsfiddle.net/fpwo8e7e/1/来轮换line,因此transition设置不会对其产生任何影响。您必须通过style属性使用CSS转换才能使用transition。以下是SVG's transform attribute

的摘录
  

'transition-property'属性指定应用转换的CSS属性的 名称

(重点是我的)

与SVG transform-origin属性不同,您还必须单独设置transform

使用这种方法的问题是从59s到0s / 60s的旋转是旋转角度从354deg变为0deg,它将反向运动,从而破坏时钟效应。

function clock() {
  // body...
  var d, h, m, s;
  d = new Date;

  h = 30 * ((d.getHours() % 12) + d.getMinutes() / 60);
  m = 6 * d.getMinutes();
  s = 6 * d.getSeconds();

  setAttrib('h', h);
  setAttrib('m', m);
  setAttrib('s', s);
  setAttrib('st', s + 180);

  h = d.getHours();
  m = d.getMinutes();
  s = d.getSeconds();

  (h >= 12) ? setText('suffix', 'PM'): setText('suffix', 'AM');

  if (h != 12) {
    h %= 12;
  }

  setText('hr', h);
  setText('min', m);
  setText('sec', s);

  setTimeout(clock, 1);
};

function setAttributes(el, attrs) {
  for (var key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}

function setAttrib(id, val) {
  // body...
  var v = 'rotate(' + val + 'deg)';
  if (id === 's') {
    setAttributes(document.getElementById(id), {
      "style": "transform:" + v + "; transform-origin: 220px 220px"
    });
  } else {
    document.getElementById(id).setAttribute('style', "transform:" + v + "; transform-origin: 220px 220px");
  }
};

function setText(id, val) {
  // body...
  if (val < 10) {
    val = "0" + val;
  }

  document.getElementById(id).innerHTML = val;
};

window.onload = clock;
* {
  margin: 0;
  padding: 0;
  font-size: 36px;
}
.analog-clock {
  position: relative;
  display: flex;
  align-items: center;
  text-align: center;
  border: solid green 2px;
  flex-direction: column;
  box-sizing: border-box;
  justify-content: center;
}
#clock {
  stroke: red;
  stroke-width: 2px;
  fill: white;
}
#h,
#m,
#s,
#st {
  stroke: black;
  stroke-linecap: round;
  /**/
}
#h {
  stroke-width: 5.5px;
}
#m {
  stroke-width: 3px;
}
#s {
  stroke-width: 1.5px;
}
#st {
  stroke-width: 1.5px;
}
.time-text {
  text-align: center;
}
#s,
#st {
  transition: transform 1s ease;
}
<div class="analog-clock">
  <svg width='440' height='440'>
    <circle id='clock' cx="220" cy='220' r='218' />

    <line id='h' x1='220' x2='220' y1='220' y2='38' />
    <line id='m' x1='220' x2='220' y1='220' y2='20' />
    <line id='s' x1='220' x2='220' y1='220' y2='12' />
    <line id='st' x1='220' x2='220' y1='220' y2='166' />

    <text x='204' y='30'>12</text>
    <text x='420' y='232'>3</text>
    <text x='210' y='435'>6</text>
    <text x='3' y='232'>9</text>

  </svg>

  <div class="time-text">
    <span id="hr">00</span>
    <span>:</span>
    <span id="min">00</span>
    <span>:</span>
    <span id="sec">00</span>
    <span id="suffix">--</span>
  </div>
</div>

使用更高的刷新率:(推荐)

要克服CSS过渡的问题,但仍然有动画效果,可以通过减少超时持续时间来增加刷新率,并使用毫秒也可以计算。

由于缓和效果,CSS输出会更令人赏心悦目,但据我所知,用JS实现它是不可能的。

function clock() {
  // body...
  var d, h, m, s, ms;
  d = new Date;

  h = 30 * ((d.getHours() % 12) + d.getMinutes() / 60);
  m = 6 * d.getMinutes();
  s = 6 * d.getSeconds();
  ms = 6 * d.getMilliseconds();

  setAttrib('h', h);
  setAttrib('m', m);
  setAttrib('s', s + (ms == 0 ? 1 : ms / 1000));
  setAttrib('st', s + (ms == 0 ? 1 : ms / 1000) + 180);

  h = d.getHours();
  m = d.getMinutes();
  s = d.getSeconds();
  ms = d.getMilliseconds();

  (h >= 12) ? setText('suffix', 'PM'): setText('suffix', 'AM');

  if (h != 12) {
    h %= 12;
  }

  setText('hr', h);
  setText('min', m);
  setText('sec', s + '.' + ms);

  setTimeout(clock, 1);
};

function setAttributes(el, attrs) {
  for (var key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}

function setAttrib(id, val) {
  // body...
  var v = 'rotate(' + val + 'deg)';
  if (id === 's') {
    setAttributes(document.getElementById(id), {
      "style": "transform:" + v + "; transform-origin: 220px 220px"
    });
  } else {
    document.getElementById(id).setAttribute('style', "transform:" + v + "; transform-origin: 220px 220px");
  }
};

function setText(id, val) {
  // body...
  if (val < 10) {
    val = "0" + val;
  }

  document.getElementById(id).innerHTML = val;
};

window.onload = clock;
* {
  margin: 0;
  padding: 0;
  font-size: 36px;
}
.analog-clock {
  position: relative;
  display: flex;
  align-items: center;
  text-align: center;
  border: solid green 2px;
  flex-direction: column;
  box-sizing: border-box;
  justify-content: center;
}
#clock {
  stroke: red;
  stroke-width: 2px;
  fill: white;
}
#h,
#m,
#s,
#st {
  stroke: black;
  stroke-linecap: round;
  /**/
}
#h {
  stroke-width: 5.5px;
}
#m {
  stroke-width: 3px;
}
#s {
  stroke-width: 1.5px;
}
#st {
  stroke-width: 1.5px;
}
.time-text {
  text-align: center;
}
<div class="analog-clock">
  <svg width='440' height='440'>
    <circle id='clock' cx="220" cy='220' r='218' />

    <line id='h' x1='220' x2='220' y1='220' y2='38' />
    <line id='m' x1='220' x2='220' y1='220' y2='20' />
    <line id='s' x1='220' x2='220' y1='220' y2='12' />
    <line id='st' x1='220' x2='220' y1='220' y2='166' />

    <text x='204' y='30'>12</text>
    <text x='420' y='232'>3</text>
    <text x='210' y='435'>6</text>
    <text x='3' y='232'>9</text>

  </svg>

  <div class="time-text">
    <span id="hr">00</span>
    <span>:</span>
    <span id="min">00</span>
    <span>:</span>
    <span id="sec">00</span>
    <span id="suffix">--</span>
  </div>
</div>

也许使用W3C spec on transitions也可以产生缓和效果而不会出现反向旋转问题,但它在Chrome中至少不会起作用,因为他们已经弃用了SMIL动画。