1 | import { settings } from '@pixi/settings';
|
2 | import { uid } from '@pixi/utils';
|
3 | import { BaseImageResource } from './BaseImageResource.mjs';
|
4 |
|
5 | const _SVGResource = class extends BaseImageResource {
|
6 | constructor(sourceBase64, options) {
|
7 | options = options || {};
|
8 | super(settings.ADAPTER.createCanvas());
|
9 | this._width = 0;
|
10 | this._height = 0;
|
11 | this.svg = sourceBase64;
|
12 | this.scale = options.scale || 1;
|
13 | this._overrideWidth = options.width;
|
14 | this._overrideHeight = options.height;
|
15 | this._resolve = null;
|
16 | this._crossorigin = options.crossorigin;
|
17 | this._load = null;
|
18 | if (options.autoLoad !== false) {
|
19 | this.load();
|
20 | }
|
21 | }
|
22 | load() {
|
23 | if (this._load) {
|
24 | return this._load;
|
25 | }
|
26 | this._load = new Promise((resolve) => {
|
27 | this._resolve = () => {
|
28 | this.resize(this.source.width, this.source.height);
|
29 | resolve(this);
|
30 | };
|
31 | if (_SVGResource.SVG_XML.test(this.svg.trim())) {
|
32 | if (!btoa) {
|
33 | throw new Error("Your browser doesn't support base64 conversions.");
|
34 | }
|
35 | this.svg = `data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(this.svg)))}`;
|
36 | }
|
37 | this._loadSvg();
|
38 | });
|
39 | return this._load;
|
40 | }
|
41 | _loadSvg() {
|
42 | const tempImage = new Image();
|
43 | BaseImageResource.crossOrigin(tempImage, this.svg, this._crossorigin);
|
44 | tempImage.src = this.svg;
|
45 | tempImage.onerror = (event) => {
|
46 | if (!this._resolve) {
|
47 | return;
|
48 | }
|
49 | tempImage.onerror = null;
|
50 | this.onError.emit(event);
|
51 | };
|
52 | tempImage.onload = () => {
|
53 | if (!this._resolve) {
|
54 | return;
|
55 | }
|
56 | const svgWidth = tempImage.width;
|
57 | const svgHeight = tempImage.height;
|
58 | if (!svgWidth || !svgHeight) {
|
59 | throw new Error("The SVG image must have width and height defined (in pixels), canvas API needs them.");
|
60 | }
|
61 | let width = svgWidth * this.scale;
|
62 | let height = svgHeight * this.scale;
|
63 | if (this._overrideWidth || this._overrideHeight) {
|
64 | width = this._overrideWidth || this._overrideHeight / svgHeight * svgWidth;
|
65 | height = this._overrideHeight || this._overrideWidth / svgWidth * svgHeight;
|
66 | }
|
67 | width = Math.round(width);
|
68 | height = Math.round(height);
|
69 | const canvas = this.source;
|
70 | canvas.width = width;
|
71 | canvas.height = height;
|
72 | canvas._pixiId = `canvas_${uid()}`;
|
73 | canvas.getContext("2d").drawImage(tempImage, 0, 0, svgWidth, svgHeight, 0, 0, width, height);
|
74 | this._resolve();
|
75 | this._resolve = null;
|
76 | };
|
77 | }
|
78 | static getSize(svgString) {
|
79 | const sizeMatch = _SVGResource.SVG_SIZE.exec(svgString);
|
80 | const size = {};
|
81 | if (sizeMatch) {
|
82 | size[sizeMatch[1]] = Math.round(parseFloat(sizeMatch[3]));
|
83 | size[sizeMatch[5]] = Math.round(parseFloat(sizeMatch[7]));
|
84 | }
|
85 | return size;
|
86 | }
|
87 | dispose() {
|
88 | super.dispose();
|
89 | this._resolve = null;
|
90 | this._crossorigin = null;
|
91 | }
|
92 | static test(source, extension) {
|
93 | return extension === "svg" || typeof source === "string" && source.startsWith("data:image/svg+xml") || typeof source === "string" && _SVGResource.SVG_XML.test(source);
|
94 | }
|
95 | };
|
96 | let SVGResource = _SVGResource;
|
97 | SVGResource.SVG_XML = /^(<\?xml[^?]+\?>)?\s*(<!--[^(-->)]*-->)?\s*\<svg/m;
|
98 | SVGResource.SVG_SIZE = /<svg[^>]*(?:\s(width|height)=('|")(\d*(?:\.\d+)?)(?:px)?('|"))[^>]*(?:\s(width|height)=('|")(\d*(?:\.\d+)?)(?:px)?('|"))[^>]*>/i;
|
99 |
|
100 | export { SVGResource };
|
101 |
|