1.0.15 • Published 8 months ago

@antv/g-image-exporter v1.0.15

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

g-plugin-image-exporter

一些图表库提供了保存内容到图片的功能,下图来自 Highcharts

为此我们提供了 g-image-exporter,它支持选定画布区域,导出指定格式的 dataURL 或保存成图片等功能,示例。其中部分功能依赖 DOM API,对于非浏览器运行环境,请参考 画布的特殊运行平台适配。例如下载功能需要通过 document.createElement('a') 实现,非浏览器环境需要自行传入 document 对象。

配置项

创建时可以指定以下配置项,其中 canvas 为必填项,将画布传入:

import { ImageExporter } from '@antv/g-image-exporter';

const exporter = new ImageExporter({
    canvas, // 传入画布
    defaultFilename: 'my-default-filename',
});

defaultFilename

在调用 downloadImage 保存并下载图片时,如果没有指定文件名,将使用该配置项的值作为默认文件名。

API

toCanvas

该方法用以将指定区域的画布内容绘制到额外的 HTMLCanvasElement 中,随后可以根据需要进一步加工,例如添加背景色、水印等。

完整方法签名如下,该方法为异步

toCanvas(options: Partial<CanvasOptions> = {}): Promise<HTMLCanvasElement>;

interface CanvasOptions {
  clippingRegion: Rectangle;
  beforeDrawImage: (context: CanvasRenderingContext2D) => void;
  afterDrawImage: (context: CanvasRenderingContext2D) => void;
}

各配置项含义如下:

  • clippingRegion 画布裁剪区域,用矩形表示
  • beforeDrawImage 在绘制画布内容前调用,适合绘制背景颜色
  • afterDrawImage 在绘制画布内容后调用,适合绘制水印
  • ignoreElements 在导出 HTML 内容时,如何判断容器内一个 HTMLElement 是否被忽略

在该示例中,我们添加了背景色和水印,通过传入的 CanvasRenderingContext2D 可以调用 Canvas2D API 进行绘制:

import { Rectangle } from '@antv/g';

const canvas = await exporter.toCanvas({
    // 忽略 stats.js lil-gui 等在容器内添加的 DOM 元素
    ignoreElements: (element) => {
        return [gui.domElement, stats.dom].indexOf(element) > -1;
    },
    // 指定导出画布区域
    clippingRegion: new Rectangle(
        clippingRegionX,
        clippingRegionY,
        clippingRegionWidth,
        clippingRegionHeight,
    ),
    beforeDrawImage: (context) => {
        // 绘制背景色
        context.fillStyle = backgroundColor;
        context.fillRect(0, 0, clippingRegionWidth, clippingRegionHeight);
    },
    afterDrawImage: (context) => {
        // 绘制水印
        context.font = '24px Times New Roman';
        context.fillStyle = '#FFC82C';
        context.fillText('AntV', 20, 20);
    },
});

注意裁剪区域使用的是 Rectangle 而非 Rect 图形。它的构造函数中包含 x/y/width/height 四个参数。它相对于视口坐标系下,即对于一个 400 x 400 的画布,裁剪的最大宽高就是 400。

在导出 HTML 时,默认会导出容器内的全部 HTMLElement,但有时有些元素并不是我们想导出的,此时可以使用 ignoreElements: (element: Element): boolean; 方法进行过滤。例如该示例中容器内还有 stats.js 和 lil-gui 添加的 DOM 元素,我们并不希望导出,此时可以:

ignoreElements: (element) => {
    return [gui.domElement, stats.dom].indexOf(element) > -1;
},

toSVGDataURL

有时我们想导出矢量图。不同于 toCanvas 对于所有渲染器都支持,只有 g-svg 渲染器支持生成 SVG 类型的 dataURL,如果选择了其他渲染器,将返回 Promise<undefined>

方法签名如下:

toSVGDataURL(): Promise<string>;

内部使用 XMLSerializer 实现,将 SVGElement 序列化成 XML 字符串。

downloadImage

触发浏览器下载行为,可以将 导出的 dataURL 传入并指定保存的文件名。

完整方法签名如下:

downloadImage(options: DownloadImageOptions): void;

interface DownloadImageOptions {
  dataURL: string;
  name?: string;
}

在该示例中,点击按钮立即开始下载图片,如果选择了 image/png 格式,最终保存成 my-file.png 文件:

const canvas = await exporter.toCanvas();
const dataURL = canvas.toDataURL();

// 触发下载
exporter.downloadImage({
    dataURL,
    name: 'my-file',
});

下载行为是通过使用 document创建 HTMLAnchorElement 并触发它的默认点击行为实现的。

导出 dataURL

通过 toCanvas 我们得到了包含画布内容的 HTMLCanvasElement,使用其原生方法 toDataURL 就可以得到 dataURL:

const canvas = await exporter.toCanvas();
const dataURL = canvas.toDataURL(); // data:...

toDataURL 方法中可以指定图片格式,默认为 image/png,以及图片质量,详见参数

导出 ImageData

HTMLCanvasElement 同样提供了 getImageData 方法用于获取指定区域的像素数据:

const canvas = await exporter.toCanvas();
const imageData = canvas.getImageData(50, 50, 100, 100); // ImageData { width: 100, height: 100, data: Uint8ClampedArray[40000] }

导出 PDF

如果我们还想在前端根据图片生成 PDF,可以参考:https://github.com/parallax/jsPDF

注意事项

导出图片的物理尺寸

导出图片的物理尺寸已经包含了 resolution,即对于指定了宽高 400 x 400 的画布,如果当前环境的 devicePixelRatio 为 2,将生成 800 x 800 的图片。

可以导出 HTML 吗?

可以,如果画布中包含 HTML,目前不同的渲染器实现如下:

在该示例中,左上角 Tooltip 就是一个 HTML。

为何 toCanvas 为异步方法?

HTMLCanvasElement 的原生方法 toDataURL 的确是一个同步方法。

但由于 WebGL / Canvaskit 使用双缓冲机制,拥有绘制 Buffer 和展示 Buffer。好处是相比每一帧都拷贝绘制 Buffer 的内容到展示 Buffer,直接交换效率更高。因此在创建 WebGL 上下文时我们关闭了 preserveDrawingBuffer,但需要确保调用 toDataURL 时渲染没有被清除(调用 gl.clear()),这会导致该行为变成异步,等待下一次渲染 tick 时才能获取内容。

另外在导出 HTML 内容时,使用 html2canvas 提供的导出方法同样也是一个异步操作。

如何导出画布视口之外的图形?

我们提供的导出方法都只针对画布视口范围,即使是裁剪也是相对视口坐标系下。因此如果想导出视口之外的图形,可以使用相机 API 在不改变场景结构的前提下改变视口范围,例如通过 setZoom 进行缩放,让视口内容纳更多图形。

toDataURL polyfill

HTMLCanvasElement 的原生方法 toDataURL 有可能在某些古早浏览器上不支持,此时可以使用 polyfill: https://stackoverflow.com/a/47148969

1.0.15

8 months ago

1.0.14

9 months ago

1.0.13

9 months ago

1.0.12

9 months ago

1.0.11

9 months ago

1.0.11-alpha.0

9 months ago

1.0.10

10 months ago

1.0.9

11 months ago

1.0.8

11 months ago

1.0.7

12 months ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago

0.7.24

1 year ago

0.7.23

1 year ago

0.7.22-next.20

1 year ago

0.7.22-next.18

1 year ago

0.7.22-next.19

1 year ago

0.7.22-next.17

1 year ago

0.7.22-next.16

1 year ago

0.7.22-next.15

1 year ago

0.7.22-next.14

1 year ago

0.7.22

1 year ago

0.7.22-next.13

1 year ago

0.7.22-next.11

1 year ago

0.7.22-next.12

1 year ago

0.7.22-next.10

1 year ago

0.7.22-next.9

1 year ago

0.7.22-next.8

1 year ago

0.7.22-next.7

1 year ago

0.7.22-next.1

1 year ago

0.7.22-next.2

1 year ago

0.7.22-next.3

1 year ago

0.7.22-next.4

1 year ago

0.7.22-next.6

1 year ago

0.7.22-next.0

1 year ago

0.7.21

2 years ago

0.7.20

2 years ago

0.7.19

2 years ago

0.7.18

2 years ago

0.7.17

2 years ago

0.7.16

2 years ago

0.7.2

2 years ago

0.7.4

2 years ago

0.7.3

2 years ago

0.7.11

2 years ago

0.7.10

2 years ago

0.7.13

2 years ago

0.7.12

2 years ago

0.7.6

2 years ago

0.7.5

2 years ago

0.7.8

2 years ago

0.7.7

2 years ago

0.7.15

2 years ago

0.7.14

2 years ago

0.7.1

2 years ago

0.7.0

2 years ago

0.6.0

2 years ago

0.6.0-beta.1

2 years ago

0.6.0-alpha.1

2 years ago

0.5.50

2 years ago

0.5.49

2 years ago

0.5.47

2 years ago

0.5.48

2 years ago

0.5.46

2 years ago

0.5.43

2 years ago

0.5.44

2 years ago

0.5.41

2 years ago

0.5.42

2 years ago

0.5.40

2 years ago

0.5.45

2 years ago

0.5.39

2 years ago

0.5.38

2 years ago

0.5.36

3 years ago

0.5.37

2 years ago

0.5.35

3 years ago

0.5.19

3 years ago

0.5.32

3 years ago

0.5.33

3 years ago

0.5.30

3 years ago

0.5.31

3 years ago

0.5.34

3 years ago

0.5.21

3 years ago

0.5.22

3 years ago

0.5.20

3 years ago

0.5.29

3 years ago

0.5.27

3 years ago

0.5.28

3 years ago

0.5.25

3 years ago

0.5.26

3 years ago

0.5.23

3 years ago

0.5.24

3 years ago

0.5.18

3 years ago

0.5.10

3 years ago

0.5.11

3 years ago

0.5.8

3 years ago

0.5.7

3 years ago

0.5.9

3 years ago

0.5.16

3 years ago

0.5.17

3 years ago

0.5.14

3 years ago

0.5.15

3 years ago

0.5.12

3 years ago

0.5.13

3 years ago

0.5.4

3 years ago

0.5.3

3 years ago

0.5.6

3 years ago

0.5.5

3 years ago

0.5.2

3 years ago

0.5.1

3 years ago

0.5.0

3 years ago

0.4.3

3 years ago

0.4.2

3 years ago

0.4.1

3 years ago

0.4.0

3 years ago

0.4.0-alpha.0

3 years ago

0.3.3

3 years ago

0.3.2

3 years ago

0.3.1

3 years ago

0.3.0

3 years ago

0.2.0

3 years ago

0.1.1

3 years ago

0.1.0

3 years ago

0.0.2

3 years ago