画布驱动的背景图片

程序化地为背景图片添加动画效果

用户以两种主要方式为背景图片添加动画效果:

  1. 使用 CSS 精灵在 JS 中更新 background-position
  2. 使用 .toDataURL() 的黑客攻击。

如果您已提前准备好图片,则第一种方法非常适用,但如果您的来源需要通过程序化方式生成(例如通过 <canvas>),该怎么办?第 1 个问题的解决方案是在画布上使用 .toDataURL(),并将背景设置为生成的网址:

while(1) {
    var url = canvas.toDataURL('image/jpeg');
    el.style.background = 'url(' + url + ')';
}

这存在两个问题:

  1. data: 网址会使生成的图片增加约 33% 的大小开销。
  2. 大量 DOM 触摸 (el.style)。

这两种方法都效率不高,对于始终流畅的 60fps 网站应用来说,是不可接受的。

使用 2D 画布作为背景

将画布用作背景的演示
演示

事实证明,WebKit 多年来一直有一个非标准 API,可以将画布作为背景的来源。但遗憾的是,此功能尚未发布规范

首先,请勿为返回按钮指定网址:

.bg {
    background: url(bg.png) no-repeat 50% 50%;
}

使用 -webkit-canvas(),将字符串标识符引用到画布上下文:

.canvas-bg {
    background: -webkit-canvas(animation) no-repeat 50% 50%;
}

接下来,我们需要使用特殊版本的 .getContext() 创建 2D 上下文:

var ctx = document.getCSSCanvasContext('2d', 'animation', 300, 300);

以下是 Dave Hyatt 提供的更多信息

动画

如演示中所示,我们可以重复使用 requestAnimationFrame() 来驱动动画。这非常棒,因为连接完成后,CSS 与画布元素之间的关联会保留。无需调整 DOM。

演示在 Chrome 中没有动画效果?

当前的 Chrome 稳定版渠道(版本 23)存在 crbug.com/161699,这会导致 requestAnimationFrame() 动画无法正确更新背景。此问题已在 Chrome 25(目前为 Canary 版)中得到修复。演示版也应该可以在当前的 Safari 中正常运行。

效果优势

我们说的是画布。硬件加速动画现已全面投入使用(至少在支持此功能的浏览器中是这样)。再次强调一下,无需从 JS 骚扰 DOM

将 WebGL 用作背景

请稍等片刻。这是否意味着我们可以使用 WebGL 为 CSS 背景提供动力?当然可以!WebGL 只是 Canvas 的 3D 上下文。只需将“experimental-webgl”替换为“2d”,即可解决问题。

var gl = document.getCSSCanvasContext('experimental-webgl', 'animation', 300, 150);

以下概念验证包含一个 div,其背景使用顶点着色器和片段着色器绘制:演示

其他方法

值得注意的是,Mozilla 已经推出 -moz-element() (MDN) 很长一段时间了。这属于 CSS 图片值和替换内容模块级别 4 规范的一部分,可让您创建由任意 HTML 生成的图片:视频、画布、DOM 内容等。不过,完全访问 DOM 的快照图片存在安全问题。这正是其他浏览器尚未采用该功能的主要原因。