Scale animated GIFs by 50%. (#108)
This halves the dimensions of animated GIF exports, which fixes #104.pull/109/head
rodzic
674a144a92
commit
72354e65a0
|
@ -86,15 +86,31 @@ const exportPng: ImageExporter = async (svgEl, onProgress) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function drawImage(canvas: HTMLCanvasElement, dataURL: string): Promise<void> {
|
function drawImage(
|
||||||
|
canvas: HTMLCanvasElement,
|
||||||
|
dataURL: string,
|
||||||
|
scale: number
|
||||||
|
): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const img = document.createElement("img");
|
const img = document.createElement("img");
|
||||||
|
|
||||||
img.onload = () => {
|
img.onload = () => {
|
||||||
canvas.width = img.width;
|
const scaledWidth = Math.floor(img.width * scale);
|
||||||
canvas.height = img.height;
|
const scaledHeight = Math.floor(img.height * scale);
|
||||||
|
canvas.width = scaledWidth;
|
||||||
|
canvas.height = scaledHeight;
|
||||||
const ctx = getCanvasContext2D(canvas);
|
const ctx = getCanvasContext2D(canvas);
|
||||||
ctx.drawImage(img, 0, 0);
|
ctx.drawImage(
|
||||||
|
img,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
img.width,
|
||||||
|
img.height,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
scaledWidth,
|
||||||
|
scaledHeight
|
||||||
|
);
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
img.onerror = reject;
|
img.onerror = reject;
|
||||||
|
@ -107,6 +123,7 @@ function drawImage(canvas: HTMLCanvasElement, dataURL: string): Promise<void> {
|
||||||
*/
|
*/
|
||||||
async function exportGif(
|
async function exportGif(
|
||||||
animate: ExportableAnimation,
|
animate: ExportableAnimation,
|
||||||
|
scale: number,
|
||||||
svgEl: SVGSVGElement,
|
svgEl: SVGSVGElement,
|
||||||
onProgress: (value: number) => void
|
onProgress: (value: number) => void
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
|
@ -127,7 +144,7 @@ async function exportGif(
|
||||||
const animPct = i / numFrames;
|
const animPct = i / numFrames;
|
||||||
const markup = renderToStaticMarkup(render(animPct));
|
const markup = renderToStaticMarkup(render(animPct));
|
||||||
const url = getSvgUrl(markup);
|
const url = getSvgUrl(markup);
|
||||||
await drawImage(canvas, url);
|
await drawImage(canvas, url, scale);
|
||||||
gif.addFrame(canvas, { delay: msecPerFrame });
|
gif.addFrame(canvas, { delay: msecPerFrame });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,11 +165,14 @@ export type ExportableAnimation = {
|
||||||
render: AnimationRenderer;
|
render: AnimationRenderer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const DEFAULT_GIF_SCALE = 0.5;
|
||||||
|
|
||||||
export const ExportWidget: React.FC<{
|
export const ExportWidget: React.FC<{
|
||||||
svgRef: React.RefObject<SVGSVGElement>;
|
svgRef: React.RefObject<SVGSVGElement>;
|
||||||
animate?: ExportableAnimation | false;
|
animate?: ExportableAnimation | false;
|
||||||
|
gifScale?: number;
|
||||||
basename: string;
|
basename: string;
|
||||||
}> = ({ svgRef, basename, animate }) => {
|
}> = ({ svgRef, basename, animate, gifScale }) => {
|
||||||
const [progress, setProgress] = useState<number | null>(null);
|
const [progress, setProgress] = useState<number | null>(null);
|
||||||
|
|
||||||
if (progress !== null) {
|
if (progress !== null) {
|
||||||
|
@ -188,7 +208,7 @@ export const ExportWidget: React.FC<{
|
||||||
basename,
|
basename,
|
||||||
"gif",
|
"gif",
|
||||||
setProgress,
|
setProgress,
|
||||||
exportGif.bind(null, animate)
|
exportGif.bind(null, animate, gifScale || DEFAULT_GIF_SCALE)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
Ładowanie…
Reference in New Issue