css动态动画开始位置与vuejs

问题描述 投票:0回答:1

我的网页上有一个音频元素,我正在使用 CSS 和 VueJS 创建一个循环进度指示器来显示已播放的音频量。一切都按照我想要的方式进行,随着音频的播放,我看到进度在变化。

我遇到的问题是当我想将音频移动到新位置时,我无法获取更新进度。

非常感谢任何帮助或建议。

我认为我应该使用

animation-range
并为其绑定一个值,但这不起作用。

<template>
  <div ref="mainCover" id="main_cover" @click="onClick">
    <div class="progress blue">
      <span class="progress-left">
          <span class="progress-bar"></span>
      </span>
      <span class="progress-right">
          <span class="progress-bar"></span>
      </span>
      <div class="progress-value">90%</div>
    </div>
  </div>
</template>

<script setup>
import { defineProps, ref, onMounted, inject } from 'vue'
import { useEventListener } from '@vueuse/core';

const { duration } = defineProps({
  duration: {
    type: String,
    required: false,
  },
})

let isPlaying = ref('paused')
let startPosition = ref(0 + '%')

eventBus.on('playing', () => {
  isPlaying.value = 'running'
})

eventBus.on('paused', () => {
  isPlaying.value = 'paused'
})

const halfDuration = ref((duration / 2) + 's')

eventBus.on('timeupdate', (currentTime) => {
  startPosition.value = (currentTime / duration) * 100 + '%'
})

const mainCover = ref()

</script>

<style lang="css" scoped>
.progress{
    width: 150px;
    height: 150px;
    line-height: 150px;
    background: none;
    margin: 0 auto;
    box-shadow: none;
    position: relative;
}
.progress:after{
    content: "";
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 5px solid #f2f5f5;
    position: absolute;
    top: 0;
    left: 0;
}
.progress > span{
    width: 50%;
    height: 100%;
    overflow: hidden;
    position: absolute;
    top: 0;
    z-index: 1;
}
.progress .progress-left{
    left: 0;
}
.progress .progress-bar{
    width: 100%;
    height: 100%;
    background: none;
    border-width: 5px;
    border-style: solid;
    position: absolute;
    top: 0;
}
.progress .progress-left .progress-bar{
    left: 100%;
    border-top-right-radius: 80px;
    border-bottom-right-radius: 80px;
    border-left: 0;
    -webkit-transform-origin: center left;
    transform-origin: center left;
}
.progress .progress-right{
    right: 0;
}
.progress .progress-right .progress-bar{
    left: -100%;
    border-top-left-radius: 80px;
    border-bottom-left-radius: 80px;
    border-right: 0;
    -webkit-transform-origin: center right;
    transform-origin: center right;
    animation: loading-1 v-bind('halfDuration') linear forwards;
    animation-play-state: v-bind('isPlaying');
    animation-range: v-bind('startPosition');
}
.progress .progress-value{
    width: 100%;
    height: 100%;
    font-size: 24px;
    color: rgb(250, 245, 245);
    text-align: center;
    position: absolute;
}
.progress.blue .progress-bar{
    border-color: #26abfd;
}
.progress.blue .progress-left .progress-bar{
    animation: loading-1 v-bind('halfDuration') linear forwards v-bind('halfDuration');
    animation-play-state: v-bind('isPlaying');
    animation-range: v-bind('startPosition');
}

@keyframes loading-1{
    0%{
        -webkit-transform: rotate(0deg);
        transform: rotate(0deg);
    }
    100%{
        -webkit-transform: rotate(180deg);
        transform: rotate(180deg);
    }
}
</style>
css vue.js css-animations progress-bar
1个回答
0
投票

在得到我需要但不完全的结果后,我决定做更多研究并发现一篇很棒的文章https://www.30secondsofcode.org/css/s/circular-progress-bar/

我用文章中的内容替换了 HTML 和 CSS,并且能够更新我的代码,使其完全符合我的要求。

附上我更新的代码。

<template>
  <svg width="150" height="150" viewBox="0 0 150 150" class="circular-progress" @click="onClick">
    <circle class="bg"></circle>
    <circle class="fg"></circle>
  </svg>
</template>

<script setup>
import { defineProps, ref, onMounted, inject } from 'vue'
import { useEventListener } from '@vueuse/core';

const { duration } = defineProps({
  duration: {
    type: String,
    required: false,
  },
})

const eventBus = inject('eventBus')

const animationDuration = ref(duration + 's')
const animationDelay = ref(0 + 's') 
const animationPlayState = ref('paused')

eventBus.on('playing', () => {
  animationPlayState.value = 'running'
})

eventBus.on('paused', () => {
  animationPlayState.value = 'paused'
})

eventBus.on('seeking', (currentTime) => {
  animationDelay.value = ((duration - (duration - currentTime)) * -1) + 's'
})

eventBus.on('timeupdate', (currentTime) => {
  if(currentTime === 0) {
    animationDelay.value = 0
  }
})

const onClick = () => {
  eventBus.emit('playPauseClick')
}

</script>

<style lang="css" scoped>
.circular-progress {
  --size: 150px;
  --half-size: calc(var(--size) / 2);
  --stroke-width: 5px;
  --radius: calc((var(--size) - var(--stroke-width)) / 2);
  --circumference: calc(var(--radius) * pi * 2);
  --dash: calc((var(--progress) * var(--circumference)) / 100);
  animation: progress-animation v-bind('animationDuration') linear v-bind('animationDelay') 1 forwards;
  animation-play-state: v-bind('animationPlayState')
}

.circular-progress circle {
  cx: var(--half-size);
  cy: var(--half-size);
  r: var(--radius);
  stroke-width: var(--stroke-width);
  fill: none;
  stroke-linecap: butt;
}

.circular-progress circle.bg {
  stroke: #ddd;
}

.circular-progress circle.fg {
  transform: rotate(-90deg);
  transform-origin: var(--half-size) var(--half-size);
  stroke-dasharray: var(--dash) calc(var(--circumference) - var(--dash));
  transition: stroke-dasharray 0.3s linear 0s;
  stroke: #5394fd;
}

@property --progress {
  syntax: "<number>";
  inherits: false;
  initial-value: 0;
}

@keyframes progress-animation {
  from {
    --progress: 0;
  }
  to {
    --progress: 100;
  }
}
</style>
© www.soinside.com 2019 - 2024. All rights reserved.