vue实现鼠标滑动预览视频封面组件示例详解

目录
  • 组件效果
  • 组件设计
    • 1、视频截取关键帧
    • 2、鼠标移入封面时显示对应关键帧
    • 3、视频和封面的状态切换
  • 功能实现
    • 1、视频截取关键帧图片列表
      • 1.1 截取指定帧
      • 1.2 截取stepNums张关键帧图片
    • 2、鼠标移入封面时显示对应关键帧
      • 2.1 鼠标移动事件监听
      • 2.2 鼠标移出事件监听
    • 3、视频和封面的状态切换
      • 3.1 播放视频
      • 3.2 视频暂停
  • 组件使用
  • 组件库引用

组件效果

https://www.jb51.net/Special/926.htm

组件设计

我们首先应该要对组件进行一个简单的设计。

主要的逻辑如上图️️️,可以拆分成这么几个步骤:

1、视频截取关键帧

我们可以先将视频各个时间的关键帧截图保存,具体截取帧数可以使用传入参数控制。

2、鼠标移入封面时显示对应关键帧

在鼠标移入的时候我们应该要计算当前鼠标位置和视频宽度的比例关系,然后从视频帧列表中获取到对应的图片作为当前的视频封面图片。

3、视频和封面的状态切换

这里我们是将用两个元素分别作为视频和封面,所以我们状态切换的时候需要控制两个元素的显示和隐藏。

  • 点击封面

显示并播放视频,隐藏封面。

  • 暂停播放

显示封面,隐藏视频。

功能实现

分析完组件的关键步骤之后我们便可以开始动手来实现相应的功能了。

1、视频截取关键帧图片列表

1.1 截取指定帧

视频关键帧的截取我们可以使用canvas来实现,具体实现方法如下:

/**
 * @param {element} video
 * @param {number} currentTime
 * @return {void}
 */
cutCover(video, currentTime) {
    video.currentTime = currentTime;
    const canvas = document.createElement("canvas");
    let ctx = canvas.getContext("2d");
    canvas.width = parseInt(this.width);
    canvas.height = parseInt(this.height);
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
    const img = canvas.toDataURL("image/png");
    return img;
},

通过该函数我们可以获取指定时间的视频图片帧。

  • 传入参数
/**
 * @param {element} video
 * @param {number} currentTime
 */

video为需要截取视频的dom元素,currentTime为要截取图片帧的时间点。

  • 返回参数
/**
 * @return {Base64} img
 */

返回参数为截取的指定帧的Base64格式的图片。

1.2 截取stepNums张关键帧图片

stepNums为我们传入的组件参数,及需要截取的封面关键帧图片数量,数量越多,预览的效果越连贯,可以根据视频长度来调整截取的张数。

init(){
    const videoContentShow = document.getElementById(
        this.uid + "-video"
    );
    videoContentShow.style.height = this.height;
    videoContentShow.style.width = this.width;
    const videoContent = videoContentShow.cloneNode();
    videoContent.addEventListener("canplay", () => {
        if (this.currentTime < this.duration) this.cut(videoContent);
        else this.progressValue = 0;
    });
}
cut(video) {
    const duration = video.duration;
    this.duration = duration;
    this.currentTime += duration / this.stepNums;
    const img = this.cutCover(video, this.currentTime);
    this.imgList.push(img);
    if (this.imgList.length == 2) {
        this.coverSrc = img;
        const coverImg = document.getElementById(
            this.uid + "-coverImg"
        );
        coverImg.setAttribute("src", img);
    }
}

具体代码如上,首先我们应该先要获取到视频的dom元素,但是要注意:我们不在原始视频元素上进行截取操作,我们这里使用了cloneNode()来克隆一个dom元素进行操作。因为在进行截取的时候我们需要对视频的currentTime属性进行一个修改,也就是改变视频的播放进度,如果在原视频上截取的话,在未截取完成前播放视频会导致视频播放进度混乱,所以这里我们在克隆元素对象上进行操作。

我们总共需要截取stepNums张图片,所以每次截取的时间间隔应该为:duration / this.stepNums,即视频总时间长度/截取图片张数,循环截取即可。

2、鼠标移入封面时显示对应关键帧

鼠标移入封面的时候我们需要对封面图片进行切换。

2.1 鼠标移动事件监听

<img
    :id="uid + '-coverImg'"
    :src="coverSrc"
    class="j-coverImg"
    @mousemove="imgHover"
    @mouseleave="hoverOut"
    @click="coverClick"
/>

这里我们使用vue中的mousemove和mouseleave对鼠标事件进行监听。

imgHover(e) {
    const coverImg = document.getElementById(this.uid + "-coverImg");
    const w = coverImg.offsetWidth / this.stepNums;
    const x = e.offsetX - coverImg.offsetLeft;
    const index = Math.min(
        Math.max(Math.ceil(x / w), 1),
        this.stepNums
    );
    if (this.imgList.length < index) return;
    this.progressValue = index;
    coverImg.setAttribute(
        "src",
        this.imgList[Math.min(this.imgList.length - 1, index)]
    );
},

鼠标移入的时候我们需要根据鼠标的坐标位置来计算展示的帧数下标,具体计算如下:

  • 每张图片展示的区间大小
const w = coverImg.offsetWidth / this.stepNums;

每个区间的大小我们只需要将封面的宽度除于图片帧列表的数量即可得到每张图片展示的区间大小。

  • 当前鼠标所在区间
const x = e.offsetX - coverImg.offsetLeft;
const index = Math.min(
    Math.max(Math.ceil(x / w), 1),
    this.stepNums
);

首先我们应该要计算当前鼠标在封面里的相对位置,这里我们只需要其横坐标x即可,然后将坐标除于区间大小,我们即可得到当前坐标所对应的区间下标。这里的最大值应该进行限制为1和stepNums。

2.2 鼠标移出事件监听

鼠标移出的时候我们需要将封面恢复成当前视频的封面。

hoverOut(e) {
    const coverImg = document.getElementById(this.uid + "-coverImg");
    const step = this.duration / this.stepNums;
    const index = Math.ceil(this.pauseTime / step);
    this.progressValue = index;
    coverImg.setAttribute("src", this.pauseCover || this.coverSrc);
},

3、视频和封面的状态切换

封面和视频的显示隐藏需要根据播放状态来进行对应的切换。

3.1 播放视频

点击封面的时候播放视频,需要隐藏封面及相关的进度条并显示视频

doHide(hide = false) {
    const videoContent = document.getElementById(this.uid + "-video");
    videoContent.style.display = hide ? "block" : "none";
    videoContent.currentTime = this.pauseTime;
    hide ? videoContent.play() : videoContent.pause();
    const img = document.getElementById(this.uid + "-coverImg");
    img.style.display = hide ? "none" : "block";
    const progress = document.getElementById(this.uid + "-progress");
    progress.style.display = hide ? "none" : "block";
    const progress1 = document.getElementById(this.uid + "-progress1");
    progress1.style.display = hide ? "none" : "block";
},
coverClick() {
    this.doHide(true);
},

3.2 视频暂停

视频暂停时我们需要隐藏视频,截取当前帧作为封面并显示封面及相关的进度条。

videoContentShow.addEventListener("pause", e => {
    this.pauseTime = videoContentShow.currentTime;
    this.pauseCover = this.cutCover(
        videoContentShow,
        videoContentShow.currentTime
    );
    coverImg.setAttribute("src", this.pauseCover);
    const step = this.duration / this.stepNums;
    const index = Math.ceil(this.pauseTime / step);
    this.progressValue = index;
    setTimeout(() => {
        if (videoContentShow.paused) this.doHide();
    }, 200);
});

这里我使用了一个setTimeout来进行一个延时控制,大家知道为什么吗?因为视频有两种操作会触发视频的pause事件:

  • 点击暂停按钮
  • 拉动进度条

这里拉动进度条的时候会触发视频的pause事件并且马上继续播放,所以我们应该要过滤掉这一情况。

组件使用

<template>
    <div class="content">
        <div class="video-list">
            <j-video-cover
                class="video"
                :videoUrl="videoUrl"
                stepNums="40"
            ></j-video-cover>
        </div>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                videoUrl: require("../../assets/video/202112250058.mp4"),
            }
        }
    }
</script>

组件库引用

这里我将这个组件打包进了自己的一个组件库,并将其发布到了npm上,有需要的同学也可以直接引入该组件进行使用。

引入组件代码

 <j-code-height-light :code = "code"
        :keyWords = "keyWords"
        :color = "color">
    </j-code-height-light>
    <!-- 注释 -->
    <div class = 'body'>
      <div class = 'title'>标题</div>
      <div class = 'main'>
        <span >内容</span>
      </div>
    </div>

        /**
         * 组件参数配置如下
         */
        props: {
            code: {
                type: String,
                default: ''
            },
            keyWords:{
                type:Array,
                default:[
                    {
                        value:'关键字1',
                        color:'颜色1'
                    },
                    {
                        value:'关键字2',
                        color:'颜色2'
                    }
                ]
            },
            color:{
                type: Object,
                default: {
                    keyWord:'orange',//js关键字
                    varWord:'purple',//js变量
                    tagWord:'#F9273F',//html标签
                    strWord:'green',//字符串变量值
                    attrWord:'green',//html属性
                    attrValue:'yellow',//html属性值
                    methodkeyWord:'#74759b',//js方法
                    functionkeyWord:'#2c9678',//自定义函数
                    note:'grey'//注释
                }
            }
        },
        methods:{
            test(){
                console.log('test');
            },
            testP(p1,p2){
                console.log(p1,p2);
            }
        }

引入后即可直接使用。

源码地址

组件库已开源,想要查看完整源码的可以到 gitee 查看,自己也整理了相关的文档对其进行了简单介绍,具体如下:

组件文档 http://shouce.jb51.net/vue/single-file-components.html

以上就是vue实现鼠标滑动预览视频封面组件示例详解的详细内容,更多关于vue鼠标滑动视频封面预览的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vue实现鼠标悬浮切换图片src

    本文实例为大家分享了Vue实现鼠标悬浮切换图片src的具体代码,供大家参考,具体内容如下 需求: 1. 鼠标悬浮到图示按钮上面,图片切换成灰色按钮2. 鼠标离开图示按钮,图片切换成回白色按钮 Html部分: <!-- 如果此处的两个鼠标事件不生效,可以在mouseenter后面添加.native后缀 --> <div class="left-btn"      @click="saveTemplate()"      @mouseenter=&qu

  • Vue 实现一个简单的鼠标拖拽滚动效果插件

    最近开源了一个 Vue 组件,还不够完善,欢迎大家来一起完善它,也希望大家能给个 star 支持一下,谢谢各位了. github 地址:github.com/qq449245884- 最近在做一个新的项目,有个需要是这样的: 简单描述一下,就是鼠标拖动页面,整个页面会随着的鼠标的拖拽而移动,如果页面有内容,里面的内容也需要跟着拖动的外层整体移到. 一开始没啥思路,所以就发了个朋友圈,得到的答案挺多的,主要还是用拖拽之类的,但这个拖拽只是单个元素的拖动,我想要的整个视图的拖动. 这里线索又断了.

  • vue实现鼠标悬浮框效果

    本文实例为大家分享了vue实现鼠标悬浮框效果的具体代码,供大家参考,具体内容如下 效果: html: <div   @mouseenter="enter"    @mouseleave="leave"    @mousemove="move" > 鼠标触碰元素 </div>   <div v-show="popUpShow" class="hover_con" :style=&

  • vue实现鼠标经过显示悬浮框效果

    本文实例为大家分享了vue实现鼠标经过显示悬浮框效果的具体代码,供大家参考,具体内容如下 项目架构采用vue-cli脚手架搭建的webpack项目 实现的效果如下: 鼠标经过button 右边显示出一个悬浮框 鼠标移出buttom元素 悬浮框隐藏 并且悬浮框可以随着鼠标的移动而改变位置 全部代码如下: <template>   <div class="hello">     <div id="focus_toolTip" class=&

  • vue实现组件跟随鼠标位置弹出效果(示例代码)

    实现鼠标放置在“我的”上时出现卡片,卡片位置跟随鼠标.当鼠标移除卡片时卡片隐藏.当鼠标移入时获取鼠标坐标,并把父组件的鼠标位置通过prop传给子组件. toCenter(event){ const{x,y}=event this.mouse_x=x; this.mouse_y=y; this.showCenter=true; }, 子组件通过动态绑定style改变div坐标. 注意!!! 一开始没用watch,而是在data里直接修改,如上所示.这样会出现刷新以后data获取不到prop中的属性

  • vue实现鼠标滑动展示tab栏切换

    本文实例为大家分享了vue实现鼠标滑动展示tab栏切换的具体代码,供大家参考,具体内容如下 动画效果: 代码如下: <template>   <div id="header">     <div class="conten_width">       <div class="contnet_width_content">         <div style="    transfo

  • vue实现鼠标滑动预览视频封面组件示例详解

    目录 组件效果 组件设计 1.视频截取关键帧 2.鼠标移入封面时显示对应关键帧 3.视频和封面的状态切换 功能实现 1.视频截取关键帧图片列表 1.1 截取指定帧 1.2 截取stepNums张关键帧图片 2.鼠标移入封面时显示对应关键帧 2.1 鼠标移动事件监听 2.2 鼠标移出事件监听 3.视频和封面的状态切换 3.1 播放视频 3.2 视频暂停 组件使用 组件库引用 组件效果 https://www.jb51.net/Special/926.htm 组件设计 我们首先应该要对组件进行一个简

  • 微信小程序激励式视频广告组件使用详解

    微信小程序搜索:短视频去水印解析 目前微信小程序针对个人来说广告是最好的变现方式,广告主要分为: 1. Banner 2. 激励式视频 3. 插屏 Banner广告很简单,插入代码就可以显示 这里介绍下激励式视频广告实现(观看完整广告奖励积分): //视频广告 let videoAd = null; //视频广告拉取状态 let videoAdPushStatus = false; Page({ data: { //积分总数 creditsAmountSum: 100 }, onLoad(opt

  • Vue实现高德坐标转GPS坐标功能的示例详解

    首先介绍一下常见的几种地图的坐标类型: WGS-84:这是一个国际标准,也就是GPS坐标(Google Earth.或者GPS模块采集的都是这个类型). GCJ-02:中国坐标偏移标准,像是Google Map.高德.腾讯地图都是采用这种坐标展示. BD-09:百度坐标偏移标准,百度地图专用的便宜标准. 所以说这篇博文主要是实现GCJ-02坐标转换成WGS-84坐标. 什么时候会用到需要解决坐标转换的问题呢?起因是一个demo,它使用GPS模块采集经纬度数据,然后使用高德地图进行转换,是的,高德

  • Vue.js3.2的vnode部分优化升级使用示例详解

    目录 背景 什么是 vnode 普通元素 vnode 组件 vnode vnode 的优势 如何创建 vnode 创建 vnode 过程的优化 总结 背景 上一篇文章,分析了 Vue.js 3.2 关于响应式部分的优化,此外,在这次优化升级中,还有一个运行时的优化: ~200% faster creation of plain element VNodes 即针对普通元素类型 vnode 的创建,提升了约 200% 的性能.这也是一个非常伟大的优化,是 Vue 的官方核心开发者 HcySunYa

  • Vue.extend实现组件库message组件示例详解

    目录 概述 Vue.extend message 组件配置对象(就是.vue文件) message 生成组件的函数 使用方法 效果图 总结 概述 当我们使用组件库的时候,某些组件并不是直接放到模板当中进行使用,而是通过api的方式调用生成组件并且挂在到我们的页面中,其中最常见的就是message组件,我们在组件库中看到的多数都是api调用的方式生成.记录自己基本实现message组件. Vue.extend 在vue中,要实现通过api方式实现组件的使用,这个aip是必不可少的,因此我们先了解下

  • QT+ffmpeg实现视频解析的示例详解

    目录 一.创建QT项目 二.引入ffmpeg 1.复制头文件和lib 2.复制bin文件 3.简单测试 三.视频解析 1.创建线程 2.创建自定义绘制控件 3.使用自定义控件 4.开启线程,进行视频解析 一.创建QT项目 首先安装了最新的Community版本,Creator是8.0.1版本了. 然后进行项目的创建. 得到的项目没有pro文件,而是CMakeLists.txt. 二.引入ffmpeg 从下面下载的ffmpeg-5.0.1-full_build-shared.7z. https:/

  • vue实现前端展示后端实时日志带颜色示例详解

    目录 vue实现前端展示后端带颜色的日志 需求 操作 采用innerHTML例子 需求: 解决 效果 vue实现前端展示后端带颜色的日志 需求 通过loki获取项目产生的日志,并且在前端显示出来,一开始在没有经过处理的数据会显示一些乱码,并没有将字符转换 经过一番查询后,发现可以使用ansi_up来对日志进行操作颜色代码进行转化. 操作 ansi_up 能够装换颜色代码 GitHub地址 https://github.com/drudru/ansi_up 安装 npm install ansi_

  • VUE中鼠标滚轮使div左右滚动的方法详解

    目录 前言 一.单个实现 1.定义变量 2.编写方法 3.触发 4.卸载 二.多个实现 1.描述 2.addEventListener(参数) 2.触发 3.卸载 总结 前言 技术点: addEventListener/attachEvent(传递参数) 功能描述: 鼠标停在div中,若div有x轴滚动条,则鼠标滚轮控制x轴滚动条横向滚动 一.单个实现 1.定义变量 data () { return { domObj: null } } 2.编写方法 绑定事件 scrollFunction ()

  • vue+webpack实现异步加载三种用法示例详解

    1.第一例 const Home = resolve => { import("@/components/home/home.vue").then( module => { resolve(module) } } 注:(上面import的时候可以不写后缀) export default [{ path: '/home', name:'home', component: Home, meta: { requireAuth: true, // 添加该属性可以判断出该页面是否需要

  • vue element-ui之怎么封装一个自己的组件的详解

    为什么要进行组件封装? 封装的目的就是为了能够更加便捷.快速的进行业务功能的开发.组件(component)是vue的最强大功能之一,组件可以实现一些类似功能的复用及与其它业务逻辑的解耦.在开发中,我们难免会写很多类似的.重复的代码,有时候两个业务模块有相似的功能,采用复制粘贴已经很省事,但如果涉及的字段或有一些小差别,你也会觉得很烦,毕竟你要从头到尾瞅着去改动.这时候如果把那些相同的功能,抽象出来抽离成组件,通过组件引用方式就会显得格外省事了. Vue中怎么封装一个自己的组件 想要封装好一个组

随机推荐