不用HTML5/CSS3如何在网页上画机器猫

前段时间有人用 CSS3 技术在网页上画了一个机器猫,可以用来测试各大浏览器对 CSS3 的支持程度,不用说,HTML5 /CSS3 的时代已经逐渐来临了。HTML5/CSS3 带来了很多新的东西,比如激动人心的绘图标签 canvas 。不过,在拥抱 HTML5/CSS3 之前,也让我来复古一番,看一看在 HTML5/CSS3 之前的时代里,如果想在网页上画机器猫该怎么做。

先贴一下最终的效果图:

上面这个机器猫完全是用 div 搭出来的(一共用了 2010 个 div,今年是 2010 年嘛),用到的技术为 JavaScript + HTML4 + CSS2 ,在目前几乎所有主流浏览中都能有一致的显示,可以点击这儿查看演示

我们知道,各大主要浏览器都支持一些可用于绘图的矢量标记语言,比如 IE Only 的 VML 以及被 Firefox 等支持的 SVG,可惜的是这些矢量标记语言一直没有一个跨浏览器的统一的标准,因而一直没有得到广泛的应用,所以长期以来,Flash 技术一直是这个领域唯一的老大。不过,除此之外,也有一些程序员做了一些虽然可能没有很大实用价值但很有趣的探索,比如,如果直接用 JavaScript + DOM + CSS 在网页上画图会怎么样?

一、DOM 画图技术

2005年有一段时间,我对如何使只用 JavaScript 以及各大浏览器都支持的原生的标准技术(如 HTML / CSS)在网页上画图的问题产生了兴趣,当时我找到了一个叫 WZ_JSGraphics (今天发现这个页面已经打不开了,或许作者已经停止了维护?)的 JS 脚本,它实现了我上面提到的想法,通过 JavaScript 在网页上生成很多绝对定位的 div 来实现了网页绘画。

虽然计算机图形学已经非常成熟,但使用 div 在网页上画图(下面称之为“DOM 画图”)与传统的计算机图形学还是有所不同,传统的计算机图形学中可以利用的最小单位是一个 1px 的点,但 DOM 画图上可以利用的最小单位是一个 div ,或者说是一个矩形,这样一来,对于 DOM 画图技术来说,画一个小点的成本和画一个很大的矩形的成本几乎是一样的(横线或竖线也可以看成矩形)。这就为 DOM 画图提出了一个优化要求:如何使用尽可能少的矩形来拼成所需图形?如下图所示。

优化网格

上图显示了 DOM 画图中一段弧线的三种优化程度。最左边的那种用了最多的 div ,同时该约简的地方没有约简,具体表现为图像看起来会有锯齿或者拖泥带水;中间那种解决了约简的问题,但用的 div 还是太多了,该合并的地方没有合并;右边那种在前两者的基础上,把同一行、同一列相邻的 div 合并了起来,用了最少的 div 完成了图像的绘制。我们认为,对于 DOM 绘画来说,右边这种方案最佳。

同样地,对于填充图形(实心图形)来说,也要遵循这样的规则,尽可能少用 div 。比如下图所示的椭圆。

优化的椭圆

可以看到,上面的椭圆由许多色条组成,每一个色条即是一个 div ,这种化圆为方的灵感是从微积分中借鉴来的。

二、DrJs

2007年,有一段时间我需要在一个页面上动态地显示很多统计图表,比如柱状图、折线图、饼图等。最好的解决方案是 Flash,不过这个需求也让我再次思考如何使用 DOM 在网页上画图的问题,于是有了 DrJs 的第一个版本。

DrJs 是 Draw 和 JavaScript 两个单词的组合,名字比较普通。事实上,DrJs 几乎没有实用价值,任何一个真正严肃的或有一定规模的解决方案都不会使用它,不过我仍然花了一些时间在上面,一方面是因为好玩,另一方面也是想看看自己能不能真的写出这样一个东西出来。这个工作时断时续,直到2008年年中,才完成现在使用的这个版本。

DrJs 参考了 WZ_JSGraphics 的部分思想,但代码完全是自己全新实现的,某些方面比 WZ_JSGraphics 更易用一些。WZ_JSGraphics 在速度方面做了很多工作,貌似还专门针对 IE 做过一些特别的优化,因此速度上比 DrJs 要快,不过它的各种绘图方法是独立的,用户只能使用它提供的那几种绘图方法,没法自行添加新的绘图函数。DrJs 采用了另外一种设计方法,它的核心非常简单,就是根据一个或多个方程(组)以及给定的 x 的取值范围,计算出对应的 y 的值,做连续性及合并相邻矩形处理之后,再把它转化为 div 添加到页面上。

在 DrJs 内部,所有的绘图(无论是直线、折线、椭圆、饼图)的背后都是一个个的方程或方程组,即:y = f(x), x ∈ [a, b] 。用户可以通过添加自定义方程(组)的方法来扩展 DrJs 的功能,因此原则上,DrJs 可以在有限精度下实现任意复杂图形的绘制。当然,我内置的方程组并不多,只有常用的点、直线、折线、多边形、矩形、椭圆、扇形、字符串、图片、方框,其中扇形的实现最为复杂。另外还预设了直方图、饼图、折线图三种统计图表。

三、Div 版机器猫

有 DrJs 作基础,用 div 在网页上堆图像就简单多了,比如说用它来画一个机器猫。应该说,机器猫是一个非常适合用程序来画的形象,因为它主要由圆(包括椭圆、圆弧)、简单的多边形以及直线组成。具体的绘制过程就不详述了,在演示页面右键查看源代码就能看到,简单来说就是使用 DrJs 在指定的地方做画圆画线等操作,最后组成一个机器猫的形象。

第一次画完之时一共用了 2007 个 div,这时我想,既然今年是 2010 年,就再多凑出 3 个 div 来吧,于是改了一些参数,现在大家看到的机器猫刚好使用了 2010 个 div。

可以看到,这个机器猫的形象很简单,有点象素画的风格,而且没有阴影,除了鼻子外也没有高光,看起来没有立体感。虽然我可以继续添加细节,为它加上阴影、高光,让它看起来更加生动,但即使是现在这么一个简单的形象,也使用了 2010 个 div 才堆出来,要继续细化下去需要更多的 div(当然,如果仅仅只是想画出这样一幅机器猫的图像,而不考虑制作一个较为通用的 DOM 画图工具,一定是可以用更少的 div 实现的),所以,就到这儿为止吧。

使用 DOM 方法当然也是能实现网页绘画的,但这是一种典型的滥用,DOM 并非为画图而设计的,使用它来画图虽然技术上可行,但成本太高。不过,强大的 HTML5/CSS3 已经到来了,对于前端开发来说,在网页上绘画也有了更多更优雅更高效的方法。对 DOM 绘画的复古回忆就进行到这儿了,接下来让我们一起探索 HTML5/CSS3 的时代吧!

最后,再贴一下演示地址:https://oldj.net/static/drjs/doraemon.html

32 Replies to “不用HTML5/CSS3如何在网页上画机器猫”

  1. IE8说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 340 毫秒。关于oldj.net © 2010

  2. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 330 毫秒。Gentoo Linux x86-64 + Firefox 3.6.9Core2Dou T5450 + 4G + 8400M GS + 1280×1024*24bit + nvidia-drivers-256.53速度不错,就是不知道内存使用量如何。

  3. 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 81 毫秒。chrome!

  4. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 72 毫秒。Opera 10.70

  5. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 106 毫秒。safari 5.0.2

  6. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 70 毫秒。chrome 6.0.472.63

  7. opera 10.53说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 68 毫秒。

  8. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 51 毫秒。opera 10.63

  9. 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 59 毫秒。

  10. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 495 毫秒。firefox 3.6.8

  11. 说明: 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 105 毫秒。opera 11.01 T2330

  12. 很想学习js代码规范,我的意思是 为什么要用这样的方式来书写,整个思想是什么?BTW 上面的图形完全使用 div 拼接而成,共使用了 2010 个 div ,耗时 98 毫秒。safari 5.1.2

评论已关闭。