使用 WebRTC 实现响应式网页排版

我非常看好新兴的 Web 技术(例如 WebRTC(网络实时通信)和 WebAPI)的发展方向,因为它们使我们能够利用计算机、平板电脑和智能手机中现有的各种硬件部件来改善用户体验。使用 WebRTC 实现响应式排版正是另一个能够改善人们体验的简单概念的例子。

解决你的痛点

自从媒体查询被引入以及响应式网页设计兴起以来,我一直觉得目前的响应式网页设计方法有些不足。这些方法都是基于仅测试视口宽度和高度(当然,还有像素密度)的媒体查询,并且我们总是不得不对其余的上下文做出假设。

尽管设备制造商试图遵循 参考像素“协议”,但由于设备种类繁多,因此出现了一些(偶尔或严重的)不一致现象,这令人沮丧。开发人员不得不 构建特殊的媒体查询 来解决这个问题。通过为其设备定义参考像素大小,制造商也间接地迫使用户以某种特定方式使用每台设备。

然而,在现实中,人们使用设备的距离各不相同。到目前为止,“设备购买协议”中还没有任何条款会限制新用户只能在某个特定的阅读距离内使用该设备。

存在一系列自然的距离,例如 手腕、手掌、膝盖、桌面、墙壁(以及购物中心)距离,并且设备已经在这些不同的距离范围内使用,无论其外形尺寸如何。在过去的几年里,我一直断断续续地思考这个问题,最终得出的结论是,为了获得完美的体验,我们必须让设备感知用户的精确需求,然后调整屏幕以匹配任何给定的读者-设备关系。

跟踪用户与屏幕之间 距离的想法可能已经在业内许多人的脑海中萦绕。我知道 Mark Boulton 一直在倡导 引入传感器以获得更好的响应式体验 的理念,并且 Tim Brown 在去年秋季在莱顿举行的 InspireConf 上发表了关于 通用排版 的精彩演讲。

从本质上讲,我一直认为我们需要开始使用设备被动地收集信息,我一直关注着设备摄像头作为最有可能的组件,但从未找到任何切实可行的方法。直到最近,在我了解了 WebRTC 和 getUserMedia 之后。

WebRTC 挺身而出

WebRTC 标准和 getUserMedia API 的发明并非用于检测阅读距离——至少从它们的名字来看是这样。然而,使用 getUserMedia 捕获设备前方的用户这一可能性似乎是将该想法转化为可行方案的缺失环节。我认为,如果我能够使用 JavaScript 捕获和操作它,那么计算阅读距离将是容易的部分。至少在真正的 邻近事件 得到广泛支持之前。

互联网上的各位朋友

在我开始学习 getUserMedia API 的时候,一些开发者已经开发了自己的面部识别和/或头部跟踪解决方案,并将其发布在 Github 或他们的个人网站上。经过一些简短的测试,我选择了 Headtrackr(由 Audun Mathias Øygard 开发),因为它已经内置了我需要的所有功能。

Headtrackr 可以返回识别出的面部周围矩形的宽度和高度,以及头部到屏幕的距离。当我第一次测试它时,后者准确性较低,因此我仅坚持使用面部识别部分。简而言之,我将“面部宽度”除以视频宽度以获得面部到画布的比率,该比率已被用作根元素字体大小的乘数,或作为相应样式表的简单断点查询。请查看 响应式排版演示 以了解不同的应用。

Headtrackr 代码 解释得很好,但此演示中的所有内容都非常简单直观,即使不阅读文档也能理解如何使用它。为了演示的目的,我创建了三个自定义但相当简单的函数,这些函数使用通过 Headtrackr 收集的信息来操作 CSS(在本演练中,我们将仅使用其中的两个)。

在此阶段,跟踪性能远非完美,并且这不是生产级代码。但是,我希望它能激发你的想象力,并让你了解未来会带来什么。

DIY 响应式排版

为了清楚起见,本文中提供的代码是 最简单的版本,没有跟随面部的绿色矩形(当你前后摇晃头部时),也没有看起来很酷但完全可选的参数(每 50 毫秒更新一次)。

首先,HTML 部分

  • video 元素用于流
  • canvas 元素是魔法发生的地方(实际上,视频帧被复制到此处)

其次,JavaScript 部分设置一些变量并初始化 Headtrackr

var d = document,
    videoInput = d.getElementById('video'),
    canvasInput = d.getElementById('compare');

var htracker = new headtrackr.Tracker({
        altVideo : {
            ogv: "./media/capture5.ogv",
            mp4: "./media/capture5.mp4"
        },
        calcAngles: true,
        ui: false,
        headPosition: false,
        debug: false
    });
htracker.init(videoInput, canvasInput);
htracker.start();

到目前为止,一切顺利。

第一个函数 updateFontSize 用于更新 HTML 元素的字体大小。它也可以更新任何其他元素的字体大小,但如果你已经熟悉 基于 em 的媒体查询,那么控制 HTML 元素的字体大小非常有意义,因为它对应于浏览器内置文本缩放的工作方式(使用 Ctrl/Cmd + +/-)。

updateFontSize 函数仅接收一个参数 facetrackingEvent 事件,我们只需要 width 属性。

function updateFontSize(ev) {
    var faceWidth = ev.width,
        videoWidth = videoInput.width,
        face2canvasRatio = videoWidth/faceWidth,
        rootSize = Math.round(face2canvasRatio*10)/10 - 1.5 + 10 + 'px';
    d.getElementsByTagName('html')[0].style.fontSize = rootSize;
}

你可能已经注意到,我做了一些“手动归一化”以获得正确的基于 face2canvasRatio 的 rootSize。这远非最佳,但它将 face2canvasRatio 转换为足够合理的整数,可以用作合理的字体大小值。

第二个函数(同样没有特别有创意的名称)breakPointClass 根据 face2canvasRatio 值在 BODY 元素上设置类名。这些断点是通过观察和调整经验性地确定的,因此请随意使用你自己的断点。

function breakPointClass(ev) {
    var b = d.getElementsByTagName('body')[0],
        faceWidth = ev.width,
        videoWidth = videoInput.width,
        face2canvasRatio = videoWidth/faceWidth;
    if (face2canvasRatio > 3.2) {
        b.className = 'far';
    }
    if (face2canvasRatio < 2.2) {
        b.className = 'close';
    }
    if (face2canvasRatio >= 2.2 && face2canvasRatio <= 3.2) {
        b.className = '';
    }
}

最后,facetrackingEvent 事件的事件侦听器将事件对象(及其属性)传递给选择的函数

d.addEventListener('facetrackingEvent', function(event) {
    updateFontSize(event);
});
// or
d.addEventListener('facetrackingEvent', function(event) {
    breakPointClass(event);
});

如果你只需要初始值,可以停止跟踪器并暂停视频流以释放处理器

d.addEventListener('facetrackingEvent', function(event) {
    htracker.stop();
    updateFontSize(event);
    videoInput.pause();
});

就是这样!你做到了。请查看 完整示例

现在你已经知道如何轻松地 使用内置硬件,你可以开始将自己的想法付诸实践。

释放巨龙

很明显,除了人为地填补我们支离破碎的社会模式中的裂痕之外(没有双关语),我们还可以使用技术更直接地改善人们的生活。除了阅读人体工程学之外,还有许多其他领域几乎没有被触及,或者仅仅基于专有技术。

例如,我们可以构建和使用传感器来监控心率或血压,实时收集此类数据并将其上传到医生电脑上的患者档案中。我们可以使用设备的加速度计,不仅可以保护即将掉落在地板上的笔记本电脑中的硬盘驱动器,还可以提醒残疾人的看护人在发生突然倒塌时提供帮助。

我们已经使用像 Runkeeper 这样的应用程序来收集我们跑步时的信息,为什么不将其与特定路线和特定日期的大气压结合起来,以获得更全面的数据集呢?仅仅意识到存在影响我们日常表现的外部因素,就可以减少日常的挫折感,并带来更幸福、更健康的生活。

想法是无限的,并且随着像 Firefox OSGeeksphone 这样的新兴技术的出现,我们很快就能访问所有内置在我们随身携带的小型设备中的传感器。到那时,我们将没有借口不开发新的概念,使我们的生活变得稍微好一点。

关于 Marko Dugonjić

Marko Dugonjić 是一位来自克罗地亚韦利卡戈里察的设计师。作为 Creative Nights 的创意和用户体验总监,他为本地和国际客户改善客户的数字体验,并偶尔在国际网页设计会议上发表演讲。他创立了 FFWD.PRO,这是一个面向克罗地亚互联网专业人士的微型会议和研讨会。他最喜欢的个人项目是 Typetester,这是一个流行的在线工具,用于测试屏幕字体。他在 Twitter 上的用户名是 @markodugonjic

更多 Marko Dugonjić 的文章…

关于 Robert Nyman [荣誉编辑]

技术布道师和 Mozilla Hacks 编辑。发表关于 HTML5、JavaScript 和开放 Web 的演讲和博客文章。Robert 坚信 HTML5 和开放 Web,并且自 1999 年以来一直在从事 Web 前端开发工作——在瑞典和纽约市。他还定期在 http://robertnyman.com 上发表博客文章,并且喜欢旅行和结识新朋友。

更多 Robert Nyman [荣誉编辑] 的文章…


10 条评论

  1. Girish

    这真是太棒了。尤其是概率图!

    2013 年 2 月 14 日 07:42

    1. Robert Nyman [编辑]

      很高兴你喜欢!

      2013 年 2 月 15 日 05:05

  2. pd

    你将如何处理许多不同视力变化的人,例如近视?这个想法可能会使无障碍性倒退好几步。

    就我个人而言,我一点也不希望设备猜测我喜欢的字体大小。也就是说,也许你已经想出了一个很棒的实现,可以证明我错了。当然,祝贺你的横向思维。

    2013 年 2 月 14 日 10:46

    1. Marko Dugonjić

      实时版本只是为了娱乐。断点和加载版本才是真正的重点 :-)

      2013 年 2 月 14 日 12:48

  3. Harsha

    我希望 HTML5 能实现这一点,并且浏览器开始实施以支持它。

    2013 年 2 月 14 日 19:12

    1. Robert Nyman [编辑]

      好吧,我们正在取得进展,如 使用 getUserMedia/WebRTC 实现跨浏览器摄像头捕获 中所述。

      2013 年 2 月 15 日 05:12

    2. Marko Dugonjić

      +1 :)

      2013 年 2 月 15 日 05:15

  4. e–p

    无需 WebRTC 而是使用 Flex Box 实现响应式网页排版。
    http://etienne.pouvreau.free.fr/#fantome

    当然,只是为了好玩 :-)

    但说正经的,你的文章写得非常好。我喜欢混合使用新 Web 技术的想法。

    2013 年 2 月 15 日 08:12

  5. Sunil Singh

    非常好…!!

    2013 年 2 月 16 日 03:43

  6. Karan

    不错

    2013 年 3 月 8 日 04:20

本文评论已关闭。