index.vue 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <template>
  2. <div :class="[ui,isDom?'cu-img-preview-dom':'']" class="cu-img-preview">
  3. <div class="cu-img-preview-box">
  4. <div :style="{transform:'scale('+ scale +')'}" class="cu-img-preview-scale">
  5. <NodeImg :src="imgUrl" :style="{transform:'rotate('+ rotate +'deg)'}" height="auto" ui="ui-img-auto-box"/>
  6. </div>
  7. </div>
  8. <div v-if="srcs.length > 0" :class="isThumb?'show':''" class="cu-img-thumb-box">
  9. <div v-for="(item,id) in srcs" :class="id === index?'cur':''" class="cu-img-thumb-item" @click="tapThumbClick(id,item)">
  10. <NodeImg :src="item" height="80px"/>
  11. </div>
  12. </div>
  13. <div class="cu-img-preview-tools-box" :class="toolsSm?'cu-img-preview-tools-sm':''">
  14. <div class="preview-tools-box">
  15. <div class="preview-tools-flex">
  16. <div v-if="srcs.length > 0" :class="isThumb?'cur':''" class="preview-tools-item" @click="thumbClick">
  17. thumb
  18. </div>
  19. <div class="preview-tools-item" @click="leftRotationClick">
  20. <HcIcon name="anticlockwise"/>
  21. </div>
  22. <div class="preview-tools-item" @click="rightRotationClick">
  23. <HcIcon name="clockwise"/>
  24. </div>
  25. <div class="preview-tools-item" @click="enlargeClick">
  26. <HcIcon name="zoom-in"/>
  27. </div>
  28. <div class="preview-tools-item" @click="shrinkClick">
  29. <HcIcon name="zoom-out"/>
  30. </div>
  31. <div class="preview-tools-item" @click="scaleClick">
  32. <HcIcon name="merge-cells-horizontal" :line="false"/>
  33. </div>
  34. <div v-if="srcs.length > 0" class="preview-tools-item" @click="topClick">
  35. back
  36. </div>
  37. <div v-if="srcs.length > 0" class="preview-tools-item" @click="nextClick">
  38. arrow
  39. </div>
  40. <div v-if="enlarge" class="preview-tools-item">
  41. enlarge
  42. </div>
  43. <div v-for="item in tools" class="preview-tools-item" @click="toolsClick(item)">
  44. <HcIcon :name="item.icon"/>
  45. </div>
  46. <div class="preview-tools-item" v-if="!isDom" @click="closeClick">
  47. <HcIcon name="close"/>
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. </div>
  53. </template>
  54. <script setup>
  55. import {ref,watch} from "vue";
  56. import NodeImg from "./NodeImg.vue"
  57. const props = defineProps({
  58. ui: {
  59. type: String,
  60. default: ''
  61. },
  62. //单图片
  63. src: {
  64. type: String,
  65. default: ''
  66. },
  67. //图片数组
  68. srcs: {
  69. type: Array,
  70. default: () => ([])
  71. },
  72. //选中索引
  73. cur: {
  74. type: Number,
  75. default: -1
  76. },
  77. //是否全屏
  78. enlarge: {
  79. type: Boolean,
  80. default: false
  81. },
  82. //扩展工具栏
  83. tools: {
  84. type: Array,
  85. default: () => ([])
  86. },
  87. //小工具栏
  88. toolsSm: {
  89. type: Boolean,
  90. default: false
  91. },
  92. //挂载在某个dom上
  93. isDom: {
  94. type: Boolean,
  95. default: false
  96. },
  97. })
  98. //变量
  99. const scale = ref(1);
  100. const rotate = ref(0);
  101. const isThumb = ref(false);
  102. const imgUrl = ref(props.src||'');
  103. const index = ref(parseInt(props.cur) || -1);
  104. //监听
  105. watch(() => [
  106. props.src,
  107. props.cur,
  108. ], ([src,cur]) => {
  109. imgUrl.value = src
  110. index.value = parseInt(cur) || -1
  111. })
  112. //事件
  113. const emit = defineEmits(['curImg', 'thumb', 'tapThumb', 'tapRotation', 'tapZoom', 'tapScale', 'tapTools', 'close', 'vmClose']);
  114. const curIndex = props.srcs?.length - 1;
  115. //处理默认选择图片
  116. if (props.src && props.srcs?.length <= 0) {
  117. imgUrl.value = props.src
  118. index.value = -1;
  119. } else if (props.srcs?.length > 0) {
  120. if (curIndex >= index.value && index.value >= 0) {
  121. imgUrl.value = props.srcs?.[index.value];
  122. } else {
  123. imgUrl.value = props.srcs?.[0];
  124. index.value = 0;
  125. }
  126. }
  127. //上一张
  128. function topClick() {
  129. if (index.value === 0) {
  130. index.value = curIndex;
  131. } else {
  132. index.value--;
  133. }
  134. setCurImageUrl();
  135. }
  136. //下一张
  137. function nextClick() {
  138. if (index.value === curIndex) {
  139. index.value = 0;
  140. } else {
  141. index.value++;
  142. }
  143. setCurImageUrl();
  144. }
  145. //从缩略图里选择图片
  146. function tapThumbClick(id, item) {
  147. index.value = id;
  148. imgUrl.value = item;
  149. emit('thumb', {cur: id, img: item})
  150. }
  151. //设置选中的图片
  152. function setCurImageUrl() {
  153. imgUrl.value = props.srcs?.[index.value];
  154. emit('curImg', {cur: index.value, img: imgUrl.value})
  155. }
  156. //缩略图
  157. function thumbClick() {
  158. isThumb.value = !isThumb.value;
  159. emit('tapThumb', isThumb.value)
  160. }
  161. //逆时针旋转
  162. function leftRotationClick() {
  163. if (rotate.value === 0) {
  164. rotate.value = 270
  165. } else if (rotate.value === 270) {
  166. rotate.value = 180
  167. } else if (rotate.value === 180) {
  168. rotate.value = 90
  169. } else if (rotate.value === 90) {
  170. rotate.value = 0
  171. }
  172. emit('tapRotation', rotate.value)
  173. }
  174. //顺时针旋转
  175. function rightRotationClick() {
  176. if (rotate.value === 0) {
  177. rotate.value = 90
  178. } else if (rotate.value === 90) {
  179. rotate.value = 180
  180. } else if (rotate.value === 180) {
  181. rotate.value = 270
  182. } else if (rotate.value === 270) {
  183. rotate.value = 0
  184. }
  185. emit('tapRotation', rotate.value)
  186. }
  187. //放大
  188. function enlargeClick() {
  189. if (scale.value <= 6) {
  190. scale.value += 0.1
  191. }
  192. emit('tapZoom', scale.value)
  193. }
  194. //缩小
  195. function shrinkClick() {
  196. if (scale.value >= 0.11) {
  197. scale.value -= 0.1
  198. }
  199. emit('tapZoom', scale.value)
  200. }
  201. //还原尺寸
  202. function scaleClick() {
  203. scale.value = 1;
  204. rotate.value = 0;
  205. emit('tapScale')
  206. }
  207. //扩展栏被点击
  208. function toolsClick(item) {
  209. emit('tapTools', item)
  210. }
  211. //close
  212. function closeClick() {
  213. emit('close')
  214. emit('vmClose')
  215. }
  216. </script>
  217. <style lang="scss" scoped>
  218. @import './style.scss';
  219. </style>