mirror of
https://github.com/niklasvh/html2canvas.git
synced 2023-08-10 21:13:10 +03:00
Fix SVG images
This commit is contained in:
parent
2d03b6e8a2
commit
357a9a029f
@ -4,39 +4,47 @@ import {serializeSvg, deserializeSvg} from '../../core/features';
|
||||
|
||||
export class ImageElementContainer extends ElementContainer {
|
||||
src: string;
|
||||
intrinsicWidth: number;
|
||||
intrinsicHeight: number;
|
||||
intrinsicWidth: number = 0;
|
||||
intrinsicHeight: number = 0;
|
||||
isSVG: boolean;
|
||||
|
||||
private static INLINE_SVG = /^data:image\/svg\+xml/i;
|
||||
private static SVG = /\.svg$/i;
|
||||
private static INLINED_SVG = /^data:image\/svg\+xml/i;
|
||||
private static IS_FIRE_FOX = /firefox/i.test(navigator?.userAgent);
|
||||
|
||||
constructor(context: Context, img: HTMLImageElement) {
|
||||
super(context, img);
|
||||
this.src = img.currentSrc || img.src;
|
||||
this.intrinsicWidth = img.naturalWidth;
|
||||
this.intrinsicHeight = img.naturalHeight;
|
||||
this.update();
|
||||
this.isSVG = this.isSvg() || this.isInlinedSvg();
|
||||
this.context.cache.addImage(this.src);
|
||||
}
|
||||
|
||||
private update() {
|
||||
if (!this.intrinsicWidth || !this.intrinsicHeight || ImageElementContainer.IS_FIRE_FOX) {
|
||||
if (ImageElementContainer.INLINE_SVG.test(this.src)) {
|
||||
const [, inlinedSvg] = this.src.split(',');
|
||||
const svgElement = deserializeSvg(inlinedSvg);
|
||||
private isInlinedSvg = () => ImageElementContainer.INLINED_SVG.test(this.src);
|
||||
private isSvg = () => ImageElementContainer.SVG.test(this.src);
|
||||
|
||||
const {
|
||||
width: {baseVal: widthBaseVal},
|
||||
height: {baseVal: heightBaseVal}
|
||||
} = svgElement;
|
||||
public setup(img: HTMLImageElement) {
|
||||
if (this.isSvg()) return;
|
||||
|
||||
if (this.isInlinedSvg()) {
|
||||
const [, inlinedSvg] = this.src.split(',');
|
||||
const svgElement = deserializeSvg(inlinedSvg);
|
||||
const {
|
||||
width: {baseVal: widthBaseVal},
|
||||
height: {baseVal: heightBaseVal}
|
||||
} = svgElement;
|
||||
|
||||
if (ImageElementContainer.IS_FIRE_FOX) {
|
||||
widthBaseVal.valueAsString = widthBaseVal.value.toString();
|
||||
heightBaseVal.valueAsString = heightBaseVal.value.toString();
|
||||
this.src = serializeSvg(svgElement, 'base64');
|
||||
|
||||
this.intrinsicWidth = widthBaseVal.value;
|
||||
this.intrinsicHeight = heightBaseVal.value;
|
||||
return;
|
||||
img.src = serializeSvg(svgElement, 'base64');
|
||||
}
|
||||
|
||||
this.intrinsicWidth = widthBaseVal.value;
|
||||
this.intrinsicHeight = heightBaseVal.value;
|
||||
return;
|
||||
}
|
||||
|
||||
this.intrinsicWidth = img.naturalWidth;
|
||||
this.intrinsicHeight = img.naturalHeight;
|
||||
}
|
||||
}
|
||||
|
@ -270,24 +270,35 @@ export class CanvasRenderer extends Renderer {
|
||||
curves: BoundCurves,
|
||||
image: HTMLImageElement | HTMLCanvasElement
|
||||
): void {
|
||||
if (image && container.intrinsicWidth > 0 && container.intrinsicHeight > 0) {
|
||||
const box = contentBox(container);
|
||||
const path = calculatePaddingBoxPath(curves);
|
||||
this.path(path);
|
||||
this.ctx.save();
|
||||
this.ctx.clip();
|
||||
this.ctx.drawImage(
|
||||
image,
|
||||
0,
|
||||
0,
|
||||
container.intrinsicWidth,
|
||||
container.intrinsicHeight,
|
||||
box.left,
|
||||
box.top,
|
||||
box.width,
|
||||
box.height
|
||||
);
|
||||
this.ctx.restore();
|
||||
if (image) {
|
||||
const isContainerWSizes = container.intrinsicWidth > 0 && container.intrinsicHeight > 0;
|
||||
const isSVGContainer =
|
||||
container instanceof SVGElementContainer ||
|
||||
(container instanceof ImageElementContainer && container.isSVG);
|
||||
if (isContainerWSizes || isSVGContainer) {
|
||||
const box = contentBox(container);
|
||||
const path = calculatePaddingBoxPath(curves);
|
||||
this.path(path);
|
||||
this.ctx.save();
|
||||
this.ctx.clip();
|
||||
if (isContainerWSizes) {
|
||||
this.ctx.drawImage(
|
||||
image,
|
||||
0,
|
||||
0,
|
||||
container.intrinsicWidth,
|
||||
container.intrinsicHeight,
|
||||
box.left,
|
||||
box.top,
|
||||
box.width,
|
||||
box.height
|
||||
);
|
||||
} else {
|
||||
// As usual it won't work in FF. https://bugzilla.mozilla.org/show_bug.cgi?id=700533
|
||||
this.ctx.drawImage(image, box.left, box.top, box.width, box.height);
|
||||
}
|
||||
this.ctx.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,6 +314,7 @@ export class CanvasRenderer extends Renderer {
|
||||
if (container instanceof ImageElementContainer) {
|
||||
try {
|
||||
const image = await this.context.cache.match(container.src);
|
||||
container.setup(image);
|
||||
this.renderReplacedElement(container, curves, image);
|
||||
} catch (e) {
|
||||
this.context.logger.error(`Error loading image ${container.src}`);
|
||||
|
Loading…
Reference in New Issue
Block a user