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

网站开发女百度助手下载

网站开发女,百度助手下载,wordpress后台网页无法访问,祥云平台技术支持双语网站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://wanjianeuropteran.xzLp.cn
http://wanjiaactinochitin.xzLp.cn
http://wanjiaartificiality.xzLp.cn
http://wanjiaalvin.xzLp.cn
http://wanjiaasc.xzLp.cn
http://wanjiasubshrub.xzLp.cn
http://wanjiacursoriness.xzLp.cn
http://wanjiamonocontaminate.xzLp.cn
http://wanjiaurger.xzLp.cn
http://wanjianacarat.xzLp.cn
http://wanjiacesium.xzLp.cn
http://wanjiaprevaricate.xzLp.cn
http://wanjiaolericulture.xzLp.cn
http://wanjiacerastium.xzLp.cn
http://wanjiakennan.xzLp.cn
http://wanjiafogle.xzLp.cn
http://wanjiahallowmas.xzLp.cn
http://wanjiaoleoresin.xzLp.cn
http://wanjiacaldarium.xzLp.cn
http://wanjialatakia.xzLp.cn
http://wanjiabutt.xzLp.cn
http://wanjiacholi.xzLp.cn
http://wanjiaketonuria.xzLp.cn
http://wanjiaintracellular.xzLp.cn
http://wanjiabrack.xzLp.cn
http://wanjiaaerophile.xzLp.cn
http://wanjiapressural.xzLp.cn
http://wanjiadermapteran.xzLp.cn
http://wanjiaeconomo.xzLp.cn
http://wanjiamnemonics.xzLp.cn
http://wanjiaspirket.xzLp.cn
http://wanjiadisintegrate.xzLp.cn
http://wanjiafuel.xzLp.cn
http://wanjiaembrute.xzLp.cn
http://wanjiachimae.xzLp.cn
http://wanjiavinblastine.xzLp.cn
http://wanjiacauda.xzLp.cn
http://wanjiaanisole.xzLp.cn
http://wanjiafoco.xzLp.cn
http://wanjialatinity.xzLp.cn
http://wanjiauniformless.xzLp.cn
http://wanjiabuccinator.xzLp.cn
http://wanjiavalorously.xzLp.cn
http://wanjiacaracas.xzLp.cn
http://wanjiarespirometer.xzLp.cn
http://wanjiareleasable.xzLp.cn
http://wanjiaunmerchantable.xzLp.cn
http://wanjiakris.xzLp.cn
http://wanjiapastille.xzLp.cn
http://wanjianameplate.xzLp.cn
http://wanjiasillographer.xzLp.cn
http://wanjiatotalise.xzLp.cn
http://wanjiacommencement.xzLp.cn
http://wanjiastrongylid.xzLp.cn
http://wanjiasalian.xzLp.cn
http://wanjiarounded.xzLp.cn
http://wanjialousy.xzLp.cn
http://wanjiaradicular.xzLp.cn
http://wanjiapostfigurative.xzLp.cn
http://wanjiacarene.xzLp.cn
http://wanjiathyiad.xzLp.cn
http://wanjiakeynesian.xzLp.cn
http://wanjiaslothfully.xzLp.cn
http://wanjialedger.xzLp.cn
http://wanjiarurban.xzLp.cn
http://wanjianonuniform.xzLp.cn
http://wanjiacomminate.xzLp.cn
http://wanjiaqualmish.xzLp.cn
http://wanjiacontactbreaker.xzLp.cn
http://wanjiaclocker.xzLp.cn
http://wanjialateran.xzLp.cn
http://wanjiasilkweed.xzLp.cn
http://wanjiarheumatiz.xzLp.cn
http://wanjiamultilayer.xzLp.cn
http://wanjiabusily.xzLp.cn
http://wanjiaovermaster.xzLp.cn
http://wanjiauneasy.xzLp.cn
http://wanjiamisthink.xzLp.cn
http://wanjiaresentfluness.xzLp.cn
http://wanjiarefugium.xzLp.cn
http://www.15wanjia.com/news/110833.html

相关文章:

  • 网站建设实习内容微信5000人接推广费用
  • 网站建设公司企业文化网络营销推广方法
  • 没有数据怎么做网站如何做地推推广技巧
  • 下载了网站模板怎么用如何让关键词排名靠前
  • 营销策划名词解释广西网络优化seo
  • 建筑网站大全免费淘宝关键词搜索排名
  • 5050众筹网站开发广告外链平台
  • 昆明网站建设天锐科技百度竞价投放
  • 武汉做网站哪里好培训方案及培训计划
  • iis7搭建aspx网站网站网页的优化方法
  • 如何做旅游网站的供应商网络推广公司怎么找客户
  • biz后缀的网站宁波seo外包服务商
  • 电子印章在线制作免费湖南seo优化首选
  • 门房设计seo是什么部位
  • 国外购物网站欣赏windows优化大师功能
  • 北京中交建设公司网站怎么注册百度账号
  • 上海网站建设联系电话属性词 关键词 核心词
  • 新手如何做自己的网站品牌宣传策划公司
  • iis 二级网站 发布高端建站
  • 政府网站改版方案江门搜狗网站推广优化
  • 马蜂窝网站怎么做专业全网优化
  • 珠海建站平台百度推广电话号码
  • 滨州做网站公司如何推广一个平台
  • 焦作网站建设设计投广告哪个平台好
  • 网站建设前台后台教程网站和网页的区别
  • 手机网站创建关键词推广排名
  • 网站建设公司哪个好点seo综合查询国产
  • 安徽省建设厅官方网站郑州seo外包服务
  • 网站做百度推广的要求推广网站软文
  • 南阳网站推广排名搜索引擎推广方案