Scribblify如何借助Node.js*和Chromium*嵌入式框架交付跨平台GUI

By Edward J. Correia

简介

对于出生于威斯康辛州的开发人员 Matt Pilz 而言,“三”是幸运数字。 Pilz 是 LinkedPIXEL 的创建者,他的创造力和勤勉连续三年赢得英特尔举办的开发人员挑战赛评委的一致好评。 近来,借助英特尔® 开发人员专区的资源,其采用 10 点触控功能和基于 Google Chrome* GUI 的 Scribblify 绘图应用在 2013 年英特尔® 应用创新竞赛 中荣获大奖。 2013 年春,Pilz 凭借一款通过手势进行控制的绘图应用 Magic Doodle Pad 在英特尔® 感知计算挑战赛上获胜。 2012 年,他凭借一款针对超极本™ 设备进行优化的动作游戏 Ballastic 脱颖而出。

如同他以往的竞赛,Scribblify(图 1)的理念首次亮相也是在竞赛上,但是实际上,Scribblify 最初是用在手持设备上。 Pilz 与其他参赛者(共 200 名)从竞赛赞助方联想收到一台联想 Horizon* 一体机 (AIO) 电脑后,对于能够将自己的涂鸦应用扩展为全尺寸屏幕感到非常兴奋。 他表示:“当了解到联想 Horizon 一体机拥有 1920 高清分辨率以及支持触控功能的超大 27 英寸屏幕时,我就发现为这款应用创建一个巨大帆布尺寸的版本将会非常有趣,这样用户便能够在聚会餐桌或其它大型平面上绘制图画。 这就是当时我的设想。” 为了实现这一设想,Pilz需要修改程序,以配合比原始版本宽 4 至 6 倍的屏幕,并接受 10 个并发触点而非 1 个的输入。

图 1: Scribblify 支持用户创建各种形式的作品,从涂鸦到严肃艺术作品。

 

Scribblify 的来源

Pilz 首次开始开发移动应用是在 2010 年,也是在这一年,他拥有了自己的第一部 Apple iPod 触控* 移动设备。 第二年,他便发布了最早版本的 Scribblify。 Pilz 回想道:“第一个接口是针对 480x320 分辨率而设计。 为了支持当时非常有限的硬件,所有的设计都非常简单。” 2011 年 1 月,Scribblify for iOS* 进入应用市场。 Pilz 表示:“事实上,它一直不断发展,每个月都有改进。” 因此,一年前他开发了面向 Android*版本

Pilz 将 Scribblify 描述为一款包含一些特殊功能的随意绘制和涂鸦程序。 他表示:“它的特色之处在于其画笔和色彩效果。” 这种画笔(图 2)由他亲自设计,集成了其他此类绘画应用中没有的纹理。 他表示:“我更愿意相信它们非常独特。”但是,他很快继续表示,Scribblify 并非要与高端绘图应用竞争。 Pilz 表示:“iPad 上的应用(如 Photoshop*)需要大量的学习。 而且,你仅有一些有限的绘图应用,包括一个圆形画笔和少数几个选项。 我对 Scribblify 的设计完全不属于这种级别,它支持各个年龄段的人拿起来就能开始使用。”

 

图 2: Scribblify 应用拥有 62 支原始画笔。

 

挑战

Pilz 的第一个主要挑战是决定使用什么技术来构建面向 Microsoft Windows* 的 Scribblify 版本。 他首先使用了 TGC 的 App Game Kit* (AGK) 作为引擎来创建 Ballastic。 他表示:“这能够帮助我创建一个粗略的原型,[但是]对于许多我想要在这款应用中加入的功能,它并无法提供。” 为了符合这次竞赛的要求,应用必须面向联想的 Aura* 多用户界面构建,且不能依赖底层操作系统的主要部分。 指南中规定,开发人员不得使用任何原生 Windows 对话框。 Pilz 举了个例子说明在与文件系统集成时遇到的挑战:“通过我的应用,用户可以轻松地浏览一个标准的文件对话框来保存其作品或打开其他图像, 但这会失去英特尔所追求的那种体验...让每个应用都像一个沙箱。”

Pilz 的解决办法是使用 Node.js*,它是一个用于构建面向 V8 的网络服务的事件驱动型服务器端 JavaScript* 框架,其中 JavaScript 引擎位于 Chrome 浏览器中。 据 Node 创建者 Ryan Dahl表示,Node 框架能够通过使用事件循环解除 I/O 的阻拦,并可促进异步文件 I/O,这要归功于内建的事件池。

Pilz 表示:“使用 Node.js 的一个主要目的是开发 web 应用,并在台式机上本地使用它们 — 无论采用何种操作系统。 用户无需必须安装 Windows;Node.js 是为整个应用提供支持的后端。” 使用名为 Node-Webkit 的框架和库,Pilz 可以通过自己使用标准 web 技术定制的接口和 gallery 系统轻松保存和加载图画文件。 应用可以在 Chromium* 嵌入式框架(CEF)上运行,它提供的能力可与Chrome 中强大的 HTML 和 JavaScript 渲染器媲美。

Scribblify 如何保存和删除图像
Scribblify 应用首次加载时,用户的公共文件目录将通过 Node.js 检索:


// Initialize Node.js file system
var fs = require('fs');

// Get User's Documents Folder (Win 7+)
var galleryPath = process.env['USERPROFILE'] + "\Documents\Scribblify\";
galleryPath = galleryPath.replace(/\/g, "/"); // Use forward slashes

// See if folder exists, otherwise create it
if(!fs.existsSync(galleryPath))
{
    fs.mkdir(galleryPath);  
}



当用户请求保存图像时,HTML5 canvas 将转换为图像数据:


var saveImg = canvas.toDataURL();

A unique filename is generated based on timestamp, and Node.js saves the image data to the system.
// Write image data buffer to file
var data = saveImg.replace(/^data:image/w+;base64,/, "");
var buf = new Buffer(data, 'base64');
var fName = galleryPath + destFilename;
fs.writeFile(fName, buf, function(err) {
    if(err)
    {
        console.log(err);
    }
});



如果用户希望将图像从 gallery 中删除,Node.js 仅需运行下列命令即可实现:


fs.unlinkSync(galleryPath + targetImg);



获取一个现有文件列表并在 gallery 中显示会稍微有些复杂,因为我还需要检查以确保检索到的文件只有 PNG 文件(不是可能存在的其他目录或其他文件)。


var fileList = fs.readdirSync(currentPath);
var result = [];
for (var i in fileList) {
    var currentFileFull = currentPath + '/' + fileList[i];
    var currentFile = fileList[i];
    var fileExt = currentFile.split(".").pop().toUpperCase();
    var stats = fs.statSync(currentFileFull);
    if (stats.isFile() && fileExt == "PNG") {
       result.push(currentFile);
    }
    else if (stats.isDirectory()) {
         // Directory instead...
    }
}



列表生成后,阵列中存储的图像路径可以使用标准的 HTML 和 JavaScript 技术加载。 这既可用于 gallery 显示,也可用于将一件特殊的作品导回 canvas。

虽然 Pilz 能够使用自己已经熟悉的技术对应用的大部分进行建模,包括使用于前端的 HTML5 原生 canvas 元素和后端上的 Node.js,该款应用最具突破性的特性是区别于普通特性。 他表示:“我在尝试 web 应用中没有大范围尝试的方式,比如使用合成的有纹理的画笔而非程序中生成的形状来创建整个创造性绘画应用。”

最初,改程序运行良好,但是不久,Pilz 发现了一个问题。 关于其新应用的响应能力,他表示:“当使用多个触点或绘制太快时,由于 canvas 元素的性能,该款应用将会滞后几秒钟,然后再继续。” 在他这次寻找解决方案的时候,他发现了 Cocos2d-x,它是一款可在 MIT 协议下使用的跨平台开源框架,该协议近来将 WebGL 支持加入其 JavaScript 分支。

借助 Cocos2d-Javascript,Pilz 能够更轻松地将其代码移植到 WebGL,他表示,它运行更加顺畅,并能得到 AIO 开发系统内视频卡的紧密支持。 Pilz 表示:“现在,Cocos2d-Javascript 使用 WebGL 将图画渲染至屏幕...而且,它能够以每秒 60 帧的速度运行。 这既优化了体验,也增加了使用的趣味性。” Scribblify 使用针对接口元素和用户交互的标准 HTML;Pilz 介绍道,它是标准 HTML 和 JavaScript 的结合,并加入了其他的引擎,包括用于后端处理的 Node.js 以及用于简化 WebGL 渲染的 Cocos2d-Javascript。

为了解决常见问题,Pilz 采用了 Stack Overflow ,它是一个面向开发专业人员和爱好者的免费问答站点。 他表示:“当我研究某个项目或遇到困难的时候,我就会去这个网站,我曾去过许多次。 它能够帮助我快速、轻松地了解其他人的建议。” 针对 Cocos2d-xNode.js,Pilz 广泛地参考了针对产品的 API;当然,他不仅在这一项目中使用了CodeProject*,多年来也在其他项目中使用过它。 他表示:“每当我想对某些编程话题进行深入调查时,我就会去那里。 他们创建了一个与竞赛相关的且非常有价值的论坛,以便能够快速地解答问题。”

此外,Pilz 还借助 Chromium 处理触控的方式以及联想 Horizon 驱动程序集找到了一个漏洞,该漏洞会导致触控无法释放,尤其在快速使用时。 他的解决方案是构建一个小型的“制衡系统”,如果错误记录了过量的触控,该系统将会发布警告。 他表示:“它将会自动将用户的作品保存到 gallery 中并提醒他们重启应用。” 然后,它将会显示将来如何阻止该问题的指南。 他表示:“[例如,]如果用户用整个手掌触碰它,它就会显示该警告:“你不可用这种方式操作,请使用指尖。” [此外,]它还会建议你重启。 在竞赛期间,我将其作为一份正式的漏洞报告提交给了 Chromium 开发人员。”


var canvas = document.getElementById('canvas');
canvas.addEventListener('touchstart', touchStartFunction, false);
canvas.addEventListener('touchend', touchEndFunction, false);
canvas.addEventListener('touchcancel', touchCancelFunction, false);
canvas.addEventListener('touchmove', touchMoveFunction, false);
canvas.addEventListener('touchleave', touchLeaveFunction, false);



hromium* 嵌入式框架(其中构建了 Google Chrome* )提供原生触控已经有一段时间,而且它易于实施。 各种形式的触控可以使用简单的事件处理程序来限制,包括touchstarttouchendtouchcanceltouchmovetouchleave

 

竞赛的时间限制以及 Pilz 正在处理的框架限制导致他延迟或放弃执行了一些 Scribblify 功能。 Pilz 表示:“我想要添加的一个重要功能是一个完整的解除和重新执行系统,但是,我并不是很熟悉如何在不影响系统的前提下来实现它。” 因此,现在我们使用一个橡皮和一个按钮来清除 canvas。 此外,他还希望再加入一些绘图模式和画笔。

调试

开发一款基于 web 的应用的优势是大部分的现代浏览器都配备了全面的调试工具,Pilz 表示,经证明,这在整个开发流程中非常有价值。

他表示:“对于我而言,可能最大的优势是 Chrome 开发人员工具支持全功能的 JavaScript 调试程序。 这能够帮助我创建断点,分步浏览代码,并从始至终监控特定变量和属性 — 尤其在遇到问题时。” 同时,Pilz 还能够分析明确的文档对象模型(DOM)元素和远程更新电子笔,从而更快地实现目标结果。 此外,Pilz 还发现联想在lenovodev.com 上提供的开发人员资源非常有价值,尤其是 Horizon 应用集成要求(需要登录)。

多用户

面向 AIO 的 Scribblify 支持 10 点并发触点,这意味着,一次最多可支持 10 个用户在 canvas 上绘图。 考虑到竞赛的时间限制,Pilz 的首要考量就是用来集成多点触控功能的容易程度。 他表示:“当我最终决定使用 HTML 5 及相关技术来开发基于 web 的应用时,我知道如果我使用已经配备了桌面多点触控支持的 web 应用,处理多点触控的复杂性将会降低。”

幸运的是,CEF 在其桌面和移动版本的产品上提供了该支持。 Pilz 表示,借助整个通过 CEF 提供动力的应用,将可更轻松地存储和检索 AIO 支持的触点的触控数据。

其它文章

更多创新

在使用 Scribblify 或观看 LinkedPIXEL 演示视频之前,你可能很难了解到其画笔的与众不同之处。 Pilz 表示:“我认为画笔是 Scribblify 最具创新性的一个方面。 所有的设计和画笔都是我的创造,每一种都有不同的属性,当你在屏幕上绘图时,这些属性能够控制外观以及运行方式。 它们非常独特。”

此外,Pilz 还对用户接口感到很骄傲,用户接口是他在六周内从头开始构建起来的。 他表示:“为了能够借助 10 点触控功能同时使用十根手指进行绘制,或者支持两个人同时在不同端绘制,我考虑提供一种创新的体验。” Pilz 表示在需要的地方提供了几种快捷方式。 他说:“我使用了几种库,如高级拾色器。 一些获得 MIT 协议的库能够加速该进程,因此我便无需浪费时间重新进行创造了。”

此外,Scribblify 还提供了一种创新的方式来挑选和混合颜色。 Pilz 表示:“当有这么多的颜色效果供你添加时,你不会只挑选基础色。 事实上,你可以将两种颜色混到一起,使用血浆色,甚至可以添加我所称的“颜色变异(color variance)”,从而能够在绘制时将光影和黑色混在一起,从而创建出更自然的插图。”

近来,Pilz 一直在努力将 Scribblify 转化为原生 Windows 8 应用,这样,它便能够通过 Windows 商店来发布,包括通过定制的联想 Windows 8 商店。 为了以最简化的方式满足要求,即将推出的 Scribblify 版本将由 Internet Explorer* 11 而非 Chromium 提供支持,而且在停止支持 Node.js 后,将使用新的方式处理文件输入/输出。 Windows 商店版 Scribblify 预计于 2014 年 4 月至 5 月发布。

关于竞赛

2013 年英特尔应用创新竞赛号召来自 Code ProjectHabrahabrThinkDigitCSDN 等领域的应用编程人员针对基于 Windows 的平板电脑和一体机电脑提交应用理念,范围包括金融、医疗、教育、游戏和娱乐行业。 胜出的理念将会获得赞助商联想提供的一个开发系统以及六周的时间将理念转化为演示应用;联想共提供了 200 台平板电脑和 300 台一体机电脑。 胜出的应用请见英特尔® 开发人员专区

大赛共有 500 个理念胜出,创建了 276 个演示应用,竞赛评选共分为 6 类,每类选出 5 个获胜者,因此共选出 30 个获胜者。 评选标准包括,每个应用演示其主机平台的功能的情况,满足其细分市场需求的情况,以及是否解决了目标最终用户的需求。 当然,获胜应用必须具备专业性,采用出色的图形,运行良好,无任何障碍,并能利用传感器(如有需要)。