previewImageDirective.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. import { h, render } from 'vue';
  2. import { ElImageViewer } from 'element-plus';
  3. import { downloadImgVideo } from '@/utils'
  4. export default function (app) {
  5. app.directive('previewImage', {
  6. mounted(el, binding) {
  7. const previewBox = document.createElement('div');
  8. previewBox.classList.add('preview-box');
  9. let vnode;
  10. let downloadIndex
  11. // 判断是否为视频文件
  12. const isVideo = (url) => /\.(mp4|webm|ogg)$/i.test(url);
  13. // 创建混合媒体预览组件
  14. const createMixedMediaViewer = (urls, initialIndex = 0) => {
  15. const mediaList = urls.map(url => ({
  16. url,
  17. isVideo: isVideo(url)
  18. }));
  19. const _el = h(ElImageViewer, {
  20. urlList: urls,
  21. initialIndex,
  22. hideOnClickModal: true,
  23. onClose: () => {
  24. render(null, previewBox);
  25. document.body.removeChild(previewBox);
  26. },
  27. onSwitch: (index) => {
  28. downloadIndex = index
  29. const elAll = document.querySelectorAll('.el-image-viewer__img');
  30. const el = elAll[index];
  31. if (!isVideo(el.src) || el.tagName !== 'VIDEO') { // 当前是 IMG
  32. elAll.forEach((item, i) => {
  33. if (item.tagName === 'VIDEO') {
  34. item.style.display = 'none'
  35. }
  36. })
  37. } else {
  38. el.style.display = 'block'
  39. }
  40. if (isVideo(el.src) && el.tagName === 'IMG') {
  41. const currentMedia = mediaList[index];
  42. const canvasElement = document.querySelector('.el-image-viewer__canvas');
  43. // 如果是视频,替换img标签为video标签
  44. setTimeout(() => {
  45. if (canvasElement) {
  46. const videoElement = document.createElement('video');
  47. videoElement.src = currentMedia.url;
  48. videoElement.controls = true;
  49. videoElement.autoplay = true;
  50. videoElement.className = el.className;
  51. videoElement.style.maxWidth = '100%';
  52. videoElement.style.maxHeight = '100%';
  53. canvasElement.appendChild(videoElement);
  54. el.remove()
  55. }
  56. }, 0);
  57. }
  58. }
  59. });
  60. return _el
  61. };
  62. el.addEventListener('click', () => {
  63. el.style.cursor = 'pointer';
  64. const urls = Array.isArray(binding.value[0]) ? binding.value[0] : [binding.value[0]];
  65. const initialIndex = binding.value[1] || 0;
  66. downloadIndex = initialIndex
  67. vnode = createMixedMediaViewer(urls, initialIndex);
  68. render(vnode, previewBox);
  69. document.body.appendChild(previewBox);
  70. // 添加下载按钮
  71. const action_btn = previewBox.children[0].children[4].children[0]
  72. const divider = document.createElement('i')
  73. divider.className = 'el-image-viewer__actions__divider'
  74. action_btn.appendChild(divider)
  75. const download_btn = document.createElement('i')
  76. download_btn.className = 'el-icon'
  77. download_btn.innerHTML = `<svg data-v-d2e47025="" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024">
  78. <path fill="currentColor" d="M160 832h704a32 32 0 1 1 0 64H160a32 32 0 1 1 0-64m384-253.696 236.288-236.352 45.248 45.248L508.8 704 192 387.2l45.248-45.248L480 584.704V128h64z"></path>
  79. </svg>`
  80. const date = new Date()
  81. download_btn.addEventListener('click', () => {
  82. const fileName = binding.value[2] || `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
  83. downloadImgVideo(urls[downloadIndex], fileName)
  84. })
  85. action_btn.appendChild(download_btn)
  86. });
  87. },
  88. unmounted(el) {
  89. el.removeEventListener('click', () => {});
  90. }
  91. });
  92. }