js实现撤销恢复_Dom节点变动检测并录制的简单实现

c0a6be79ff04f27abce8b504c8a76548.png

点击上方蓝字关注我们

关键技术

MutationObserver

MutationObserver使用来监测某个范围内DOM的变动,如节点的增减、属性的变动,文本节点的变化等。相当于DOM的改变就会触发MutationObserver这个事件,但是这个事件是异步触发的,会把DOM的变动封装成一个数组进行统一更新的,这点和react中的setState非常相像。

构造函数

var observer = new MutationObserver(function (mutations, observer) {  mutations.forEach(function(mutation) {    console.log(mutation);  });})

在调用时,观察者对象会传给该函数两个参数:

  • MutationObserver接受一个callback参数,用来处理节点变化的回调函数,返回两个参数,mutations和observer。

  • mutations:节点变化记录列表

  • observer:MutationObserver的实例对象。

方法

MutationObserver对象有三个方法,分别如下:

  • observe:设置观察目标,接受两个参数,target:观察目标,options:通过对象成员来设置观察选项

  • disconnect:阻止观察者观察任何改变

  • takeRecords:清空记录队列并返回里面的内容

observe方法中常用的options参数有以下几个选项:

  • childList:设置true,表示观察目标子节点的变化,比如添加或者删除目标子节点,不包括修改子节点以及子节点后代的变化

  • attributes:设置true,表示观察目标属性的改变

  • characterData:设置true,表示观察目标数据的改变

  • subtree:设置为true,目标以及目标的后代改变都会观察

使用示例

现在有一个id为target的节点

'target' class='block'>div>

对该dom进行监听并测试

var target=document.getElementById('target');var i=0var observe=new MutationObserver(function (mutations,observe) {    i++  });observe.observe(target,{ childList: true});target.appendChild(docuemnt. createElement ('span')); target.appendChild(docuemnt. createElement ('div'));console.log(i)  //1

录制回放操作的简单实现

初始思路:使用MutationObserver监听整个页面,每当有页面变动,则将页面的html转换成图片进行队列存储,回放用户操作即不停从队列中取出元素展示

Html转Canvas

这里我们直接使用html2canvas这个第三方库官方地址,基于html2canvas.js可将一个元素渲染为canvas,只需要简单的调用html2canvas(element[, options]),下列html2canvas方法会返回一个包含有canvas元素的promise:

html2canvas(document.body).then(function(canvas) {    document.body.appendChild(canvas);});

Canvas转Img

上一步生成的canvas即为包含目标元素的canvas元素对象。实现保存图片的目标只需要将canvas转image即可。通过canvas的toDataURL方法将canvas输出为data: URI类型的图片base64地址,再将该图片地址赋值给元素的src属性即可。

示例

<canvas id="canvas" width="5" height="5">canvas>

获取该图片,直接可以用toDataURL转成图片,默认为 PNG 格式

var canvas = document.getElementById("canvas");var dataURL = canvas.toDataURL();console.log(dataURL);// "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby...

最后,通过定时器将img不停的插入到img标签的src中,实现回放的效果。

Canvas在高分屏中一些缺陷的解决方法

Canvas在高分屏中绘制图片会有模糊的效果,其实不只是绘制图片时会出现模糊的问题,高清屏的设备中任何绘制在 canvas 中的图形(包括文字)都会出现模糊的问题。

这是因为HIDPI的屏幕上的像素实际上是逻辑像素,我们如果当成正常的像素(css中设置的像素)使用它,如我们在css中设置100px时,在例如iphone4S(devicePixelRatio为2)上,实际渲染的是200px的物理像素。所以当我们向这种高分辨率的屏幕添加img的时候,我们的图像及其他一些图形文字都会受到devicePixelRatio的影响会变得模糊。
解决方法很简单,就是将 canvas 的高和宽分别乘以 devicePixelRatio将其放大,然后又用 CSS 将高和宽限制成初始的大小。

Demo效果

这里为了简化操作,做了两个按钮做添加和删除元素,实际情况中,不仅需要对dom节点的操作进行监听,例如用户的点击、停留、轨迹等行为数据都需要进行采集分析。

56698174912323e80b49e3f99392c832.gif

方案优化

在Web中, 图形图像的操作以及存储会消耗大量的性能, 通过使用html快照来替代图像快照可以大幅的提高性能以达到生成可用状态,但是需要做很多的处理,当我们存储的是html的快照链时,想要在客户端进行用户操作回放,我们需要构建沙盒环境对html重新进行渲染,有一些工具如parse5可以进行html的序列化和解析操作,“视频回放”其实就是 HTML DOM 的变化增量及快照。
在html的解析过程中需要要对dom快照进行一点的处理,如:

禁止表单提交

禁止跳转、window.open等操作

js脚本的执行(因为我们只是需要dom结构的变化)等

浏览器端存一定量的增量快照后再一起发送到服务端,减少网络开销;也包括多次增量之后再进行一次全量,对齐真实状态。

数据脱敏

通过 DocumentFragment 提高平台回放效率。

可以参考开源方案RRWeb:https://github.com/rrweb-io/rrweb

基于上述技术还可以实现哪些小功能(思路)

网页中长按保存截图(针对移动端)

捕捉长按的操作,然后通过我们上面的,实现转canvas转img的操作

网页中实现撤销操作

记录用户的每次的dom操作放到一个栈中,每次用户触发撤销操的时候从栈中取出一个元素,可以还原上次的dom结构,从而实现了撤销的操作

有关动态显示的部分

例如根据文本内容是否超出来动态控制是否显示Tooltip,文本末尾显示其他内容等

写在最后

方凳雅集是由阿里巴巴B系6大BU(1688,ICBU,零售通,AE,企业金融,考拉)共同维护的公众号奥,我们会定期发送优质好文,欢迎扫码关注

45e5605f414f84e2cdddc3f8cff526b7.png

求关注

求转发

ecd4b0d583d4b28cce1428ccb4fa0464.pnge23e737bcc16eff5b34a3bf9a83df3b8.png
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值