Web 前端

修改 zrender 的图形填充方式

2021-01-07  本文已影响0人  时光觅迹

H5 的 canvas 绘制图形,在填充图形时,支持两种填充方式:非零环绕填充(默认)、奇偶填充。

而 zrender 没有对我们提供选择填充方式的接口,直接使用了默认填充方式,这样在某些情况下,我们绘制出来的图形可能就会不是我们想要的结果。

例如(此处例图为假设,模拟可能发生的情况):


我们想要的 实际得到的

可以看出,我们想要的是在大的图形内区域内去除两个小的区域,但是实际上只有一块区域被去除了,另一块区域仍然被填充,这就是「非零环绕填充」带来的结果。

想要解决这个问题,只有使用「奇偶填充」,可是 zrender 没有给我们提供接口,那么我们就只有修改它的源码了……

源码获取方式自行解决,可以通过 gitnpm 或其他方式都可以,这里以 npm 方式举例。

我们可以通过 npmzrender 下载到本地,然后在 node_modules 中找到 zrender 目录,然后修改 src 目录以下文件:

  1. /graphic/Style.js:
    Style.prototype 中,增加:
/**
 * 'nonzero': 非零环绕规则,默认值
 * 'evenodd': 奇偶环绕规则
 */
fillType: 'nonzero'
  1. /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 创建图形时,继承 zrenderPath ,在 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()
    })
  }
})
上一篇 下一篇

猜你喜欢

热点阅读