直播软件源码使用canvas实现一个小小的截图功能
考虑了一下这个功能,肯定得用 hook,因为是一个有状态的东西,hook 需要返回截图,取消截图的功能函数以及截取图片
在图片所在的同一父元素节点下添加两个 canvas,【canvas A】用于展示截图动效(比如,未被截取区域背景置灰,截取区域显示边框);【canvas B】用于展示完整图片,便于截取动作进行以及生成截图数据(记住 canvas A 和 canvas B,后面讲解还会用到)
通过在【canvas A】上通过监听mouseup,mousemove,mousedown三个事件计算截取的区域,生成截取动效,生成截取图片等
截图动作完毕的时候即时生成截取图片数据返回
难点
1. 计算截取区域
在截图开始后,在【canvas A】的mousedown事件记录起点坐标 A, 通过mousemove事件实时监听具体的坐标,document 级的mouseup事件记录结束坐标 B(鼠标有可能会跑出截图区域外,所以是在 document 上监听 mouseup),以 A 为起点,B 为终点,AB 两点就能够计算出截取区域
// 获取截图开始的点 【canvas A】.onmousedown = function (e) { 记录起点坐标A } // 获取鼠标坐标 【canvas A】.onmousemove = function (坐标数据) { 1. 记录鼠标坐标 2. 生成截图区域动效 } // 获取截图结束的点 document.addEventListener('mouseup', function (e) { 1.记录终点坐标 2. 生成截图() }
2 截图动画效果(未被选取部分置灰,截取部分添加边框等)
在mousedown事件上把【canvas A】给置灰
// 设置截图时灰色背景 【canvas A】.fillStyle = 'rgba(0,0,0,0.6)' 【canvas A】.strokeStyle = 'rgba(0,143,255,1)'
在mouseup事件上绘制被截取效果
第一步:遮罩层:globalCompositeOperation = 'source-over' 表示在目标图像上显示源图像,那么此时进行fillRect(0, 0, 【canvas A】.width, 【canvas A】.height)那就是把我们之前设置好置灰样式在目标图片上层进行绘制,实现了第一步置灰效果
第二步:画框:globalCompositeOperation = 'destination-out' 在源图像之外显示目标图像。只有源图像之外的目标图像部分会被显示,源图像是透明的。【canvas A】.fillRect(x, y, w, h)使得截取内部透明
第三步:描边:懂的都懂,不细讲了
//第一步:遮罩层 【canvas A】.globalCompositeOperation = 'source-over' 【canvas A】.fillRect(0, 0, 【canvas A】.width, 【canvas A】.height) //第二步:画框 【canvas A】.globalCompositeOperation = 'destination-out' 【canvas A】.fillRect(x, y, w, h) //第三步:描边 【canvas A】.globalCompositeOperation = 'source-over' 【canvas A】.moveTo(x, y) 【canvas A】.lineTo(x + w, y) 【canvas A】.lineTo(x + w, y + h) 【canvas A】.lineTo(x, y + h) 【canvas A】.lineTo(x, y) 【canvas A】.stroke() 【canvas A】.closePath()
3. 生成&获得截取区域图片
鼠标动作停止后就是截图结束,所以需要在moveup事件生成截取图片数据,在这里可以通过 canvas 自带的 canvas.toDataURL 把截图转化为 base64,因为通过mousedown和mousemove我们已经获取用户的截取区域了,并且我们在截图开始的时候,会把原图片绘制到【canvas B】中,所以我们可以直接在【canvas B】上对该区域进行截取然后生成图片~
const canvas = document.createElement('canvas') const context = canvas.getContext('2d') const data = 【canvas B】.getImageData(area.x, area.y, area.w, area.h) canvas.width = area.w canvas.height = area.h context.putImageData(data, 0, 0) return canvas.toDataURL('image/png', 1)
以上就是直播软件源码使用canvas实现一个截图功能的相关代码, 更多内容欢迎关注之后的文章