图片的描绘首先需要预读入这张图片,所以在代码中,应用先初始化了一个 Image 对象,然后绑定 load 事件,再读入相应的图片。一旦成功,这个对象就存放了图片的信息,可以应用 CANVAS 函数描绘出来。这里有两点需要说明,第一是 load 事件,因为图片读入是一个异步事件,所以不能按照顺序结构来,需要利用回调函数;第二是图片的缩放,在本例中,应用根据图片的宽度和实际的展现宽度进行比较,确认图片需要缩放的比例。
文字的展示主要通过 CANVAS 中的 context 对象进行设定,包括文字的字体、文字的颜色和文字的对其方向。文字的起始点是和字的底边对其的,所以在显示文字时需要留有一定的空白,否则文字会看不到。而对其方式是以 Y 轴为标准的:当居中时文字分布在 Y 轴的两边,向左时文字在 Y 轴的右边。这些都是描绘文字时需要注意的地方。
还需要注意一点的是文字的颜色和填充图像的颜色是一个属性,所以当文字和填充图像颜色不同时,要分别设定这个值。
球队描绘在这部分功能中,主要实现下面的两个关键点:绘制矩形和绘制圆弧。
绘制矩形是一个很基础的工作,但是却有几个需要注意的地方:首先在画一个独立的矩形时,最好加上 beginPath 这句话,因为只有这样,之后的路径才是一条新路径;新路径可以设定新的线条粗细、颜色和样式等等属性;然后是利用 closePath 封闭路径,这样可以显示的告诉维护者这里的代码描绘的是一个封闭的图形(不光是矩形);最后就是线条的粗细设定,如果线条的宽度是 1,那么起始点的坐标最好设定成 a+0.5(a 为整数),因为这样 CANVAS 画的线条才真正会呈现 1 的宽度。
在描绘圆弧时,需要进行一定的计算。整个圆只需要弧度从 0 到 2π就可以了,但是如果需要画的是一段圆弧就需要进行计算了。比如在实例中,圆弧的半径和圆弧两点间的距离已知,这时候就可以利用三角函数知道需要绘制弧度的起始点了。
在绘制球队时,为了描述球队主力队员的位置,需要画一个球场。在这里,代码利用了各种基本的函数,包括移动、画线、设置线条属性等等。所以利用 CANVAS 虽然功能强大,但是有时候会需要很多重复的工作。
在_drawOneMember 函数中,主要涉及了对于平移坐标轴的应用,同时也演示了文字和图形的合作:首先每个对象的基本绘制函数是相同的,只不过显示在坐标轴的起始方位不同,这个时候就可以利用平移坐标轴来统一这个过程;在具体的一个对象中,需要描绘三个元素,对象的名称、位置和综合能力,这就牵涉到如何让图形和文字更好的协作。现在 CANVAS 提供函数去获得文字的宽度,这样就可以帮助开发者对文字进行左、中或者右的对其,但是对于取得文字的高度还是一个比较复杂的过程,所以一般利用经验值去协调彼此的坐标高度。从代码中可以看到文字的颜色和填充图像的颜色是如何被分开设置的。
能力的描绘在这部分功能中,就要描述一个功能:如何画一个正五边形,然后在上面显示相应的数据。
在一个给定的矩形框内(假设高度大于宽度)画一个正五边形需要进行详细的运算,图 3 中给了一个相应的几何模型。
图 3. 正五边形从图中可以看到,为了方便计算,加入了两条红线作为辅助线。当宽度确定时,X0 的坐标是最容易获得的,为 (w/2, 0)。X1 的坐标就复杂一点,它的 Y 轴高度和 X 轴长度成一个比例,比例的值为 tan54°(这里需要一定的三角函数知识,请读者参阅相关书籍),所以 X1 的坐标为 (w, w * tan45°/2)。X2 的坐标是最复杂的,它的 X 轴坐标为 w / 2 加上正五边形边长的二分之一,那么如何求得正五边形的边长呢?刚才在求 X1 的坐标时,我们已经知道了 X1 到 X0 在 X 轴的距离,而 Y 轴距离通过计算也获得了,所以利用勾股定理就能获得正五边形的边长,它的计算结果为 w /(2 * cos36°)。X2 的 Y 轴坐标利用三角函数也可以获得,就是 w / (4 * (cos36° * tan18°))。X3 和 X4 分别和 X2、X1 对称,就不再详细描述计算结果,最后的坐标如清单 4 所示。
清单 4. 正五边形坐标x0 = w / 2, y0 = 0; x1 = w, y1 = w * tan36 / 2; x2 = w / 2 + w / 4 / cos36, y2 = w / 4 / (cos36 * tan18); x3 = w / 2 - w / 4 / cos36, y3 = w / 4 / (cos36 * tan18); x4 = 0, y4 = w * tan36 / 2;
为了描绘实际的值(图中的褐色线条),需要通过获得“原点”O 的坐标,然后通过一次函数的公式,计算获得各个点的实际坐标,详细的坐标如清单 4 所示。
清单 5. 能力点坐标ox = w / 2, oy = w / 2 * (1 / tan54 + 1 / tan72); px0 = (x0 - ox) * p0 + ox, py0 = (y0 - oy) * p0 + oy; px1 = (x1 - ox) * p1 + ox, py1 = (y1 - oy) * p1 + oy; px2 = (x2 - ox) * p2 + ox, py2 = (y2 - oy) * p2 + oy; px3 = (x3 - ox) * p3 + ox, py3 = (y3 - oy) * p3 + oy; px4 = (x4 - ox) * p4 + ox, py4 = (y4 - oy) * p4 + oy;
从描绘正五边形的过程中可以看到,利用 CANVAS 的接口绘图,虽然带来了很多的便利,但是同时也需要很多基础的数学知识(三角函数、一次函数)去完成数学建模,达到预期的绘图效果。最后文字的描述和球队描绘类似,不再赘述。
信息查看CANVAS 也和其他的 DOM 元素一样可以监听各种事件,在 CANVAS 中用户点击的具体位置会产生两个不同的坐标,分别是在 CANVAS 中的坐标 (CX, CY) 和在整个 DOM 页面中的坐标 (DX, DY)。一般来说,前者主要是为了在 CANVAS 中继续绘图,比如将一个矩形移动到新的位置;后者则是为了显示提示信息,比如在 DOM 节点中有一个显示详细信息的 DIV,那么通过这个坐标值,就可以将 DIV 设定为 absolute,显示在合适的位置上。具体的公式如清单 6 所示:
清单 6. 事件坐标公式CX = e.x; CY = e.y; DX = CX - e.target.offsetLeft + document.body.scrollTop; DY = CY - e.target.offsetTop + document.body.scrollLeft;
其中 e 是相应的触摸事件对象。可以看到影响整个 DOM 坐标的除了本身点击的位置,还有 CANVAS 相对于 DOM 的偏移量,以及整体 DOM 卷轴的位置。
结论和展望在对实例进行了详细分析后,CANVAS 强大的绘图能力一定已经被读者所了解。在熟悉它提供的不同 API 基础上,开发者还需要对相应的数学知识有足够的了解才可以更好的绘制图像,创建自身应用需要的内容。