1

Есть такой таймер обратного отсчета, вида 00.000 (секунды.милисекунды), на JS чистом просто. Реализуется путём innerHTML в див с помощью requestAnimationFrame, что по сути получается замыканием. Вот код:

let freshBtn = document.querySelector(".fresh");
freshBtn.addEventListener("click", onCleanJS);

function onCleanJS() {

let max = 5; let min = 2; let randomAge = Math.floor(Math.random() * (max - min + 1)) + min;

let timeElem = document.getElementById("time"), countdown = new Date(), responseTime = new Date(Date.now() + 1000 * randomAge); // таймер на randomAge секунд

function startTime() { countdown.setTime(responseTime - Date.now()); timeElem.innerHTML = countdown.getUTCSeconds() + "." + countdown.getUTCMilliseconds(); if ( countdown.getUTCHours() > 0 || countdown.getUTCMinutes() > 0 || countdown.getUTCSeconds() > 0 ) { requestAnimationFrame(startTime); } else { timeElem.innerHTML = "Текущее время: " + new Date().toLocaleTimeString(); } } requestAnimationFrame(startTime); }

<br/><hr>
<div id="time"></div>
<br/>
<button class="fresh">Вот на чистом JS счётчик</button>

JS Counter

Возникла задача, реализовать это компонентов на vue.js и добавлять эти компоненты на сцену. Вот код:

Vue.component("count", {
  template: `
    <div class="count">
   &lt;div class="count_dino"&gt;
    &lt;svg width="50px" height="50px" viewBox="13 0 285 306" version="1.1"      xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"&gt;
    &lt;g id="Group-3" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(13.000000, 0.000000)"&gt;
    &lt;polygon id="Path" fill="#666666" points="256.351585 91.6642857 213.916427 91.6642857 213.916427 80.0385714 284.492795 80.0385714 284.492795 14.3085714 270.198847 14.3085714 270.198847 0 155.400576 0 155.400576 14.3085714 141.553314 14.3085714 141.553314 105.972857 127.259366 105.972857 127.259366 119.834286 106.26513 119.834286 106.26513 134.142857 85.2708934 134.142857 85.2708934 148.451429 70.9769452 148.451429 70.9769452 162.312857 45.0691643 162.312857 45.0691643 148.004286 31.221902 148.004286 31.221902 134.142857 16.9279539 134.142857 16.9279539 105.972857 0.847262248 105.972857 0.847262248 192.718571 14.6945245 192.718571 14.6945245 207.027143 28.9884726 207.027143 28.9884726 220.888571 42.8357349 220.888571 42.8357349 235.197143 57.129683 235.197143 57.129683 249.058571 70.9769452 249.058571 70.9769452 305.398571 101.351585 305.398571 101.351585 289.301429 87.5043228 289.301429 87.5043228 277.228571 101.351585 277.228571 101.351585 263.367143 115.645533 263.367143 115.645533 249.058571 127.259366 249.058571 127.259366 263.367143 141.553314 263.367143 141.553314 305.398571 171.927954 305.398571 171.927954 289.301429 157.634006 289.301429 157.634006 235.197143 171.927954 235.197143 171.927954 220.888571 185.775216 220.888571 185.775216 199.872857 200.069164 199.872857 200.069164 150.687143 211.682997 150.687143 211.682997 164.548571 228.210375 164.548571 228.210375 134.142857 200.069164 134.142857 200.069164 108.208571 256.351585 108.208571"&gt;&lt;/polygon&gt;
    &lt;rect id="Rectangle" fill="#FFFFFF" x="169.247839" y="20.5685714" width="16.9740634" height="16.9914286"&gt;&lt;/rect&gt;
    &lt;/g&gt;
    &lt;/svg&gt;
  &lt;/div&gt;

  &lt;div class="count_title"&gt;... динозавр вымрет через:&lt;/div&gt;
  &lt;div class="count_counter"&gt;{{ counRunner }}&lt;/div&gt;
 &lt;/div&gt;

`, data() { return { counRunner: 88 }; }, props: { dinoColors: { type: Array, default: () => [] } }, computed: { vars() { this.counRunner = this.timeProgress } }, methods: {

startCount() {

  let timeProgress,
      countdown = new Date(),
      responseTime = new Date(Date.now() + 1000 * 2); // таймер 2 секунды

  function animation() {
    countdown.setTime(responseTime - Date.now());
    timeProgress = countdown.getUTCSeconds() + "." + countdown.getUTCMilliseconds();

    //console.log(timeProgress)

    if (countdown.getUTCHours() &gt; 0 || countdown.getUTCMinutes() &gt; 0 || countdown.getUTCSeconds() &gt; 0) {
      requestAnimationFrame(animation);
    } else {
      alert("готово")
    }
    return timeProgress;
  }
  requestAnimationFrame(animation);
}

},

mounted: function() { //console.log(this.$el.this.time) this.startCount(); } });

new Vue({ el: "#app", data: { counters: [ { title: "И динозавр вымирает через :", url: " " } ], greeting: "<h4>Welcome</h4>", message: "You loaded this page on " + new Date().toLocaleTimeString(), timeNow: new Date().toLocaleTimeString() }, methods: { addCount() { this.counters.push({ id: 0, title: "И динозавр вымирает через :", url: " " }); } }, created: function() { // время setInterval(() => { this.timeNow = new Date().toLocaleTimeString(); }, 1000); } });

//------ просто на JS счетчик --------------------------------------------

let freshBtn = document.querySelector(".fresh"); freshBtn.addEventListener("click", onCleanJS);

function onCleanJS() {

let max = 5; let min = 2; let randomAge = Math.floor(Math.random() * (max - min + 1)) + min;

let timeElem = document.getElementById("time"), countdown = new Date(), responseTime = new Date(Date.now() + 1000 * randomAge); // таймер на randomAge секунд

function startTime() { countdown.setTime(responseTime - Date.now()); timeElem.innerHTML = countdown.getUTCSeconds() + "." + countdown.getUTCMilliseconds(); if ( countdown.getUTCHours() > 0 || countdown.getUTCMinutes() > 0 || countdown.getUTCSeconds() > 0 ) { requestAnimationFrame(startTime); } else { timeElem.innerHTML = "Динозавр вымер в: " + new Date().toLocaleTimeString(); } } requestAnimationFrame(startTime); }

@import url("https://fonts.googleapis.com/css?family=Open+Sans");
body, html {
  font-family: 'Open Sans', sans-serif;
}

#app .adding {
  display: flex;
  justify-content: center;
}
#app .adding_Btn {
  font-weight: bold;
  text-align: center;
  cursor: pointer;
  margin: 20px 0;
}
#app .counters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
#app .counters .count {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 15%;
  align-items: center;
  border: 1px solid #504949;
  padding: 10px;
  margin: 10px;
  border-radius: 4px;
}
#app .counters .count_title {
  color: #a02828;
  margin-bottom: 5px;
  margin-top: 5px;
}
#app .counters .count_dino {
  transform: rotate(0deg);
}
#app .counters .count_counter {
  font-size: 1.2em;
  font-weight: bold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
  <span v-html="greeting"></span> 
  <br /> Время сейчас : {{ timeNow }}
  <hr>

  <div class="adding">
    <button class="adding_Btn" title="Время вымирать" @click="addCount">Добавить компонент</button>
  </div>

  <component class="counters">
    <count v-for="item in counters"></count>
  </component>

</div>

<br/>
<hr>
<div id="time"></div>
<button class="fresh">Вот на чистом JS счётчик</button>

Vue.js project

Всё вроде ок, но нет визуализации таймера. Пытаюсь реализовать путём присваивания переменной counRunner, значения переменной timeProgress которая ретёрнится из функции анимации animation(). И никак не могу получить реактивность из за областей видимости видимо. В консоли отлавливаются переменные, но нет реактивности для анимации счетчиков.

Буду благодарен за помощь или исправление, кручусь где то рядом вроде и никак. Первый раз просто во vue применяю requestAnimationFrame.

  • 1
    причем тут замыкание, если ты нигде не выводишь текущий счетчик? – Grundy May 01 '19 at 18:39
  • @Grundy подразумевалось выводить переменную в див под динозавром:
    {{ counRunner }}
    только this. забыл. А перед этим:

    http://prntscr.com/nj8tbo

    переменная выводится из счетчика и переназначается в компьютед, как на скрине. Но что то я не рублю уже совсем. Завтра попробую пересмотреть, не то что то делаю

    – Jack Kosovskiy May 01 '19 at 20:43

0 Answers0