H5 的 canvas 绘制图形,在填充图形时,支持两种填充方式:非零环绕填充(默认)、奇偶填充。
而 zrender 没有对我们提供选择填充方式的接口,直接使用了默认填充方式,这样在某些情况下,我们绘制出来的图形可能就会不是我们想要的结果。
例如(此处例图为假设,模拟可能发生的情况):
我们想要的 实际得到的
可以看出,我们想要的是在大的图形内区域内去除两个小的区域,但是实际上只有一块区域被去除了,另一块区域仍然被填充,这就是「非零环绕填充」带来的结果。
想要解决这个问题,只有使用「奇偶填充」,可是 zrender 没有给我们提供接口,那么我们就只有修改它的源码了……
源码获取方式自行解决,可以通过 git
、npm
或其他方式都可以,这里以 npm
方式举例。
我们可以通过 npm
将 zrender
下载到本地,然后在 node_modules
中找到 zrender
目录,然后修改 src 目录以下文件:
- /graphic/Style.js:
Style.prototype
中,增加:
/**
* 'nonzero': 非零环绕规则,默认值
* 'evenodd': 奇偶环绕规则
*/
fillType: 'nonzero'
- /graphic/Path.js:
Path.prototype
中,在下面代码内:
if (hasFill) {
...
}
修改两处 path.fill(ctx);
为 path.fill(ctx, style);
3:/core/PathProxy.js
PathProxy.prototype
中,
fill: function (ctx) {
ctx && ctx.fill();
this.toStatic();
},
改为
fill: function (ctx, style) {
ctx && ctx.fill(style.fillType);
this.toStatic();
},
最后,重新编译 zrender
,在 dist 目录中就是编译后的新文件。
怎么使用
在使用的时候,我们使用 zrender
创建图形时,继承 zrender
的 Path
,在 style
属性中,设置 fillType: xxx
就行了:
/** 自定义封闭形状 */
export var CustomizeRegions = zrender.Path.extend({
type: 'Regions',
shape: {
offset: 0,
coordinates: {
inverted: false,
regions: []
}
},
style: {
stroke: '#000',
fill: 'rgba(0, 0, 255, 0.2)',
// 设置填充方式为 「奇偶填充」
fillType: 'evenodd'
},
buildPath: function (ctx, shape) {
// console.warn(ctx)
// ctx.beginPath();
// 旋转算法 >>>
// if (shape.coordinates.inverted) {
// ctx.moveTo(rect1[0], rect1[1] + offset)
// ctx.lineTo(rect1[0], rect2[1] + offset)
// ctx.lineTo(rect2[0], rect2[1] + offset)
// ctx.lineTo(rect2[0], rect1[1] + offset)
// ctx.closePath()
// }
shape.coordinates.regions.forEach(function (region, i) {
// console.info("region.length = ", region.length);
if (region.length <= 0) {
return
}
ctx.moveTo((region[0][0]), (region[0][1]) + shape.offset)
for (let i = 1; i < region.length; i++) {
ctx.lineTo((region[i][0]), (region[i][1]) + shape.offset)
}
ctx.closePath()
})
}
})
网友评论