fix: generate html image in safari (#123)

This commit is contained in:
boojack 2022-07-17 01:52:29 +08:00 committed by GitHub
parent 2a1e34fe03
commit 167e5596f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 45 deletions

View File

@ -1,34 +1,33 @@
import convertResourceToDataURL from "./convertResourceToDataURL";
const applyStyles = async (sourceElement: HTMLElement, clonedElement: HTMLElement) => {
if (!sourceElement || !clonedElement) {
return;
}
if (sourceElement.tagName === "IMG") {
try {
const url = await convertResourceToDataURL(sourceElement.getAttribute("src") ?? "");
(clonedElement as HTMLImageElement).src = url;
} catch (error) {
// do nth
}
}
const sourceStyles = window.getComputedStyle(sourceElement);
for (const item of sourceStyles) {
clonedElement.style.setProperty(item, sourceStyles.getPropertyValue(item), sourceStyles.getPropertyPriority(item));
}
for (let i = 0; i < clonedElement.childElementCount; i++) {
await applyStyles(sourceElement.children[i] as HTMLElement, clonedElement.children[i] as HTMLElement);
}
};
const getCloneStyledElement = async (element: HTMLElement) => {
const clonedElementContainer = document.createElement(element.tagName);
clonedElementContainer.innerHTML = element.innerHTML;
const applyStyles = async (sourceElement: HTMLElement, clonedElement: HTMLElement) => {
if (!sourceElement || !clonedElement) {
return;
}
const sourceStyles = window.getComputedStyle(sourceElement);
if (sourceElement.tagName === "IMG") {
try {
const url = await convertResourceToDataURL(sourceElement.getAttribute("src") ?? "");
(clonedElement as HTMLImageElement).src = url;
} catch (error) {
// do nth
}
}
for (const item of sourceStyles) {
clonedElement.style.setProperty(item, sourceStyles.getPropertyValue(item), sourceStyles.getPropertyPriority(item));
}
for (let i = 0; i < clonedElement.childElementCount; i++) {
await applyStyles(sourceElement.children[i] as HTMLElement, clonedElement.children[i] as HTMLElement);
}
};
await applyStyles(element, clonedElementContainer);
return clonedElementContainer;

View File

@ -6,6 +6,7 @@
* 2. <foreignObject>: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject
*/
import getCloneStyledElement from "./getCloneStyledElement";
import waitImageLoaded from "./waitImageLoaded";
type Options = Partial<{
backgroundColor: string;
@ -51,7 +52,6 @@ const generateSVGElement = (width: number, height: number, element: HTMLElement)
export const toSVG = async (element: HTMLElement, options?: Options) => {
const { width, height } = getElementSize(element);
const clonedElement = await getCloneStyledElement(element);
if (options?.backgroundColor) {
@ -65,11 +65,6 @@ export const toSVG = async (element: HTMLElement, options?: Options) => {
};
export const toCanvas = async (element: HTMLElement, options?: Options): Promise<HTMLCanvasElement> => {
const url = await toSVG(element, options);
const imageEl = new Image();
imageEl.src = url;
const ratio = options?.pixelRatio || 1;
const { width, height } = getElementSize(element);
@ -91,18 +86,20 @@ export const toCanvas = async (element: HTMLElement, options?: Options): Promise
context.fillRect(0, 0, canvas.width, canvas.height);
}
return new Promise((resolve) => {
imageEl.onload = () => {
context.drawImage(imageEl, 0, 0, canvas.width, canvas.height);
resolve(canvas);
};
});
const url = await toSVG(element, options);
const imageEl = new Image();
imageEl.style.zIndex = "-1";
imageEl.style.position = "absolute";
imageEl.style.top = "0";
document.body.append(imageEl);
await waitImageLoaded(imageEl, url);
context.drawImage(imageEl, 0, 0, canvas.width, canvas.height);
imageEl.remove();
return canvas;
};
const toImage = async (element: HTMLElement, options?: Options) => {
const canvas = await toCanvas(element, options);
return canvas.toDataURL();
};

View File

@ -0,0 +1,17 @@
const waitImageLoaded = (image: HTMLImageElement, url: string): Promise<void> => {
return new Promise((resolve, reject) => {
image.loading = "eager";
image.onload = () => {
// NOTE: There is image loading problem in Safari, fix it with some trick
setTimeout(() => {
resolve();
}, 200);
};
image.onerror = () => {
reject("Image load failed");
};
image.src = url;
});
};
export default waitImageLoaded;

View File

@ -63,14 +63,14 @@
@apply flex flex-row justify-start items-center w-full py-3 px-6;
> .normal-text {
@apply w-full flex flex-row justify-start items-center text-sm text-gray-500;
> .name-text {
@apply text-black ml-2;
}
@apply w-full flex flex-row justify-start items-center text-sm leading-6 text-gray-500;
> .icon-text {
@apply text-lg ml-1 mr-2;
@apply text-lg ml-1 mr-2 leading-6;
}
> .name-text {
@apply text-black ml-2 leading-6;
}
}
}