index.vue 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <template>
  2. <div
  3. :style="{
  4. visibility: show ? 'visible' : 'hidden',
  5. }"
  6. class="subtitle"
  7. ref="dom"
  8. >
  9. <div :style="{ background: data.background }" v-html="data.content" />
  10. </div>
  11. </template>
  12. <script lang="ts" setup>
  13. import { AnimationModelSubtitle } from "@/api";
  14. import { Pos, Size } from "../drawing/dec";
  15. import { ref, watch, watchEffect } from "vue";
  16. const props = defineProps<{
  17. data: AnimationModelSubtitle;
  18. pixel: Pos;
  19. show: boolean;
  20. sizeChang: (csize: Size) => void;
  21. }>();
  22. // watchEffect(() => {
  23. // if (!dom.value) return;
  24. // dom.value.style.transform = `translate(${props.pixel.x}px, ${props.pixel.y}px)`;
  25. // });
  26. const dom = ref<HTMLDivElement>();
  27. watch(
  28. () => props.data.content,
  29. () => {
  30. watch(
  31. dom,
  32. (dom, _, onCleanup) => {
  33. if (!dom) return;
  34. const timeout = setTimeout(() => {
  35. props.sizeChang({ width: dom.offsetWidth, height: dom.offsetHeight });
  36. });
  37. onCleanup(() => clearTimeout(timeout));
  38. },
  39. { immediate: true }
  40. );
  41. }
  42. );
  43. </script>
  44. <style lang="scss" scoped>
  45. .subtitle {
  46. position: absolute;
  47. z-index: 1;
  48. transition: transform 0.3s linear;
  49. will-change: transform;
  50. left: 0;
  51. top: 0;
  52. text-shadow: 0px 2px 4px rgba(0, 0, 0, 0.25);
  53. pointer-events: none;
  54. > div {
  55. max-width: 280px;
  56. border-radius: 4px;
  57. font-size: 14px;
  58. padding: 10px 20px;
  59. color: #ffffff;
  60. line-height: 16px;
  61. word-break: break-all;
  62. }
  63. }
  64. </style>