本地上传图片或视频获取预览图

多媒体上传预览


在我们上传图片或视频需要进行预览操作,即获取该图片或视频一帧的画面作为背景显示时


使用el-upload时的图片预览

// el-upload 设置 :on-change 事件 值为 onChange 函数

const onChange = (file) => {
	const reader = new FileReader();
    reader.readAsDataURL(file.raw);
    reader.onload = () => {
        Promise.resolve().then(() => {
            file.url = reader.result;
            // file.url 为预览图的url地址
        });
    };
}

// 获取到预览图的地址后 需要显示在 background 中的话需要设置计算属性(vue3)
// 如果使用原生css则不需要这样写,直接用v-bind in css拼接即可,由于使用的时scss,需要使用这种写法
const bgStyle = computed(() => ({
    border: 'none',
    backgroundImage: `url(${此处为获取到的预览图地址})`,
    backgroundSize: 'cover',
    backgroundPosition: 'center center',
}))

// 设置需要显示背景的元素 :style="bgStyle" 即可

图片预览并裁剪

// 通过input file 获取到file文件

// FileReader读取文件内容 生成base64
const reader = new FileReader();
reader.readAsDataURL(file);
reader.addEventListener('load', function () {

    // 将生成的base64给img获取图片属性
    const img = new Image();
    img.src = reader.result;
    img.addEventListener('load', function () {

        // 获取图片的宽高 
        const width = this.width;
        const height = this.height;

        // 此处由于需求原因需要裁剪,不需要可以删除 ----------------------------------------
        // 由于接口要求图片必须符合16:9 且宽能整除4  计算符合条件的矩形的高度
        let rectWidth = Math.floor(width / 4) * 4;
        let rectHeight = Math.floor(rectWidth * 9 / 16);

        if (rectHeight > height) {
            rectHeight = height; // 高度不超过矩形的高度
            rectWidth = Math.floor(rectHeight * 16 / 9);
            rectWidth = Math.floor(rectWidth / 4) * 4;
            rectHeight = Math.floor(rectWidth * 9 / 16); // 再次计算高度,确保宽高比为 16:9
        }
		// ---------------------------------------------------------------------------

        const canvas = document.createElement('canvas');
        canvas.width = rectWidth; // 替换为要截取的宽度  不需要裁剪时为 width 即可
        canvas.height = rectHeight; // 替换为要截取的高度 不需要裁剪时为 height 即可

        // 使用canvas截取符合比例的图片
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height, 0, 0, canvas.width, canvas.height);

        // 转化为二进制文件后分别转化为 图片文件 和 图片url地址
        canvas.toBlob(function (blob) {
            const newFile = new File([blob], file.name, {type: file.type});
            const imageUrl = URL.createObjectURL(blob);
		
            // 输出图片文件和图片 URL
            // newFile为处理后的图片(裁剪后),imageUrl为预览图url路径
        });
    });
});

视频预览

// 上传文件为视频

// 通过input file 获取到file文件

const url = window.URL.createObjectURL(file);
 const video = document.createElement("video");
 video.src = url;
 // video.style.display = "none";

 /*
  * 当上传的视频较大时 video 的 loadedmetadata 事件并不能获取到视频的对应帧的画面
  * 因为此时视频还未加载完, 所以需要使用canplaythrough事件
  * 由于 video 的 canplaythrough 事件触发频率过快且一直执行
  * 设置 canGeneratePreview 当生成可用的图片后清除监听
  * 为防止图片生成错误导致事件无法停止 设置5s后自动清除监听
  */
 let canGeneratePreview = false

 setTimeout(() => {
     canGeneratePreview = true
 }, 5000)

 const canplayHandler = () => {
     if (canGeneratePreview) video.removeEventListener("canplaythrough", canplayHandler)

     const canvas = document.createElement('canvas');
     const width = video.videoWidth;
     const height = video.videoHeight;
     canvas.width = width;
     canvas.height = height;

     // 设置截取画面为第10帧
     video.currentTime = 10
     const context = canvas.getContext('2d');
     context.drawImage(video, 0, 0, canvas.width, canvas.height);

     // 生成的视频预览图截图 当截取不到画面时其base64长度约为3000左右 这里将阈值设置为20000
     const previewUrl = canvas.toDataURL('image/jpeg');
     if (previewUrl.length > 20000) canGeneratePreview = true

     // previewUrl为预览图url路径
 }

 video.addEventListener('canplaythrough', canplayHandler);

你可能感兴趣的:(else,音视频,javascript,前端,html)