Fix safari icons support

This commit is contained in:
Paulo Gustavo Veiga 2021-12-31 01:52:24 -08:00
parent 85f560324b
commit 6b7a7660f1
5 changed files with 50 additions and 26 deletions

View File

@ -36,7 +36,7 @@ import DragManager from './DragManager';
import RelationshipPivot from './RelationshipPivot';
import Relationship from './Relationship';
import SVGExporter from './export/SVGExporter';
import PNGExporter from './export/PNGExporter';
import BinaryImageExporter from './export/PNGExporter';
import TopicEventDispatcher, { TopicEvent } from './TopicEventDispatcher';
import TopicFeatureFactory from './TopicFeature';
@ -369,7 +369,11 @@ class Designer extends Events {
break;
}
case 'png': {
exporter = new PNGExporter(mindmap, svgElement, size.width, size.height);
exporter = new BinaryImageExporter(mindmap, svgElement, size.width, size.height, 'image/png');
break;
}
case 'jpeg': {
exporter = new BinaryImageExporter(mindmap, svgElement, size.width, size.height, 'image/jpeg');
break;
}
default:

View File

@ -2,16 +2,21 @@
import { Mindmap } from "../..";
import Exporter from "./Exporter";
import SVGExporter from "./SVGExporter";
class PNGExporter implements Exporter {
/**
* Based on https://mybyways.com/blog/convert-svg-to-png-using-your-browser
*/
class BinaryImageExporter implements Exporter {
svgElement: Element;
mindmap: Mindmap;
width: number;
height: number;
imgFormat: string;
constructor(mindmap: Mindmap, svgElement: Element, width: number, height: number) {
constructor(mindmap: Mindmap, svgElement: Element, width: number, height: number, imgFormat: 'image/png' | 'image/jpeg') {
this.svgElement = svgElement;
this.mindmap = mindmap;
this.imgFormat = imgFormat;
this.width = width;
this.height = height;
}
@ -19,19 +24,28 @@ class PNGExporter implements Exporter {
async export(): Promise<string> {
const svgExporter = new SVGExporter(this.mindmap, this.svgElement);
const svgUrl = await svgExporter.export();
// Get the device pixel ratio, falling back to 1. But, I will double the resolution to look nicer.
const dpr = (window.devicePixelRatio || 1) * 2;
// Create canvas ...
const canvas = document.createElement('canvas');
canvas.setAttribute('width', this.width.toString());
canvas.setAttribute('height', this.height.toString());
canvas.setAttribute('width', (this.width * dpr).toString() );
canvas.setAttribute('height', (this.height * dpr).toString());
// Render the image and wait for the response ...
const img = new Image();
const result = new Promise<string>((resolve, reject) => {
img.onload = () => {
canvas.getContext('2d').drawImage(img, 0, 0);
const imgDataUri = canvas.toDataURL('image/png').replace('image/png', 'octet/stream');
const ctx = canvas.getContext('2d');
// Scale for retina ...
ctx.scale(dpr, dpr);
ctx.drawImage(img, 0, 0);
const imgDataUri = canvas
.toDataURL(this.imgFormat)
.replace('image/png', 'octet/stream');
URL.revokeObjectURL(imgDataUri);
resolve(imgDataUri);
}
@ -40,4 +54,4 @@ class PNGExporter implements Exporter {
return result;
}
}
export default PNGExporter;
export default BinaryImageExporter;

View File

@ -11,13 +11,17 @@ class SVGExporter implements Exporter {
export(): Promise<string> {
// Replace all images for in-line images ...
const imagesElements: HTMLCollection = this.svgElement.getElementsByTagName('image');
let svgTxt:string = new XMLSerializer().serializeToString(this.svgElement);
let svgTxt:string = new XMLSerializer()
.serializeToString(this.svgElement);
// Are namespace declared ?. Otherwise, force the declaration ...
if(svgTxt.indexOf('xmlns:xlink=')!==-1){
svgTxt.replace('<svg ', '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
svgTxt = svgTxt.replace('<svg ', '<svg xmlns:xlink="http://www.w3.org/1999/xlink" ')
}
// Add white background. This is mainly for PNG export ...
svgTxt = svgTxt.replace('<svg ', '<svg style="background-color:white" ');
const blob = new Blob([svgTxt], { type: 'image/svg+xml' });
const result = URL.createObjectURL(blob);
return Promise.resolve(result);

View File

@ -213,20 +213,22 @@ class Menu extends IMenu {
this._addButton('export', false, false, () => {
const formatType = 'png';
designer.export(formatType).then((url) => {
// Create hidden anchor to force download ...
const anchor = document.createElement('a');
anchor.style = 'display: none';
anchor.download = `${mapId}.${formatType}`;
anchor.href = url;
document.body.appendChild(anchor);
// Trigger click ...
anchor.click();
designer.export(formatType)
.then((url) => {
// Create hidden anchor to force download ...
const anchor = document.createElement('a');
anchor.style = 'display: none';
anchor.download = `${mapId}.${formatType}`;
anchor.href = url;
document.body.appendChild(anchor);
// Clean up ...
document.body.removeChild(anchor);
});
// Trigger click ...
anchor.click();
// Clean up ...
document.body.removeChild(anchor);
});
// Create anchor element ...
});

View File

@ -3,7 +3,7 @@ import fs from 'fs';
import path from 'path';
import XMLSerializerFactory from '../../../src/components/persistence/XMLSerializerFactory';
import SVGExporter from '../../../src/components/export/SVGExporter';
import PNGExporter from '../../../src/components/export/PNGExporter';
import BinaryImageExporter from '../../../src/components/export/PNGExporter';
test('mindplot generation of simple maps', async () => {
// Load mindmap DOM ...