CSS动画的重复播放及保持原效果

遇到的问题

无法让动画重复播放,每次播放结束后都无法继续播放
如果设置为可以多次播放,则又无法保持原状态(设置多次播放是通过重写了animation属性实现;一旦重写,这个 forwards 就没用了)

相关代码

转盘小游戏,Vue3代码

<template>
    <div id="app">
        <canvas id="canvas" :width="data.radius" :height="data.radius" class="container">canvas>
        <span class="play" @click="play">点击开启转盘span>
    div>
template>

<script>
import { onBeforeMount, onMounted, reactive } from "vue";

export default {
    name: "App",
    setup() {
        onBeforeMount(() => {
            const widthOfDevice = document.body.clientWidth;
            data.radius = widthOfDevice * 0.8;
        });
        const data = reactive({
            awardList: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
            radius: 200
        });

        function play() {
            const randomDeg = 360 * 8 + parseInt(Math.random() * 360 * 2);
            document.styleSheets[0].insertRule(
                `@keyframes run-rotate {
                    from {
                        transform: rotateZ(0deg);
                    }
                    to {
                        transform: rotateZ(${randomDeg}deg);
                    }
                }`,
            );
        }

        onMounted(() => {
            const myCanvas = document.getElementById("canvas");
            draw(myCanvas);
        });

        const randomColorList = ["#4169e199", "#fa807299", "#98fb9899", "#f5deb399", "#dda0dd99"];
        function draw(myCanvas) {
            const ctx = myCanvas.getContext("2d");
            ctx.translate(data.radius / 2, data.radius / 2);
            for (var i = 0; i < 10; i++) {
                ctx.beginPath();
                ctx.fillStyle = "#000000";
                ctx.font = "20px 行楷";
                for (var j = 0; j < 10; j++) {
                    ctx.fillText(data.awardList[i], data.radius / 2 * 0.6, 46);
                }
                ctx.fillStyle = randomColorList[i % 5];
                ctx.moveTo(0, 0);
                ctx.arc(0, 0, data.radius / 2, (0 * Math.PI) / 180, (36 * Math.PI) / 180);
                ctx.rotate((36 * Math.PI) / 180);
                ctx.fill();
                ctx.closePath();
            }
        }

        return {
            data,
            play,
        };
    },
};
script>

<style>
* {
    padding: 0;
    margin: 0;
}

/* 容器样式 */
.container {
    width: 80vw;
    height: 80vw;
    margin-left: 10vw;
    margin-top: 10vw;
    border-radius: 50%;
    animation: run-rotate 3s ease-in-out 1;
    animation-fill-mode: forwards;
}

/* 开启按钮样式 */
.play {
    display: block;
    width: 40vw;
    height: 10vw;
    line-height: 10vw;
    margin-left: 30vw;
    margin-top: 10vw;
    cursor: pointer;
    color: crimson;
    text-align: center;
    border: 1px solid crimson;
    font-size: 20px;
    border-radius: 4vw;
}
style>

img

参考这样改改看看行不行

<canvas ref="myCanvas" :width="data.radius" :height="data.radius" class="container run-rotate"></canvas>
function play() {
      // 移除 run-rotate class,以重置动画状态
      this.$refs.myCanvas.classList.remove("run-rotate");

      const randomDeg = 360 * 8 + parseInt(Math.random() * 360 * 2);
      document.styleSheets[0].insertRule(
        `@keyframes run-rotate {
          from {
            transform: rotateZ(0deg);
          }
          to {
            transform: rotateZ(${randomDeg}deg);
          }
        }`
      );

      // 使用 setTimeout 函数,延迟一段时间后再次添加 run-rotate class,以触发动画的重复播放
      setTimeout(() => {
        this.$refs.myCanvas.classList.add("run-rotate");
      }, 100);
    }

    onMounted(() => {
      const myCanvas = this.$refs.myCanvas;
      draw(myCanvas);
    });
.run-rotate {
  animation: run-rotate 3s ease-in-out 1;
  animation-fill-mode: forwards;
}