2019年2月20日,星期三
几个月前,我们已经开始与Electron进行实验。在工作概念验证之后,我们的目标是为Delphi开发人员尽可能多地包装Electron API。但当然不仅仅是可以使用的Electron API,您可以轻松地传输已有的代码,使其成为桌面应用程序!我们已经在之前的博文中给出了一个小小的预告片。
现在,我们想借此机会对即将推出的新TMS Web电子申请支持提供更多见解。
IDE集成
您可能已经熟悉创建TMS Web应用程序或渐进式Web应用程序。程序是相同的,创建新的Electron应用程序所需要做的就是从向导中选择TMS Web Electron Application:
它生成一个类似于TMS Web PWA应用程序的项目,但不是清单和serviceworker文件,它生成了一个主JavaScript文件,一个包文件和3个不同平台的图标。默认生成的package.json和main.js都能够创建,运行和打包应用程序,但可以通过编辑它们进一步自定义它们。也可以通过项目选项更改图标文件。
您现在可以像通常使用TMS Web应用程序一样开发应用程序。
在调试模式下按F9,项目将照常编译,然后Electron引擎启动并启动应用程序。
在构建模式方面,几乎没有差异和平台限制。在Windows 32/64位构建模式下按F9 将打包应用程序并启动它。在Linux 32/64位构建模式下按F9 将创建Linux的打包应用程序,然后可以将其移动到Linux机器上并启动。虽然添加了macOS 32/64位构建模式,但遗憾的是,目前无法从Windows机器创建打包的macOS应用程序。但好消息是一个打包的macOS 64位应用程序仍然可以通过将源文件复制到准备好的Mac计算机并运行单个命令来完成。更不用说如果你想分发一个macOS应用程序,那么建议你签名,这只能在Mac上完成。
创建照片编辑器应用程序
Electron为TMS Web应用程序提供了一种创建跨平台(Windows / macOS / Linux)桌面应用程序并使用本机操作系统调用并直接访问本地文件系统的方法。所以我们想通过创建一个基本的照片编辑器应用程序来展示它的强大功能。
为了保持这个简单,我们只允许通过CSS过滤器属性对选定的照片应用过滤器,这比在VCL中编写它更简单快捷,因为图像过滤器如模糊,对比度,灰色-scale ...不是开箱即用的VCL。作为第一步,我们在照片编辑器中添加了我们需要的所有组件。 当然,如果我们没有图像,我们就无法编辑图像。要解决这个问题,我们将使用 TWebImageControl,TElectronMainMenu和TElectronOpenDialog
。使用TElectronMainMenu,我们可以添加菜单栏,其中包含“打开”或“另存为...”等菜单项。在Open菜单项的OnClick事件中,我们可以执行TElectronOpenDialog并使用检索到的文件名从本地文件系统加载图像。
- 程序 TForm1 。Open1Click(发件人:TObject);
- 开始
- 如果是 ElectronOpenDialog1 。然后执行
- 开始
- WebImageControl1 。图片。LoadFromFile(ElectronOpenDialog1 。文件名);
- 结束;
- 结束;
有了图像,我们仍然需要一些可以应用过滤器的东西。幸运的是,TJSHTMLElement正是我们所寻找的,因为它具有样式属性。让我们在创建表单时检索我们的TWebImageControl的TJSHTMLElement。
- 程序 TForm1 。WebFormCreate(发件人:TObject);
- 开始
- FImgEl:= TJSHTMLElement(文件。的getElementById(WebImageControl1 。ElementID));
- 结束;
现在我们有了应用CSS过滤器的所有内容。更简单的解决方案是将所有过滤器存储在自己的字符串属性中,而不是在更改时添加和删除过滤器。当过滤器轨迹栏发生更改时,我们会更新给定的字符串属性,并将其与其余的过滤器字符串连接起来。作为最后一步,我们将此单个过滤字符串应用于我们的图像。
程序 TForm1 。BrightnessTBChange(发件人:TObject);
开始
FBrightnessFilter:= '亮度(' + IntToStr(BrightnessTB 。位置)+ '%)' ;
CreateFilter;
结束;
程序 TForm1 。CreateFilter;
开始
FFilter:= FBlurFilter + FBrightnessFilter + FContrastFilter + FGrayscaleFilter + FHueRotateFilter + FInvertFilter + FOpacityFilter + FSaturateFilter + FSepiaFilter;
FImgEl 。风格。setProperty('filter' ,FFilter);
结束;
使用此方法,重置滤镜也很简单,只需将单个滤镜字符串设置为基本值并将轨迹栏重置为其原始位置即可。
到目前为止,这并不复杂,我们的应用程序已经基本完成,但仍然缺少保存功能。为此,我们将使用TElectronSaveDialog,TElectronBinaryDataStream和TJSHTMLCanvasElement。
我们可以在菜单栏中添加“另存为...”菜单项,就像我们使用“打开”菜单项一样,然后在OnClick事件中,我们将逻辑写入图像保存。
- 程序 TForm1 。Save1Click(发件人:TObject);
- 开始
- 如果是 ElectronSaveDialog1 。然后执行
- 开始
- //保存图片
- 结束;
- 结束;
默认情况下,如果您尝试保存已应用过滤器的图片,则会在没有过滤器的情况下保存原始图像。更糟糕的是,每个浏览器都不支持普遍接受的方法。幸运的是Chromium支持它,它允许我们创建我们的应用程序没有任何缺点。
我们需要采取以下5个步骤:将图像检索为TJSHTMLCanvasElement,创建新的TJSHTMLCanvasElement以进行渲染,将过滤器分配给新画布的上下文,渲染图像,并将其保存到本地文件系统中的文件中。分配过滤器需要一些JavaScript,但正如您将在下面的代码中看到的那样,这对于一个好的结果来说是微不足道的。为了实现图像的实际保存,我们将使用TElectronBinaryDataStream。TElectronBinaryDataStream有一个名为Base64的属性,所以我们要做的就是将canvasUR中的dataURL分配给它,然后调用SaveToFile方法。到现在为止,代码看起来像这样:
程序 TForm1 。Save1Click(发件人:TObject);
VAR
canvas,el:TJSHTMLCanvasElement;
ctx:TJSCanvasRenderingContext2D;
bd:TElectronBinaryDataStream;
w,h:整数;
开始
如果是 ElectronSaveDialog1 。然后执行
开始
// 1:将图像作为TJSHTMLCanvasElement
EL:= TJSHTMLCanvasElement(文件。的getElementById(WebImageControl1 。ElementID));
ASM
w = el 。naturalWidth;
h = el 。naturalHeight;
结束;
// 2:创建canvas元素
帆布:= TJSHTMLCanvasElement(文件。的createElement('画布' ));
帆布。width:= w;
帆布。身高:= h;
ctx:= canvas 。getContextAs2DContext('2d' );
ASM
ctx 。填充样式= “RGBA(255 , 255 , 255 , 0.0 )”; //设置透明背景
ctx 。filter = el 。风格。过滤; // 3:添加过滤器
结束;
ctx 。fillRect(0 , 0 ,W,H);
// 4:渲染我们的形象
ctx 。的drawImage(TJSObject(EL), 0 , 0 ,W,H);
// 5:保存到文件
bd:= TElectronBinaryDataStream 。创建;
bd 。Base64:=画布。toDataURL;
bd 。的SaveToFile(ElectronSaveDialog1 。文件名);
结束;
结束;
现在,如果您看一下我们到目前为止所做的事情,您迟早会注意到即使没有图像加载到我们的应用程序中,也可以点击“另存为...”菜单项,这不是我们想要的。通过引入标志可以快速解决这个问题。
修改我们的“另存为...”菜单项后,默认情况下将其设置为禁用,我们可以在打开第一个图像后执行以下操作:
程序 TForm1 。WebFormCreate(发件人:TObject);
开始
FImgEmpty:= True; //旗
FImgEl:= TJSHTMLElement(文件。的getElementById(WebImageControl1 。ElementID));
结束;
程序 TForm1 。Open1Click(发件人:TObject);
开始
如果是 ElectronOpenDialog1 。然后执行
开始
WebImageControl1 。图片。LoadFromFile(ElectronOpenDialog1 。文件名);
如果 FImgEmpty 那么
开始
保存1 。启用:=真;
ElectronMainMenu1 。EndUpdate;
FImgEmpty:= False;
结束;
结束;
结束;
您可能想知道为什么需要TElectronMainMenu.EndUpdate调用。这是Electron的缺点,您无法动态修改菜单。每次修改菜单时,都需要将其重新分配给窗口。为了使这个过程对Delphi开发人员的问题减少,调用EndUpdate将重新创建菜单栏并将其重新分配给窗口。
通过这最后一个小小的补充,我们可以说我们已经创建了一个基本且简单的跨平台照片编辑器应用程序,它能够:
- 通过本机打开对话框打开本地文件系统映像
- 使用CSS应用过滤器
- 并将图像保存到本地文件系统通过本机保存对话框。
当然,它运行在3个主要操作系统上:使用单一源代码库的Windows,macOS和Linux! 如果这让您感到兴奋,那么我们会有更多好消息:我们的Electron PhotoEditor演示版中将提供更多功能,例如从JPEG中提取照片EXIF信息并将其显示在子窗口中。用于从JPEG文件中提取EXIF信息的现有JavaScript库
使用,在几分钟内为我们提供此功能,因为我们可以轻松地从TMS WEB Core应用程序中使用此JavaScript库。从EXIF信息中,我们可以提取拍摄照片的地理坐标。TMS WEB Core的强大功能和灵活性使我们能够使用TWebGoogleMaps组件在地图上将其可视化。再次,目标和功能在几分钟内完成,并且最少的代码行。 构建跨平台Electron应用程序支持将成为TMS WEB Core v1.2 Padua版本的一部分,很快我们将为TMS ALL-ACCESS用户提供第一个BETA !今天不要错过使用TMS WEB Core的方法
!您可以下载通常可用的试用版,继续使用您购买的独立版本或使用TMS WEB Core以及TMS ALL-ACCESS中包含的其他工具。我们的团队期待您的所有意见,反馈和功能请求,以帮助指导TMS WEB Core的发展到下一阶段!