当前位置: 首页 > news >正文

工程建设教育网首页郑州seo多少钱

工程建设教育网首页,郑州seo多少钱,安徽省两学一做网站,袜子的网站建设方案Electron 应用实现截图并编辑功能 Electron 应用如何实现截屏功能,有两种思路,作为一个框架是否可以通过框架实现截屏,另一种就是 javaScript 结合 html 中画布功能实现截屏。 在初步思考之后,本文优先探索使用 Electron 实现截屏…

Electron 应用实现截图并编辑功能

Electron 应用如何实现截屏功能,有两种思路,作为一个框架是否可以通过框架实现截屏,另一种就是 javaScript 结合 html 中画布功能实现截屏。
在初步思考之后,本文优先探索使用 Electron 实现截屏功能。作为一个成熟的框架,如果能够完成截屏,那自然是已经考虑了各种会出现的问题。
Electron 想要截屏还是要用到 desktopCapturer API。这个 API 也是用来实现录屏。
首先创建一个项目,直接 clone angular-electron。

环境

  • Angular@13.3.1
  • Electron@18.0.1
  • ngx-img-cropper@11.0.0

流程:

1.渲染进程向主进程取截屏的数据。
2.主进程获取截屏数据,并返回。
3.渲染进程取到数据后,将数据转为图片显示在页面上。
4.页面编辑图片并获取新的图片数据保存到本地。

首先在 home.component.ts 中绑定一个点击事件,向主进程发送一个消息取得录屏的初始数据:

async getScreensht() {let data = await this.electron.ipcRenderer.invoke("get-screenshot");
}

在主进程 main.ts 中,首先获取当前屏幕(可能存在多个屏幕),再取得当前屏幕的截屏数据:

先看取得截屏数据的方法:

let sources = await desktopCapturer.getSources({ types: ['screen'], thumbnailSize: thumbSize });

结果如下(只有一个屏幕数据,如果有两个屏幕,则有两条数据,依次类推):

 [{name: 'Entire Screen',id: 'screen:0:0',thumbnail: NativeImage {toPNG: [Function: toPNG],toJPEG: [Function: toJPEG],toBitmap: [Function: toBitmap],getBitmap: [Function: getBitmap],toDataURL: [Function: toDataURL],...},display_id: '2528732444',appIcon: null}
]

这个结果中有一个参数 display_id,代表着对应的屏幕。那么怎么知道截屏哪个屏幕呢?需要利用鼠标点击事件,鼠标在哪个屏幕点击则截屏哪个屏幕。
鼠标点击位于当前屏幕的窗口,方法如下,通过 BrowserWindow 找到聚焦的窗口,再根据位置判断当前窗口位于哪个屏幕:

// 获取当前窗口所在屏幕
function getCurrentScreen() {let focusedWindow = BrowserWindow.getFocusedWindow();let currentBounds =  focusedWindow.getBounds();let currentDisplay = screen.getAllDisplays().find((display) => {return (currentBounds.x >= display.bounds.x &&currentBounds.x < display.bounds.x + display.bounds.width &&currentBounds.y >= display.bounds.y &&currentBounds.y < display.bounds.y + display.bounds.height);});return currentDisplay;
}

以上方法返回的结果如下,可以看到其中的 id 参数与上文中的 display_id 一致。
由此可以从 desktopCapturer.getSources() 返回的多个数据中找到当前点击的屏幕。

{id: 2528732444,bounds: { x: 0, y: 0, width: 1920, height: 1080 },workArea: { x: 0, y: 0, width: 1920, height: 1040 },accelerometerSupport: 'unknown',...
}

遗憾的是在后续的测试中,竟然存在部分设备返回 currentDisplay 中的 id 参数为 “”(空字符串)。
这样,无法通过 display_id 与 id 的一一对应,而确定截取的是哪个屏幕。
为什么会出现这种情况?在 github 上 electron 的代码库中有此讨论。
请看这里 desktopCapturer display_id is empty string

根据讨论,另一种方法为下,

function getCurrentScreen() {let currentBounds = win.getBounds();let currentDisplay = screen.getDisplayNearestPoint({ x: currentBounds.x, y: currentBounds.y });let allDisplays = screen.getAllDisplays();let currentDisplayIndex = allDisplays.findIndex((display) => {return display.id === currentDisplay.id});return { 'screen_index': currentDisplayIndex };;
}

那么梳理一下流程:渲染进程响应一个点击事件,向主进程发送一个消息,获取当前屏幕的截屏数据:

// 渲染进程
let data = await this.electron.ipcRenderer.invoke("get-screenshot");// 主进程
ipcMain.handle('get-screenshot', async (e, args) => {let current_screen = getCurrentScreen();  // 取得当前屏幕let primaryDisplay = screen.getPrimaryDisplay();// 这里的 primaryDisplay.size 由于缩放的原因可能与系统设置的分辨率不一样, 再乘上缩放比 scaleFactorlet reality_width = primaryDisplay.size.width * primaryDisplay.scaleFactor;let reality_height = primaryDisplay.size.height * primaryDisplay.scaleFactor;let thumbSize = { width: reality_width, height: reality_height };let source = await getDesktopCapturer(current_screen, thumbSize); // 取得当前屏幕截屏数据if (source) {return source;}
});async function getDesktopCapturer(current_screen, thumbSize) {let screenName = current_screen['screen_index'] + 1;let screen_names = [];screen_names.push('Screen ' + screenName);  // 中文为 `screen_names.push('屏幕 ' + screenName);`screen_names.push('Entire Screen');  // 中文为 `screen_names.push('整个屏幕');`// 以 thumbSize 屏幕分辨率取得所有屏幕截屏数据,如果 types 设置为 ['screen', 'window'] 同时可以获取各个窗口的截屏数据let sources = await desktopCapturer.getSources({ types: ['screen'], thumbnailSize: thumbSize });// 如果只有一个屏幕,则 name 为'整个屏幕',如果有两个及以上屏幕,则 name 为 '屏幕 1' 和 '屏幕 2'if (sources) {for (let source of sources) {if (screen_names.indexOf(source.name) != -1) {  // 通过 name 确定屏幕return source;}}}
}

渲染进程中取到的截屏数据如下:

{name: 'Entire Screen',id: 'screen:0:0',thumbnail: NativeImage {toPNG: [Function: toPNG],toJPEG: [Function: toJPEG],toBitmap: [Function: toBitmap],getBitmap: [Function: getBitmap],toDataURL: [Function: toDataURL],...},display_id: '2528732444',appIcon: null
}

thumbnail 为一个对象,通过其中的 toPNG、toJPG、toDataURL 等方法可以将数据转为 PNG、JPG 等格式。
例如以下转为 dataURL,即 base64 编码格式,以便在 web 中显示在 img 标签中:

let data = await this.electron.ipcRenderer.invoke("get-screenshot");
let image_url = data.thumbnail.toDataURL();

又或者在主进程中先转为 PNG 格式 let png_data = data.thumbnail.toPNG();
再使用 fs 模块直接保存到本地 fs.writeFileSync('D:\\1.png', png_data);

在渲染进程中得到了截屏数据,然后就是显示和编辑。

这里选取 ngx-img-cropper 插件。安装 npm i ngx-img-cropper@11.0.0 --save,由于本项目使用 Angular@13.3.1 所以使用 v11.0.0 版本。
ngx-img-cropper 教程。

在 module.ts 中导入 import { ImageCropperModule } from 'ngx-img-cropper';

然后根据教程中 Customizing Image cropper 一节内容这里做如下修改:

home.conponent.html 文件内容如下,去掉多余的选择文件和预览显示,留下编辑部分,再加上三个 button,用于获取截屏,清除截屏,和保存结果。

<div class="container"><div style="display: flex;"><button (click)="getScreensht()">get</button><button (click)="clear()">clear</button><button (click)="save()">save</button></div><img-cropper #cropper [image]="image_data" [settings]="cropperSettings"></img-cropper>
</div>

home.component.ts 文件修改如下,首先修改 constructor 中的内容,

this.cropperSettings = new CropperSettings();
this.cropperSettings.preserveSize = true;  // 不缩放裁剪图像 以裁剪大小保存
this.cropperSettings.keepAspect = false;  // 不保持裁剪图片纵横比
this.cropperSettings.noFileInput = true;  // 不要 input 标签
this.cropperSettings.cropperDrawSettings.strokeWidth = 2;  // 选择框边框宽度
this.cropperSettings.cropperDrawSettings.strokeColor = '#1296db';  // 选择框边框颜色
this.cropperSettings.cropperDrawSettings.fillColor = '#fff';  // 角选择块颜色
this.cropperSettings.markerSizeMultiplier = 1;  // 角选择块大小
this.cropperSettings.canvasWidth = 960;  // 画布宽
this.cropperSettings.canvasHeight = 540;
this.cropperSettings.width = 960;  // 初始选择框的宽
this.cropperSettings.height = 540;
this.data = { image: '' };

以上配置参数与页面样式或保存图片相关,添加了部分注释,点击 get button 对应的代码如下,首先是向主进程取得数据,转换后赋值。

async getScreensht() {let data = await this.electron.ipcRenderer.invoke("get-screenshot");let image_url = data.thumbnail.toDataURL();this.data['image'] = image_url;let image: any = new Image();image.src = image_url;this.cropper.setImage(image);
}

此时页面如下图显示:

在这里插入图片描述

这时拖动四个角可以选择截图区域,拖动中间图标可以移动选择截取的区域,点击 clear 清除页面。

clear() {this.cropper.reset();
}

点击 save button,则会将图片保存,保存图片方法如下,首先是取得截取的数据,再发送到主进程并重置页面。

save() {let base64Data = this.data['image'];if (base64Data) {this.electron.ipcRenderer.send('save-screenshot', {data: base64Data});this.clear();}
}

主进程接收到数据后,处理数据,去除 base64 文件编码信息部分,再通过 fs.writeFileSync() 方法保存本地。

ipcMain.on('save-screenshot', (e, args) => {let temp_file = "C:\\temp\\test.png"; // 文件路径let base64Data = args['data'].replace(/^data:image\/png;base64,/, '');let imageBuffer = Buffer.from(base64Data, 'base64');fs.writeFileSync(temp_file, imageBuffer);
});

到此即可将截屏数据显示再页面上,编辑后保存到本地。不过 ngx-img-cropper 这个插件的功能较少,暂时只能编辑大小。
CropperSettings 还有一些其他的参数,可以看 ngx-img-cropper 教程,centerTouchRadius 可以设置拖动图标的范围,默认是图标所在区域的一小部分。
一些问题,如果编辑图片的窗口是动态的,则 this.cropperSettings.canvasWidth = 960; 这些设置宽高的参数可以在 ngOnInit() 初始化中取得参数后设置。
当前截图类似与 QQ 聊天窗口中的屏幕截图按钮,会将主窗口一同截取。如果想实现 QQ 截图快捷键的操作(不截取聊天窗口,本项目是主窗口),
一种办法是在通过 desktopCapturer.getSources() 取得屏幕资源数据前最小化(minimize 方法)主窗口。并在资源数据返回到渲染进程时,再显示(show 方法)主窗口。
需要注意,要先判断主窗口最小化,再取数据,因为 minimize 需要等待时间才能获取数据。

http://www.hkea.cn/news/11381/

相关文章:

  • 西安那里做网站百度关键词优化首选667seo
  • 浏览收费网站模板营销型网站的类型有哪些
  • 旅游网站的功能结构图seo手机优化软件哪个好用
  • 官方网站哪家做的最好服务器ip域名解析
  • 网站建设做什么费用乐天seo培训
  • 找人做网站!!! 网站定制开发福建seo网站
  • 网站建设的认可搜索引擎优化培训免费咨询
  • 网罗天下做网站靠谱吗网络广告设计
  • wordpress 指定审核人南昌seo排名扣费
  • 南通网站建设系统电话优化网站排名方法
  • dede中英文企业网站学习软件的网站
  • 石家庄疫情最新情况最新消息seo标题优化
  • 淘宝做轮播广告哪个网站好永久免费google搜索引擎
  • 曰本免费网站文军seo
  • 项目计划书目录徐州网站建设方案优化
  • 创新的邯郸网站建设页面设计漂亮的网站
  • 怎样建设个人影视网站公司seo排名优化
  • wordpress全站加密免费手机网站建站系统
  • 织梦可以做哪些类型型网站整合营销传播策略
  • 软件库网站源码竞价托管外包服务
  • 网站建设概况培训网络营销机构
  • 最近播放中文版在线观看电视剧上海优化关键词的公司
  • 淘宝官网首页登录注册长沙seo行者seo09
  • 建站公司网站建设武汉做seo
  • 百度网站推广网络网络推广深圳有效渠道
  • 邵阳网站建设公司中国进入全国紧急状态
  • 信息图表设计网站痘痘怎么去除有效果
  • 网站的域名在哪里看互联网推广是什么工作内容
  • 用手机做自己的网站怎么申请网站详细步骤
  • 详情页设计多少钱广告优化