当前位置: 代码网 > it编程>编程语言>Javascript > 前端实现图片或视频预览的三种方法总结

前端实现图片或视频预览的三种方法总结

2024年07月03日 Javascript 我要评论
一、上传到oss或者服务器缺点:1.大文件上传时间过长2.如果用户只是预览则会浪费服务端存储二、使用filereader对象转换file对象为base64<input type="file" i

一、上传到oss或者服务器

缺点:

1.大文件上传时间过长

2.如果用户只是预览则会浪费服务端存储

二、使用filereader对象转换file对象为base64

<input type="file" id="videoinput">
<video src="" alt="预览" id="video" controls="controls">
<script>
  const videoinput = document.getelementbyid('videoinput');
  videoinput.addeventlistener('change', e => {
    previewbyreader(e.target.files[0])
  })

function filetobase64(file: file): promise<{ url: any, filename: string }> {
  const filereader = new filereader()
  filereader.readasdataurl(file)
  var filename = file.name;
  return new promise((resolve, reject) => {
    filereader.addeventlistener("loadend", (e: progressevent<filereader>) => {
      var url: any = e.target!.result;
      resolve({ url, filename })
    }, false);
  })
}
  async function previewbyreader (file) {
   const {url} = await filetobase64(file)
   video.src = url
  }
</script>

三、通过blob协议实现预览

<input type="file" id="videoinput">
  <video src="" alt="预览" id="video" controls="controls" width="400" height="200">
  <script>
    const videoinput = document.getelementbyid('videoinput');
    videoinput.addeventlistener('change', e => {
      previewbyurl(e.target.files[0])
    })
    function previewbyurl (file) {
      video.src = url.createobjecturl(file)
    }
  </script>

附:前端自定义封装图片预览组件(支持多张图片预览 缩放)

封装图片预览组件:

<template>
    <div ref="previewwrapper" class="image-preview">
      <div class="overlay" v-if="showoverlay" @click="closepreview"></div>
      <div class="preview-container" v-wheelscale>
        <img :src="currentimageurl" alt="preview image" @load="imageloaded" ref="previewimage">
      </div>
      <div class="arrow arrow-left" @click="previmage" :disabled="currentindex === 0">&lt;</div>
      <div class="arrow arrow-right" @click="nextimage" :disabled="currentindex === images.length - 1">&gt;</div>
    </div>
  </template>
  
  <script>
  export default {
    props: {
      images: {
        type: array,
        required: true,
      },
    },
    data() {
      return {
        showoverlay: false,
        currentindex: 0,
        currentimageurl: '',
        scale: 1,
        initialmousex: 0,
        initialscale: 1,
        isdragging: false,
      };
    },
    methods: {
      openpreview() {
        this.showoverlay = true;
        this.currentimageurl = this.images[this.currentindex];
        this.$refs.previewwrapper.style.display = 'flex';
        settimeout(() => {
          this.$refs.previewwrapper.style.opacity = 1;
        }, 10);
      },
      closepreview() {
        this.showoverlay = false;
        settimeout(() => {
          this.$refs.previewwrapper.style.opacity = 0;
          settimeout(() => {
            this.$refs.previewwrapper.style.display = 'none';
          }, 0);
        }, 0);
      },
      nextimage() {
        this.currentindex = (this.currentindex + 1) % this.images.length;
        this.currentimageurl = this.images[this.currentindex];
      },
      previmage() {
        this.currentindex = (this.currentindex - 1 + this.images.length) % this.images.length;
        this.currentimageurl = this.images[this.currentindex];
      },
      imageloaded() {
        // 可以在此处调整图片的居中或其它布局逻辑
      },
    },
    mounted() {
      // 初始化时隐藏预览层
      this.$refs.previewwrapper.style.display = 'none';
    },
  };
  </script>
  
  <style scoped>
  .image-preview {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 999;
    display: none;
    justify-content: center;
    align-items: center;
    opacity: 0;
    transition: opacity 0.7s ease-in-out;
  }
  
  .overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8);
    cursor: pointer;
  }
  
  .preview-container {
    position: relative;
    text-align: center;
    overflow: hidden;
    max-width: 90%;
    max-height: 90vh;
  }
  
  .arrow {
    width: 50px;
    height: 50px;
    position: absolute;
    top: 50%;
    transform: translatey(-50%);
    background: rgba(255, 255, 255, 0.8);
    padding: 10px;
    border-radius: 50%;
    cursor: pointer;
    z-index: 1;
    opacity: 0.5;
    transition: opacity 0.3s;
    border: none;
    font-size: 20px;
    line-height: 50px;
  }
  
  .arrow:hover {
    opacity: 1;
  }
  
  .arrow-left {
    left: 10px;
  }
  
  .arrow-right {
    right: 10px;
  }
  </style>

图片放大缩小依靠自定义指令实现:

自定义指定代码:src/utils/scale.js

export const initvwheelscale = (vue) => {
    vue.directive("wheelscale", (el, binding) => {
      const {
        maxscale = 5,
        minscale = 0.5,
        initscale = 1,
        cssvarname = "--scale",
      } = binding.arg || {}
      let currentscale = initscale || el.style.getpropertyvalue(cssvarname) || 1
      setwheelscale(binding, {
        el,
        cssvarname,
        currentscale,
        minscale,
        maxscale,
      })
      if (el) {
        el.onwheel = (e) => {
          currentscale = el.style.getpropertyvalue(cssvarname) || 1
   
          if (e.wheeldelta > 0) {
            currentscale = currentscale * 1 + 0.1
          } else {
            currentscale = currentscale * 1 - 0.1
          }
          setwheelscale(binding, {
            el,
            cssvarname,
            currentscale,
            minscale,
            maxscale,
          })
        }
      }
    })
  }
  // 设置 --scale 变量 缩放比例
  const setvarscale = (el, cssvarname, currentscale, minscale, maxscale) => {
    // 现在缩放范围
    if (currentscale > maxscale) {
      currentscale = maxscale
    } else if (currentscale < minscale) {
      currentscale = minscale
    }
    let csstext = el.style.csstext
    let csstextlist = csstext.split(";")
    let isexist = false
    let isexistindex = -1
    for (let index = 0; index < csstextlist.length; index++) {
      const element = csstextlist[index]
      if (element.includes(cssvarname + ":")) {
        isexist = true
        isexistindex = index
        break
      }
    }
    if (isexist) {
      csstextlist[isexistindex] = `--scale: ${currentscale}`
    } else {
      csstextlist.push(`--scale: ${currentscale}`)
      //   el.setattribute("style", `--scale: ${currentscale}`)
    }
    csstext = csstextlist.join(";")
    el.style.csstext = csstext
    return currentscale
  }
  // 设置 style.transform
  const settransformcss = (el, cssvarname) => {
    let transformcssstring = el.style.transform
    let regscaleglobal = /scale\(.*?[ )]*[)]+[ ]*/g //匹配 scale属性 全局
    if (regscaleglobal.test(transformcssstring)) {
      transformcssstring = transformcssstring.replace(
        regscaleglobal,
        ` scale(var(${cssvarname})) `
      )
    } else {
      transformcssstring += " " + `scale(var(${cssvarname}))`
    }
    el.style.transform = transformcssstring
  }
  export const setwheelscale = (binding = {}, options) => {
    const { el, cssvarname, currentscale, minscale, maxscale } = options
    const nowscale = setvarscale(el, cssvarname, currentscale, minscale, maxscale)
    settransformcss(el, cssvarname)
    // 缩放改变回调函数
    const wheelscalehandle = binding.value || null
    if (wheelscalehandle instanceof function) {
      wheelscalehandle({
        el,
        cssvarname,
        maxscale,
        minscale,
        currentscale: nowscale,
        setscale: (_scale) => {
          setwheelscale(binding, { ...options, currentscale: _scale })
        },
        binding,
      })
    }
  }
   

main.js中全局注册自定义指令:

import { initvwheelscale} from "@/utils/scale.js"
initvwheelscale(vue)

在图片预览组件中使用:

组件的使用:

<template>
  <div>
    <!-- ...其他内容 -->
    <button @click="openpreview">预览图片</button>
    <image-preview :images="imagelist" ref="imagepreview"></image-preview>
  </div>
</template>

<script>
import imagepreview from '@/components/imagepreview.vue'; // 引入你的图片预览组件

export default {
  components: {
    imagepreview,
  },
  data() {
    return {
      imagelist: [
        'https://img1.baidu.com/it/u=582697934,2565184993&fm=253&fmt=auto&app=120&f=jpeg?w=500&h=539',
        'https://img2.baidu.com/it/u=3519181745,2349627299&fm=253&fmt=auto&app=120&f=jpeg?w=750&h=500',
        // 更多图片路径
      ],
    };
  },
  methods: {
    openpreview() {
      this.$refs.imagepreview.openpreview();
    },
  },
};
</script>

效果:

总结 

到此这篇关于前端实现图片或视频预览的三种方法的文章就介绍到这了,更多相关前端图片或视频预览内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com