rrweb录屏组件实现

文章详细介绍了rrweb录屏和rrweb-playerVue组件的安装、配置和使用方法,包括如何设置依赖、组件代码实现以及在实际项目中的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

官方文档:https://github.com/rrweb-io/rrweb/blob/master/guide.zh_CN.md

一、rrweb录屏

安装依赖:

npm install --save rrweb

组件代码:

<template>
    <div></div>
</template>

<script>
import * as rrweb from "rrweb";

export default {
    name: "HmRrwebRecord",
    props: {
        /**
         * 保存接口
         */
        url: {
            type: String,
            default: "",
        },
        /**
         * 额外保存参数
         */
        params: {
            type: Object,
            default: function () {
                return {}
            }
        },
        /**
         * 最大操作次数
         */
        maxCount: {
            type: Number,
            default: -1,
        },
        /**
         * 保存频率(秒)
         */
        cycle: {
            type: Number,
            default: 10,
        },
        /**
         * 是否增量保存
         */
        incremental: {
            type: Boolean,
            default: true
        },
        /**
         * 页面切换是否停止
         */
         routeStop: {
            type: Boolean,
            default: true
        },
    },
    data() {
        return {
            cUrl: "",
            cMaxCount: -1,
            cCycle: 10,
            cParams: {},
            events: [],
            cRouteStop:true,
        };
    },
    watch: {
        url(value) {
            this.cUrl = value;
        },
        maxCount(value) {
            this.cMaxCount = value;
        },
        cycle(value) {
            this.cCycle = value;
        },
        params(value) {
            this.cParams = value;
        },
        routeStop(value) {
            this.cRouteStop = value;
        },
    },
    mounted() {
        this.cUrl = this.url;
        this.cMaxCount = this.maxCount;
        this.cCycle = this.cycle;
        this.cParams = this.params;
        this.cRouteStop = this.routeStop;
        //开始录制
        //this.start();
        this.currentRoute = this.$route.path;
    },
    methods: {
        start: function (e) {
            let self = this;
            self.stopFn = rrweb.record({
                emit(event) {
                    if (self.cMaxCount && self.cMaxCount != -1 && self.events.length > self.cMaxCount) {
                        // 当事件数量大于 maxCount 时停止录制
                        self.stopFn();
                    }
                    // 将 event 存入 events 数组中
                    self.events.push(event);
                },
                packFn: rrweb.pack,//数据压缩
            });

            // 每 cycle 秒调用一次 save 方法
            if (self.cCycle && self.cCycle != -1) {
                //开启定时器存储
                self.startSaveInterval();
            }

            /**
             * 开始录制
             * @params e
             * @event start
             */
            this.$emit("start", self.events);
        },
        stop: function (e) {
            //停止录制
            if (typeof this.stopFn === 'function') {
                this.stopFn();
            }
            // 停止循环定时
            clearInterval(this.recordInterval);

            /**
             * 停止录制
             * @params e
             * @event stop
             */
            this.$emit("stop", this.events);
        },
        startSaveInterval: function(e){
            let self = this;
            //定时保存录屏数据
            let time = self.cCycle * 1000;
            self.recordInterval = setInterval(() => {
                self.save();
            }, time);
        },
        save: function (e) {
            let self = this;
            //console.log(self.currentRoute+" <---> "+self.$route.path);
            //路由变化自动停止录屏,可防止其他页面也被录进去
            if(self.cRouteStop && self.currentRoute != self.$route.path){
                self.stop();
                return;
            }

            if (!self.cUrl || self.cUrl == '' || self.events.length == 0) {
                return;
            }
            let eventData = self.events;
            //是否增量更新
            if (self.incremental) {
                self.events = [];
            }

            let params = { ...self.cParams, events: JSON.stringify(eventData) };
            self.$postAction(self.cUrl, params).then((resp) => {
                /**
                 * 保存录制数据
                 * @params e
                 * @event save
                 */
                self.$emit("save", self.events, resp);
                //未授权时停止录屏
                if(resp.code && resp.code == 401){
                    self.stop();
                }
            });
        },
    },
    destroyed(e) {
        // 停止循环定时
        clearInterval(this.recordInterval);
    },
};
</script>
<style scoped></style>

二、rrweb-player录屏播放器

安装依赖:

npm install --save rrweb-player

组件代码:

<template>
    <div id="playback" class="player-body">
        <div :class="cLoading?'spin-active':'spin-hide'">
            <a-spin tip="Loading..." size="large" :spinning="cLoading" />
        </div>
    </div>
</template>

<script>
import * as rrweb from "rrweb";
import rrwebPlayer from 'rrweb-player';
import 'rrweb-player/dist/style.css';

export default {
    name: "HmRrwebPlayer",
    props: {
        /**
         * 播放器配置
         */
        config: {
            type: Object,
            default: function () {
                return {
                    events: [],//包含回放所需的数据
                    width:1024,//播放器宽度
                    height:576,//播放器高度
                    autoPlay:true,//是否自动播放
                    mouseTail:false,//是否在回放时增加鼠标轨迹
                    speedOption: [1, 2, 5, 10],//倍速播放可选值
                    showController:true,//是否显示播放器控制 UI
                }
            }
        },
        /**
         * loading
         */
         loading: {
            type: Boolean,
            default: true
        },
    },
    data() {
        return {
            replayer:null,
            cConfig: [],
            cLoading:true,
        };
    },
    watch: {
        config(value) {
            this.cConfig = value;
        },
        loading(value) {
            this.cLoading = value;
        },
    },
    mounted() {
        this.cConfig = this.config;
        this.cLoading = this.loading;
    },
    methods: {
        play: function (e) {
            let self = this;
            self.destroyPlayer();
            //至少包含2个以上事件时为正常录屏数据
            if(self.cConfig.events.length>2){
                self.cLoading = false;
            }
            self.replayer = new rrwebPlayer({
                target: document.getElementById("playback"),
                    // 配置项
                    props: {
                        ...self.cConfig,
                        unpackFn: rrweb.unpack,//数据解压
                    },
                });

            /**
             * 播放
             * @params e
             * @event play
             */
            this.$emit("play", this.cEvents);
        },
        destroyPlayer: function (e) {
            let self = this;
            if(self.replayer){
                // 假设rrwebPlayer元素的类名为"rr-player"
                let rrwebPlayers = document.getElementsByClassName("rr-player");

                // 从DOM中移除所有具有"rr-player"类名的rrwebPlayer元素
                while (rrwebPlayers.length > 0) {
                    rrwebPlayers[0].parentNode.removeChild(rrwebPlayers[0]);
                }
                self.replayer =null;
            }
        }
    },
};
</script>
<style scoped>
.player-body{
    display: flex;
    justify-content: center;
    align-items: center;
}
.spin-active {
    display: flex;
    justify-content: center;
    align-items: center;
    position: fixed;
    z-index: 99999;
}
.spin-hide {
    display: none;
}
</style>

三、使用示例

<template>
    <div>
        <HmRrwebRecord ref="hmRrwebRecord"></HmRrwebRecord>
        <HmRrwebPlayer ref="hmRrwebPlayer"></HmRrwebPlayer>
        <div>
            <button type="primary" @click="count">点击计数器</button>
        </div>
        <div>计数:{{ sum }}</div>
        <div>
            <button type="primary" @click="start">开始录屏</button>
            <button type="primary" @click="stop">停止录屏</button>
            <button type="primary" @click="play">查看回放</button>
        </div>
    </div>
</template>
  
<script>
import HmRrwebRecord from '/@/components/rrweb/HmRrwebRecord.vue'
import HmRrwebPlayer from '/@/components/rrweb/HmRrwebPlayer.vue'
export default {
    components: {
        HmRrwebRecord,
        HmRrwebPlayer
    },
    data() {
        return {
            sum: 0,
        }
    },
    mounted() {
        
    },
    methods: {
        count: function (e) {
            this.sum++;
            console.log(this.$refs.hmRrwebRecord.events)
        },
        start(){
            this.$refs.hmRrwebRecord.start();
        },
        stop(){
            this.$refs.hmRrwebRecord.stop();
        },
        play: function (e) {
            this.$refs.hmRrwebPlayer.cConfig.events = this.$refs.hmRrwebRecord.events;
            this.$refs.hmRrwebPlayer.play();
        }
    }
}
</script>
  
<style></style>

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_月下闲人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值