@fessss

Круговой таймер обратного отсчета?

Здравствуйте, делаю таймер отсчета до даты на vue
сам таймер сделал, но так как не работал с svg понятия не имею, как сделать круговой таймер.

<div id="timer">
  <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
    :width="width" :height="width"
  >
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      opacity="0.4"
      :stroke="color" 
      :stroke-width="border"
    />
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      transform="rotate(270,100,100)" 
      :stroke="color" 
      :stroke-width="border"
      :stroke-dasharray="dashLen" 
      :stroke-dashoffset = "days | myFilter"
      style="transition: stroke-dashoffset 0.4s"
    />
    <text x="100" y="100" text-anchor="middle"
      :font-size="fontSize + 5" 
      :fill="color" 
    >
      {{ days | myFilter }}
    </text>
  </svg>
  <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
    :width="width" :height="width"
  >
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      opacity="0.4"
      :stroke="color" 
      :stroke-width="border"
    />
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      transform="rotate(270,100,100)" 
      :stroke="color" 
      :stroke-width="border"
      :stroke-dasharray="dashLen" 
      :stroke-dashoffset = "hours | myFilter"
      style="transition: stroke-dashoffset 0.4s"
    />
    <text x="100" y="100" text-anchor="middle"
      :font-size="fontSize + 5" 
      :fill="color" 
    >
      {{ hours | myFilter }}
    </text>
  </svg>
  <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
    :width="width" :height="width"
  >
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      opacity="0.4"
      :stroke="color" 
      :stroke-width="border"
    />
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      transform="rotate(270,100,100)" 
      :stroke="color" 
      :stroke-width="border"
      :stroke-dasharray="dashLen" 
      :stroke-dashoffset = "minutes | myFilter"
      style="transition: stroke-dashoffset 0.4s"
    />
    <text x="100" y="100" text-anchor="middle"
      :font-size="fontSize + 5" 
      :fill="color" 
    >
      {{ minutes | myFilter }}
    </text>
  </svg>
  <svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"
    :width="width" :height="width"
  >
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      opacity="0.4"
      :stroke="color" 
      :stroke-width="border"
    />
    <circle cx="100" cy="100" :r="100 - border / 2" 
      fill="none"
      transform="rotate(270,100,100)" 
      :stroke="color" 
      :stroke-width="border"
      :stroke-dasharray="dashLen" 
      :stroke-dashoffset = "seconds | myFilter"
      style="transition: stroke-dashoffset 0.4s"
    />
    <text x="100" y="100" text-anchor="middle"
      :font-size="fontSize + 5" 
      :fill="color" 
    >
      {{ seconds | myFilter }}
    </text>
  </svg>
</div>


mounted () {
  window.setInterval(() => {
    this.now = Math.trunc((new Date()).getTime() / 1000)
  }, 1000)
},

props: {
  date: {
    type: String
  },
  width: {
    type: Number,
    default: 80
  },
  border: {
    type: Number,
    default: 8
  },
  color: {
    type: String,
    default: '#fcaa55'
  },
  fontSize: {
    type: Number,
    default: 30
  }
},

data() {
    return {
      now: Math.trunc((new Date()).getTime() / 1000),
      dashLen: (100 - this.border / 2) * Math.PI * 2
    }
},

computed: {
  modifiedDate () {
    return Math.trunc(Date.parse(this.date) / 1000)
  },
  seconds () {
    return (this.modifiedDate - this.now) % 60
  },
  minutes () {
    return Math.trunc((this.modifiedDate - this.now) / 60) % 60
  },
  hours() {
      return Math.trunc((this.modifiedDate - this.now) / 60 / 60) % 24;
  },
  days() {
      return Math.trunc((this.modifiedDate - this.now) / 60 / 60 / 24);
  }
},

filters: {
  myFilter: function (value) {
    if (value.toString().length <= 1) {
      return '0' + value.toString()
    }
    return value.toString()
  }
}


Доработал. Таймер работает. Но не правильно считает бордер. Подскажите
  • Вопрос задан
  • 1660 просмотров
Решения вопроса 1
0xD34F
@0xD34F Куратор тега Vue.js
Наверное, вместо того, чтобы лепить 4 svg вручную, следовало сделать отдельный компонент, который бы представлял один из элементов даты, и создать 4 экземпляра этого компонента - для дней, часов, минут и секунд. Каждый из экземпляров компонента получал бы собственные максимальные значения счётчика (365 дней в году, 24 часа в сутках, ...), на основе которых можно рассчитывать значения stroke-dashoffset независимо от остальных экземпляров. Как-то так.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы