Image.vue 3.5 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, watch} from '@nuxtjs/composition-api'
  42. import {UseImage} from "~/composables/data/useImage";
  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 useImg = new UseImage()
  82. const { imageLoaded, fetch } = useImg.getOne(props.id, props.imageByDefault, props.height, props.width)
  83. const unwatch: WatchStopHandle = watch(() => props.id, async (newValue, oldValue) => {
  84. imgSrcReload.value = await useImg.provideImg(newValue as number, props.height, props.width)
  85. })
  86. /**
  87. * Quand on souhaite faire un reset de l'image
  88. */
  89. const reset = () => {
  90. imgSrcReload.value = null
  91. imageLoaded.value = require(`assets/images/byDefault/${props.imageByDefault}`)
  92. openUpload.value = false
  93. }
  94. /**
  95. * Lorsqu'on démonte le component on supprime le watcher
  96. */
  97. onUnmounted(() => {
  98. unwatch()
  99. })
  100. return {
  101. imgSrcReload,
  102. imageLoaded,
  103. openUpload,
  104. fetch,
  105. reset
  106. }
  107. }
  108. })
  109. </script>
  110. <style lang="scss">
  111. div.image-wrapper {
  112. display: block;
  113. position: relative;
  114. img{
  115. max-width: 100%;
  116. }
  117. .click-action{
  118. position: absolute;
  119. top:0;
  120. left:0;
  121. width: 100%;
  122. height: 100%;
  123. background: transparent;
  124. opacity: 0;
  125. transition: all .2s;
  126. &:hover{
  127. opacity: 1;
  128. background:rgba(0,0,0,0.3);
  129. cursor: pointer;
  130. }
  131. i{
  132. color: #fff;
  133. position: absolute;
  134. top: 50%;
  135. left: 50%;
  136. transform: translate(-50% , -50%);
  137. font-size: 50px;
  138. z-index: 1;
  139. opacity: 1;
  140. &:hover{
  141. color: rgba(#3fb37f, 0.7);
  142. }
  143. }
  144. }
  145. }
  146. </style>