|
一、上传到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"><</div>
- <div class="arrow arrow-right" @click="nextImage" :disabled="currentIndex === images.length - 1">></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>
复制代码 效果:
总结
到此这篇关于前端实现图片或视频预览的三种方法的文章就介绍到这了,更多相关前端图片或视频预览内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
来源:https://www.jb51.net/javascript/323380w1s.htm
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|