npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@antv/g-image-exporter

v1.0.20

Published

A image exporter for G using DOM API

Downloads

1,026

Readme

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