Image.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. <template>
  2. <main>
  3. <div class="image-wrapper" :style="{width:width + 'px'}">
  4. <v-img
  5. :src="imgSrcReload ? imgSrcReload : imageLoaded"
  6. :lazy-src="require(`/assets/images/byDefault/${imageByDefault}`)"
  7. :height="height"
  8. :width="width"
  9. aspect-ratio="1"
  10. >
  11. <template #placeholder>
  12. <v-row
  13. class="fill-height ma-0"
  14. align="center"
  15. justify="center"
  16. >
  17. <v-progress-circular
  18. indeterminate
  19. color="grey lighten-1"
  20. ></v-progress-circular>
  21. </v-row>
  22. </template>
  23. </v-img>
  24. <div>
  25. <div v-if="upload" class="click-action hover" @click="openUpload=true"><v-icon>mdi-upload</v-icon></div>
  26. <UiInputImage
  27. v-if="openUpload"
  28. @close="openUpload=false"
  29. :existingImageId="id"
  30. :field="field"
  31. :ownerId="ownerId"
  32. @update="$emit('update', $event, field); openUpload=false"
  33. @reload="fetch();openUpload=false"
  34. @reset="reset"
  35. ></UiInputImage>
  36. </div>
  37. </div>
  38. </main>
  39. </template>
  40. <script lang="ts">
  41. import {defineComponent, onUnmounted, ref, Ref, useContext, watch} from '@nuxtjs/composition-api'
  42. import {useImageProvider} from "~/composables/data/useImageProvider";
  43. import {WatchStopHandle} from "@vue/composition-api";
  44. export default defineComponent({
  45. props: {
  46. id: {
  47. type: Number,
  48. required: false
  49. },
  50. field: {
  51. type: String,
  52. required: false
  53. },
  54. imageByDefault: {
  55. type: String,
  56. required: false,
  57. default: 'default_pic.jpeg'
  58. },
  59. height: {
  60. type: Number,
  61. required: false
  62. },
  63. width: {
  64. type: Number,
  65. required: false
  66. },
  67. upload: {
  68. type: Boolean,
  69. required: false,
  70. default: false
  71. },
  72. ownerId:{
  73. type: Number,
  74. required: false
  75. }
  76. },
  77. fetchOnServer: false,
  78. setup(props) {
  79. const openUpload: Ref<Boolean> = ref(false)
  80. const imgSrcReload: Ref<any> = ref(null)
  81. const {$dataProvider, $config} = useContext()
  82. const {getOne, provideImg} = useImageProvider($dataProvider, $config)
  83. const { imageLoaded, fetch } = getOne(props.id, props.imageByDefault, props.height, props.width)
  84. const unwatch: WatchStopHandle = watch(() => props.id, async (newValue, oldValue) => {
  85. imgSrcReload.value = await provideImg(newValue as number, props.height, props.width)
  86. })
  87. /**
  88. * Quand on souhaite faire un reset de l'image
  89. */
  90. const reset = () => {
  91. imgSrcReload.value = null
  92. imageLoaded.value = require(`assets/images/byDefault/${props.imageByDefault}`)
  93. openUpload.value = false
  94. }
  95. /**
  96. * Lorsqu'on démonte le component on supprime le watcher
  97. */
  98. onUnmounted(() => {
  99. unwatch()
  100. })
  101. return {
  102. imgSrcReload,
  103. imageLoaded,
  104. openUpload,
  105. fetch,
  106. reset
  107. }
  108. }
  109. })
  110. </script>
  111. <style lang="scss">
  112. div.image-wrapper {
  113. display: block;
  114. position: relative;
  115. img{
  116. max-width: 100%;
  117. }
  118. .click-action{
  119. position: absolute;
  120. top:0;
  121. left:0;
  122. width: 100%;
  123. height: 100%;
  124. background: transparent;
  125. opacity: 0;
  126. transition: all .2s;
  127. &:hover{
  128. opacity: 1;
  129. background:rgba(0,0,0,0.3);
  130. cursor: pointer;
  131. }
  132. i{
  133. color: #fff;
  134. position: absolute;
  135. top: 50%;
  136. left: 50%;
  137. transform: translate(-50% , -50%);
  138. font-size: 50px;
  139. z-index: 1;
  140. opacity: 1;
  141. &:hover{
  142. color: rgba(#3fb37f, 0.7);
  143. }
  144. }
  145. }
  146. }
  147. </style>