Revert "Set scale for export images ()" ()

This reverts commit 82f559f826.
pull/423/head
Timur Khazamov committed by GitHub
parent 82f559f826
commit d603921234
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -44,9 +44,3 @@
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap; flex-wrap: wrap;
} }
.ExportDialog__scales {
display: flex;
align-items: baseline;
justify-content: flex-end;
}

@ -18,11 +18,6 @@ const probablySupportsClipboard =
"write" in navigator.clipboard && "write" in navigator.clipboard &&
"ClipboardItem" in window; "ClipboardItem" in window;
const scales = [1, 2, 3];
const defaultScale = scales.includes(devicePixelRatio) ? devicePixelRatio : 1;
type ExportCB = (elements: readonly ExcalidrawElement[], scale: number) => void;
export function ExportDialog({ export function ExportDialog({
elements, elements,
appState, appState,
@ -37,12 +32,11 @@ export function ExportDialog({
exportPadding?: number; exportPadding?: number;
actionManager: ActionsManagerInterface; actionManager: ActionsManagerInterface;
syncActionResult: UpdaterFn; syncActionResult: UpdaterFn;
onExportToPng: ExportCB; onExportToPng(elements: readonly ExcalidrawElement[]): void;
onExportToClipboard: ExportCB; onExportToClipboard(elements: readonly ExcalidrawElement[]): void;
}) { }) {
const someElementIsSelected = elements.some(element => element.isSelected); const someElementIsSelected = elements.some(element => element.isSelected);
const [modalIsShown, setModalIsShown] = useState(false); const [modalIsShown, setModalIsShown] = useState(false);
const [scale, setScale] = useState(defaultScale);
const [exportSelected, setExportSelected] = useState(someElementIsSelected); const [exportSelected, setExportSelected] = useState(someElementIsSelected);
const previeRef = useRef<HTMLDivElement>(null); const previeRef = useRef<HTMLDivElement>(null);
const { exportBackground, viewBackgroundColor } = appState; const { exportBackground, viewBackgroundColor } = appState;
@ -60,8 +54,7 @@ export function ExportDialog({
const canvas = getExportCanvasPreview(exportedElements, { const canvas = getExportCanvasPreview(exportedElements, {
exportBackground, exportBackground,
viewBackgroundColor, viewBackgroundColor,
exportPadding, exportPadding
scale
}); });
previewNode?.appendChild(canvas); previewNode?.appendChild(canvas);
return () => { return () => {
@ -72,8 +65,7 @@ export function ExportDialog({
exportedElements, exportedElements,
exportBackground, exportBackground,
exportPadding, exportPadding,
viewBackgroundColor, viewBackgroundColor
scale
]); ]);
function handleClose() { function handleClose() {
@ -106,7 +98,7 @@ export function ExportDialog({
icon={downloadFile} icon={downloadFile}
title="Export to PNG" title="Export to PNG"
aria-label="Export to PNG" aria-label="Export to PNG"
onClick={() => onExportToPng(exportedElements, scale)} onClick={() => onExportToPng(exportedElements)}
/> />
{probablySupportsClipboard && ( {probablySupportsClipboard && (
@ -115,9 +107,7 @@ export function ExportDialog({
icon={clipboard} icon={clipboard}
title="Copy to clipboard" title="Copy to clipboard"
aria-label="Copy to clipboard" aria-label="Copy to clipboard"
onClick={() => onClick={() => onExportToClipboard(exportedElements)}
onExportToClipboard(exportedElements, scale)
}
/> />
)} )}
</Stack.Row> </Stack.Row>
@ -129,21 +119,6 @@ export function ExportDialog({
syncActionResult syncActionResult
)} )}
<Stack.Col gap={1}> <Stack.Col gap={1}>
<div className="ExportDialog__scales">
<Stack.Row gap={1} align="baseline">
{scales.map(s => (
<ToolIcon
size="s"
type="radio"
icon={"x" + s}
name="export-canvas-scale"
id="export-canvas-scale"
checked={scale === s}
onChange={() => setScale(s)}
/>
))}
</Stack.Row>
</div>
{actionManager.renderAction( {actionManager.renderAction(
"changeExportBackground", "changeExportBackground",
elements, elements,

@ -5,7 +5,7 @@ import React from "react";
type StackProps = { type StackProps = {
children: React.ReactNode; children: React.ReactNode;
gap?: number; gap?: number;
align?: "start" | "center" | "end" | "baseline"; align?: "start" | "center" | "end";
}; };
function RowStack({ children, gap, align }: StackProps) { function RowStack({ children, gap, align }: StackProps) {

@ -20,12 +20,6 @@
} }
} }
.ToolIcon_size_s .ToolIcon__icon {
width: 25px;
height: 25px;
font-size: 0.8em;
}
.ToolIcon_type_button { .ToolIcon_type_button {
padding: 0; padding: 0;
border: none; border: none;

@ -2,8 +2,6 @@ import "./ToolIcon.scss";
import React from "react"; import React from "react";
type ToolIconSize = "s" | "m";
type ToolIconProps = type ToolIconProps =
| { | {
type: "button"; type: "button";
@ -13,7 +11,6 @@ type ToolIconProps =
name?: string; name?: string;
id?: string; id?: string;
onClick?(): void; onClick?(): void;
size?: ToolIconSize;
} }
| { | {
type: "radio"; type: "radio";
@ -23,17 +20,12 @@ type ToolIconProps =
id?: string; id?: string;
checked: boolean; checked: boolean;
onChange?(): void; onChange?(): void;
size?: ToolIconSize;
}; };
const DEFAULT_SIZE: ToolIconSize = "m";
export function ToolIcon(props: ToolIconProps) { export function ToolIcon(props: ToolIconProps) {
const sizeCn = `ToolIcon_size_${props.size || DEFAULT_SIZE}`;
if (props.type === "button") if (props.type === "button")
return ( return (
<label className={`ToolIcon ${sizeCn}`} title={props.title}> <label className="ToolIcon" title={props.title}>
<button <button
className="ToolIcon_type_button" className="ToolIcon_type_button"
aria-label={props["aria-label"]} aria-label={props["aria-label"]}
@ -46,7 +38,7 @@ export function ToolIcon(props: ToolIconProps) {
); );
return ( return (
<label className={`ToolIcon ${sizeCn}`} title={props.title}> <label className="ToolIcon" title={props.title}>
<input <input
className="ToolIcon_type_radio" className="ToolIcon_type_radio"
type="radio" type="radio"

@ -478,23 +478,18 @@ export class App extends React.Component<{}, AppState> {
appState={this.state} appState={this.state}
actionManager={this.actionManager} actionManager={this.actionManager}
syncActionResult={this.syncActionResult} syncActionResult={this.syncActionResult}
onExportToPng={(exportedElements, scale) => { onExportToPng={exportedElements => {
if (this.canvas) if (this.canvas)
exportCanvas("png", exportedElements, this.canvas, { exportCanvas("png", exportedElements, this.canvas, this.state);
exportBackground: this.state.exportBackground,
name: this.state.name,
viewBackgroundColor: this.state.viewBackgroundColor,
scale
});
}} }}
onExportToClipboard={(exportedElements, scale) => { onExportToClipboard={exportedElements => {
if (this.canvas) if (this.canvas)
exportCanvas("clipboard", exportedElements, this.canvas, { exportCanvas(
exportBackground: this.state.exportBackground, "clipboard",
name: this.state.name, exportedElements,
viewBackgroundColor: this.state.viewBackgroundColor, this.canvas,
scale this.state
}); );
}} }}
/> />
{this.actionManager.renderAction( {this.actionManager.renderAction(

@ -174,12 +174,10 @@ export function getExportCanvasPreview(
{ {
exportBackground, exportBackground,
exportPadding = 10, exportPadding = 10,
viewBackgroundColor, viewBackgroundColor
scale = 1
}: { }: {
exportBackground: boolean; exportBackground: boolean;
exportPadding?: number; exportPadding?: number;
scale?: number;
viewBackgroundColor: string; viewBackgroundColor: string;
} }
) { ) {
@ -202,13 +200,8 @@ export function getExportCanvasPreview(
} }
const tempCanvas = document.createElement("canvas"); const tempCanvas = document.createElement("canvas");
const width = distance(subCanvasX1, subCanvasX2) + exportPadding * 2; tempCanvas.width = distance(subCanvasX1, subCanvasX2) + exportPadding * 2;
const height = distance(subCanvasY1, subCanvasY2) + exportPadding * 2; tempCanvas.height = distance(subCanvasY1, subCanvasY2) + exportPadding * 2;
tempCanvas.style.width = width + "px";
tempCanvas.style.height = height + "px";
tempCanvas.width = width * scale;
tempCanvas.height = height * scale;
tempCanvas.getContext("2d")?.scale(scale, scale);
renderScene( renderScene(
elements, elements,
@ -237,27 +230,58 @@ export async function exportCanvas(
exportBackground, exportBackground,
exportPadding = 10, exportPadding = 10,
viewBackgroundColor, viewBackgroundColor,
name, name
scale = 1
}: { }: {
exportBackground: boolean; exportBackground: boolean;
exportPadding?: number; exportPadding?: number;
viewBackgroundColor: string; viewBackgroundColor: string;
scrollX: number;
scrollY: number;
name: string; name: string;
scale?: number;
} }
) { ) {
if (!elements.length) return window.alert("Cannot export empty canvas."); if (!elements.length) return window.alert("Cannot export empty canvas.");
// calculate smallest area to fit the contents in // calculate smallest area to fit the contents in
const tempCanvas = getExportCanvasPreview(elements, { let subCanvasX1 = Infinity;
exportBackground, let subCanvasX2 = 0;
viewBackgroundColor, let subCanvasY1 = Infinity;
exportPadding, let subCanvasY2 = 0;
scale
elements.forEach(element => {
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
subCanvasX1 = Math.min(subCanvasX1, x1);
subCanvasY1 = Math.min(subCanvasY1, y1);
subCanvasX2 = Math.max(subCanvasX2, x2);
subCanvasY2 = Math.max(subCanvasY2, y2);
}); });
function distance(x: number, y: number) {
return Math.abs(x > y ? x - y : y - x);
}
const tempCanvas = document.createElement("canvas");
tempCanvas.style.display = "none"; tempCanvas.style.display = "none";
document.body.appendChild(tempCanvas); document.body.appendChild(tempCanvas);
tempCanvas.width = distance(subCanvasX1, subCanvasX2) + exportPadding * 2;
tempCanvas.height = distance(subCanvasY1, subCanvasY2) + exportPadding * 2;
renderScene(
elements,
rough.canvas(tempCanvas),
tempCanvas,
{
viewBackgroundColor: exportBackground ? viewBackgroundColor : null,
scrollX: 0,
scrollY: 0
},
{
offsetX: -subCanvasX1 + exportPadding,
offsetY: -subCanvasY1 + exportPadding,
renderScrollbars: false,
renderSelection: false
}
);
if (type === "png") { if (type === "png") {
const fileName = `${name}.png`; const fileName = `${name}.png`;

Loading…
Cancel
Save