

神奇的程序员K的个人空间
source link: https://my.oschina.net/u/4219607/blog/5336449
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

上周六有个群友@我说Gitee的反馈模块新增了截图功能,我就去体验了下,发现他们用的就是我的插件?,本文就跟大家分享下这个插件,欢迎各位感兴趣的开发者阅读本文。
插件地址与实现原理
本插件采用原生js实现,可以集成在任意一个web项目中,插件npm地址与GitHub地址请移步:
插件的实现原理请移步:
在线体验本插件,可移步我的开源项目chat-system进行体验,插件的运行效果视频请移步实现web端自定义截屏功能-效果视频。
Gitee产品经理的青睐
月初的时候,Gitee的产品经理在掘金看到我的截图插件js-screen-shot觉得还不错,他们最近在做这方面的功能,就打算将我的插件直接集成进去,跟我沟通了下版权相关的事情。
沟通完成后,他问我要不要把插件在Gitee也放一份,可以帮我推荐下,我毫不犹豫的抱住了大腿,就把插件搬过去了,得到一波首页推荐?
Gitee的反馈模块需要登录后,点页面右侧的发送反馈图标。
影响体验的一些小问题
上周二,从GitHub来了个网友,加了我微信,给我的插件提了两个issues,因为周内没时间处理这些问题,就计划周末统一处理下插件的issues。
整理有效的issues
时间回到上周六早上,我打开GitHub瞅了一眼issues,许久不看居然已经有19条了。
经过一番整理,去掉一些无用的和已经修改好了的,最终确定了4条:
- 调用者可以在框选区域外绘制问题
- 截图区域工具栏首次点击时删除裁剪框的8个可操作点
- 修复框选完成后,鼠标点击其他位置截图工具栏跟着移动问题
- 添加可选参数支持单击截全屏功能
解决issues
问题整理完成,接下来就是解决问题环节了。
选区外绘制问题
正常情况下,截图区域确立后,用户都会在裁剪框区域内进行绘制,所以我就没考虑这个边界情况?,插件用的人多了后,自然就有人发现了这个问题,我们拿gitee的反馈模块举例(gitee目前用的还是我的旧版插件,肯定存在这个问题),如下所示,我们绘制的4个红色方框都超出裁剪框了:
这个问题解决起来比较简单,裁剪框已经绘制好了,知道它的坐标信息,我们在进行绘制时,只需要判断当前鼠标位置是否超出裁剪框的坐标点区域即可。部分实现代码如下所示:
// 获取裁剪框位置信息
const cutBoxPosition = this.data.getCutOutBoxPosition();
// 绘制中工具的起始x、y坐标不能小于裁剪框的起始坐标
// 绘制中工具的起始x、y坐标不能大于裁剪框的结束坐标
// 当前鼠标的x坐标不能小于裁剪框起始x坐标,不能大于裁剪框的结束坐标
// 当前鼠标的y坐标不能小于裁剪框起始y坐标,不能大于裁剪框的结束坐标
if (
!getDrawBoundaryStatus(startX, startY, cutBoxPosition) ||
!getDrawBoundaryStatus(currentX, currentY, cutBoxPosition)
)
return;
getDrawBoundaryStatus
函数实现如下所示:
/**
* 获取工具栏工具边界绘制状态
* @param startX x轴绘制起点
* @param startY y轴绘制起点
* @param cutBoxPosition 裁剪框位置信息
*/
export function getDrawBoundaryStatus(
startX: number,
startY: number,
cutBoxPosition: positionInfoType
): boolean {
if (
startX < cutBoxPosition.startX ||
startY < cutBoxPosition.startY ||
startX > cutBoxPosition.startX + cutBoxPosition.width ||
startY > cutBoxPosition.startY + cutBoxPosition.height
) {
// 无法绘制
return false;
}
// 可以绘制
return true;
}
具体代码请移步提交记录: fix: 修复插件调用者可以在框选区域外绘制问题
实现后的效果如下所示:
工具栏跟随鼠标移动问题
这个问题可以描述为:裁剪框确定后,工具栏尚未点击,此时鼠标点其他位置,截图工具栏就跟着鼠标重新计算了位置,我们继续用Gitee来举例,如下所示:
当鼠标左键抬起时,如果工具栏尚未被点击,则会根据当前鼠标的位置结合裁剪框的大小确立截图工具栏的位置。用户只是单纯的点击了裁剪框区域的任意位置,工具栏就跟着移动了。
解决这个问题也很简单,我们只需要在鼠标移动时添加一个标识,鼠标抬起时判断这个标识是否为true即可。部分代码如下所示:
// 鼠标拖动状态
private dragFlag = false;
// 鼠标移动事件
private mouseMoveEvent = (event: MouseEvent) => {
// 工具栏未选择且鼠标处于按下状态时
if (!this.data.getToolClickStatus() && this.data.getDragging()) {
// 修改拖动状态为true;
this.dragFlag = true;
}
}
// 鼠标抬起事件
private mouseUpEvent = () => {
// 鼠标尚未拖动且工具栏未选择则不修改工具栏位置
if (!this.dragFlag && !this.data.getToolClickStatus()) {
// 复原裁剪框的坐标
this.drawGraphPosition.startX = this.drawGraphPrevX;
this.drawGraphPosition.startY = this.drawGraphPrevY;
// 显示截图工具栏
this.data.setToolStatus(true);
return;
}
}
具体代码请移步提交记录:fix: 修复框选完成后,鼠标点击其他位置截图工具栏跟着移动问题
修复后的效果如下所示:
删除8个可操作点
去年截图插件刚写好时,我就发现这个问题了,当截图工具栏点击后裁剪框就不允许更改了,如果8个可操作点依然存在的话,看起来很奇怪,当时想到的思路是直接删除边框的8点,但是这8个点都是绘制上去的,折腾了挺久没找到方案就搁置了,这个问题如下图所示:
一年后的今天,我知道删除那8个点的思路肯定行不通,我就一遍又一遍的体验QQ的截图,观察他是怎么做的,突然,我灵感惊现?,我既然有裁剪框的坐标和大小信息,我重新绘制一下这个裁剪框不就好了?,裁剪框四周的8个可操作点删除后,我就可以删掉生成图片时优化那8个点的计算逻辑,导致范围不精确问题,从而实现完美截图。部分实现代码如下所示:
// 工具栏尚未点击,当前属于首次点击,重新绘制一个无像素点的裁剪框
if (!data.getToolClickStatus()) {
// 获取裁剪框位置信息
const cutBoxPosition = data.getCutOutBoxPosition();
// 开始绘制无像素点裁剪框
drawCutOutBox(
cutBoxPosition.startX,
cutBoxPosition.startY,
cutBoxPosition.width,
cutBoxPosition.height,
screenShortCanvas,
data.getBorderSize(),
screenShortController as HTMLCanvasElement,
ScreenShortImageController,
false
);
}
具体代码请移步提交记录:fix: 截图区域工具栏首次点击时删除裁剪框的8个可操作点
实现单击截全屏功能
给我提issues的那个网友希望截图插件加载完毕后,用户不拖拽生成选框,直接鼠标左键单击就能截取整个屏幕,我觉得这个需求需要的人不多,就将其做成了可选参数。
这个也很简单,鼠标抬起时,如果开启了单击截全屏,则从坐标(0,0)位置绘制一个与画布同等大小的裁剪框即可,部分代码如下所示:
// 鼠标抬起事件
private mouseUpEvent = () => {
if (
cutBoxPosition.width === 0 &&
cutBoxPosition.height === 0 &&
cutBoxPosition.startX === 0 &&
cutBoxPosition.startY === 0 &&
!this.dragFlag &&
this.clickCutFullScreen
) {
// 设置裁剪框位置为全屏
this.tempGraphPosition = drawCutOutBox(
0,
0,
this.screenShortImageController.width,
this.screenShortImageController.height,
this.screenShortCanvas,
this.data.getBorderSize(),
this.screenShortController,
this.screenShortImageController
) as drawCutOutBoxReturnType;
}
}
具体代码请移步提交记录:feat: 添加可选参数支持单击截全屏功能
至此,文章就分享完毕了。
我是神奇的程序员,一位前端开发工程师。
如果你对我感兴趣,请移步我的个人网站,进一步了解。
- 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注?
- 本文首发于神奇的程序员公众号,未经许可禁止转载?
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK