Angular实现svg和png图片下载实现

我经常思考,在面临一个不确定问题时,以往的经验究竟有无辅助作用?如果把经验遗忘会产生何种程度的影响?在上下求索未果之后,如何找回曾经的感觉,恰若灵光一现?凡此种种,终是要思考总结的,这篇文章便是我的反思之作。

本篇文章会记述一些实用的svg与png之间的转换技巧并强调一种思考原则。

概述

技巧

svg和png图片转换和下载

解决chrome data url too large下载问题

解决@ViewChild未及时刷新问题

原则

永远从问题最近的地方开始分析

理解下面这些内容的前提是具备一些Angular的编程基础,要求大致处于能自定义component的水平。

假意需求

当我说“假意需求”的时候,其实是将解决方案视作眼下的需求,目的是方便理解。在这个项目中,我们需要把页面上的已经存在的svg元素转换成可下载的svg和png链接。svg是矢量图,适合打印成海报;而png清晰度有限,用作在线预览。

背景知识

下面是svg(Scalable Vector Graphics)和canvas在编程方式、技术原理、使用范围以及转换程度这4个维度上的对比和评估。这些知识是理解实现svg转换为png的基础。

编程方式

svg是矢量图形语言,canvas提供画布标签和绘制API;

svg提供各种图形,滤镜和动画。canvas只有绘制API,相对原始。

技术原理

svg是矢量图,提供了很多图形,还有完整的动画,事件机制,本身可以独立使用;

canvas基于像素,是一种HTML元素,只能通过脚本绘制。

适用范围

svg被主流浏览器和svg阅读器支持,canvas只有主流浏览器支持;

svg适用于大面积渲染区域的程序和静态文档,如google地图。canvas适合小范围图像密集型场景,如游戏。

转换程度

svg较难以转换成png或者jpeg格式的图片,不过canvas较容易。

技巧

假设主页面 app.component.html 面已经有一个component,它的内容如下:

<app-template #template></app-template>

其中 <app-template></app-template> 是一个自定义的component,它代表了一个svg文件,svg的内容存放在 template.component.html 中,而 template.component.ts 的定义如下:

// template.component.ts @Component({ selector: 'app-template', templateUrl: './template.component.html', styleUrls: ['./template.component.scss'], }) export class TemplateComponent implements OnInit { ngOnInit() { } }

当然,这个template.component需要在 app.module.ts 中声明后才能在 app.component.html 中使用。

注意, #template 是Angular5之后引入的语法,它的全称是 ,功能在于引用其所指向的DOM元素。

接下来要解决的就是如何在component中引用页面上的svg元素并将它转化成png格式的图片。

svg和png图片转换和下载

1. 获取元素

Angular中提供一种叫做 ViewChild 的注解,可以帮助我们引用到页面中的svg元素,此处就是 #template .

@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnDestroy { @ViewChild('template') template: { svgRef: ElementRef }; ngOnDestroy(): void { } }

获取svg元素的方式为 this.template.svgRef.nativeElement .

2. 图片转换

有了svg元素,接下来需要考虑的是如何对其编程。svg和html在浏览器的内存中都是以DOM树的形式存在,所以想要对svg进行编程,就得利用svg的. 比如说我们要获取 <svg> 元素中的各项属性,就需要使用 SVGSVGElement编程接口

svg转换成png并不直接,但是我们知道canvas转换成png非常简单。所以有种思路是将svg转换成canvas再转成png. canvas有个 drawImage 函数,可以将图片绘制到画布上,该函数的输入源是 HTMLImageElement 或者另外的canvas元素。

也就是说,如果我们能把svg转换成 HTMLImageElement 即 <img> ,那么上述过程就顺理成章连成一串了。

第一步是将svg元素转换成DataURL.

private toSvgDataURL(viewerSvg: SVGSVGElement): string { const svg = viewerSvg.cloneNode(true) as SVGSVGElement; svg.setAttribute('width', '600px'); const base64Data = btoa(unescape(encodeURIComponent(svg.outerHTML))); return `data:image/svg+xml;base64,${base64Data}`; }

第二步是将DataURL转换成 <img> .

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/20c74ff6e7737e77a9e39b9d613078d1.html