Image.vue 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. <template>
  2. <div
  3. class="relative"
  4. :style="containerStyles"
  5. :class="roundedClass"
  6. >
  7. <NuxtImg
  8. v-if="cachedSrc"
  9. :src="cachedSrc"
  10. :alt="errorMessage"
  11. class="absolute z-10 top-0 left-0 w-full h-full object-cover object-center show"
  12. :class="roundedClass"
  13. :custom="true"
  14. v-slot="{ src, isLoaded, imgAttrs }"
  15. >
  16. <img v-if="isLoaded" v-bind="imgAttrs" :src="src" />
  17. <div v-else class="w-full h-full loading" />
  18. </NuxtImg>
  19. <div
  20. class="loading"
  21. :class="roundedClass"
  22. :style="containerStyles"
  23. />
  24. </div>
  25. </template>
  26. <script setup lang="ts">
  27. interface ImageProps {
  28. src: string;
  29. height?: number;
  30. minHeight?: number;
  31. maxHeight?: number;
  32. width?: number;
  33. minWidth?: number;
  34. rounded?: string;
  35. }
  36. const props = defineProps<ImageProps>();
  37. const errorMessage = 'Возникла проблема с загрузкой фото, попробуйте позже.';
  38. const containerStyles = computed(() => {
  39. const styles = [];
  40. if (props.height) {
  41. styles.push(`height: ${props.height}px;`);
  42. } else if (props.minHeight) {
  43. styles.push(`min-height: ${props.minHeight}px`);
  44. }
  45. if (props.maxHeight) {
  46. styles.push(`max-height: ${props.maxHeight}px`);
  47. }
  48. if (props.width) {
  49. styles.push(`width: ${props.width}px;`);
  50. } else if (props.minWidth) {
  51. styles.push(`min-width: ${props.minWidth}px`);
  52. }
  53. return styles;
  54. });
  55. const roundedClass = computed(() =>
  56. props.rounded ? `rounded-${props.rounded}` : ''
  57. );
  58. const { $getCachedUrl } = useNuxtApp();
  59. const log = useLogger('imageComponent')
  60. const cachedSrc = ref<string | null>(null);
  61. onMounted(async () => {
  62. try {
  63. cachedSrc.value = await $getCachedUrl(props.src);
  64. } catch (error) {
  65. log.error('Не удалить загрузить картинку: ', error);
  66. }
  67. });
  68. </script>
  69. <style scoped>
  70. .loading {
  71. background-color: #f3f4f656;
  72. animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
  73. }
  74. @keyframes pulse {
  75. 0%, 100% {
  76. opacity: 1;
  77. }
  78. 50% {
  79. opacity: .5;
  80. }
  81. }
  82. </style>