LongImageSerialFrames.vue 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. <template>
  2. <div
  3. class="single-long-image-serial-frames"
  4. :style="{
  5. width: frameWidth + 'px',
  6. height: props.height + 'px',
  7. }"
  8. >
  9. <img
  10. class="long-image"
  11. :style="{
  12. left: `calc(-${frameWidth}px * ${frameIdx})`,
  13. }"
  14. :src="props.imageSrc"
  15. alt=""
  16. draggable="false"
  17. @dragstart.prevent
  18. >
  19. </div>
  20. </template>
  21. <script setup>
  22. import { ref, onMounted, onBeforeUnmount } from 'vue'
  23. const props = defineProps({
  24. imageSrc: {
  25. type: String,
  26. required: true,
  27. },
  28. totalWidth: {
  29. type: Number,
  30. required: true,
  31. },
  32. height: {
  33. type: Number,
  34. required: true,
  35. },
  36. frameNumber: {
  37. type: Number,
  38. required: true,
  39. },
  40. frameDuration: {
  41. type: Number,
  42. default: 41
  43. },
  44. })
  45. const frameWidth = ref(props.totalWidth / props.frameNumber)
  46. console.assert(Number.isInteger(frameWidth.value), `序列帧的每帧宽度不是整数,可能导致播放时抖动!总宽度:${props.totalWidth},帧数:${props.frameNumber},每帧宽度:${frameWidth.value}`)
  47. const frameIdx = ref(0)
  48. let intervalId = null
  49. onMounted(() => {
  50. intervalId = setInterval(() => {
  51. frameIdx.value++
  52. if (frameIdx.value === props.frameNumber) {
  53. frameIdx.value = 0
  54. }
  55. }, props.frameDuration)
  56. })
  57. onBeforeUnmount(() => {
  58. clearInterval(intervalId)
  59. })
  60. </script>
  61. <style lang="less" scoped>
  62. .single-long-image-serial-frames {
  63. position: absolute;
  64. overflow: hidden;
  65. pointer-events: none;
  66. > .long-image {
  67. position: absolute;
  68. height: 100%;
  69. }
  70. }
  71. </style>