Fixes canvas re-renders

This commit is contained in:
Josh Perez 2021-12-03 13:05:11 -05:00 committed by GitHub
parent c0dcce7c82
commit b87e05b1de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 59 additions and 10 deletions

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10,20A10,10,0,1,1,20,10,10.011,10.011,0,0,1,10,20ZM10,1.474A8.526,8.526,0,1,0,18.526,10,8.536,8.536,0,0,0,10,1.474Z"/><circle cx="10" cy="10" r="2.513"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10,20A10,10,0,1,1,20,10,10.011,10.011,0,0,1,10,20ZM10,1.483A8.517,8.517,0,1,0,18.517,10,8.526,8.526,0,0,0,10,1.483Z"/><circle cx="10" cy="10" r="3.747"/></svg>

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 229 B

View File

@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10,20A10,10,0,1,1,20,10,10.011,10.011,0,0,1,10,20ZM10,1.483A8.517,8.517,0,1,0,18.517,10,8.526,8.526,0,0,0,10,1.483Z"/><circle cx="10" cy="10" r="3.747"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M10,20A10,10,0,1,1,20,10,10.011,10.011,0,0,1,10,20ZM10,1.474A8.526,8.526,0,1,0,18.526,10,8.536,8.536,0,0,0,10,1.474Z"/><circle cx="10" cy="10" r="2.513"/></svg>

Before

Width:  |  Height:  |  Size: 229 B

After

Width:  |  Height:  |  Size: 229 B

View File

@ -94,6 +94,12 @@ export const MediaEditor = ({
// Initial image load and Fabric canvas setup
useEffect(() => {
// This is important. We can't re-run this function if we've already setup
// a canvas since Fabric doesn't like that.
if (fabricCanvas) {
return;
}
const img = new Image();
img.onload = () => {
setImage(img);
@ -117,7 +123,7 @@ export const MediaEditor = ({
img.onload = noop;
img.onerror = noop;
};
}, [canvasId, imageSrc, onClose]);
}, [canvasId, fabricCanvas, imageSrc, onClose]);
const history = useFabricHistory(fabricCanvas);
@ -142,7 +148,22 @@ export const MediaEditor = ({
ev => isCmdOrCtrl(ev) && ev.key === 't',
() => setEditMode(EditMode.Text),
],
[ev => isCmdOrCtrl(ev) && ev.key === 'z', () => history?.undo()],
[
ev => isCmdOrCtrl(ev) && ev.key === 'z',
() => {
if (history?.canUndo()) {
history?.undo();
}
},
],
[
ev => isCmdOrCtrl(ev) && ev.shiftKey && ev.key === 'z',
() => {
if (history?.canRedo()) {
history?.redo();
}
},
],
[
ev => ev.key === 'Escape',
() => {
@ -519,6 +540,7 @@ export const MediaEditor = ({
return;
}
obj.exitEditing();
obj.set(getTextStyleAttributes(textStyle, sliderValue));
fabricCanvas.requestRenderAll();
}, [editMode, fabricCanvas, sliderValue, textStyle]);
@ -610,6 +632,8 @@ export const MediaEditor = ({
textStyle,
]);
const [isSaving, setIsSaving] = useState(false);
// In an ideal world we'd use <ModalHost /> to get the nice animation benefits
// but because of the way IText is implemented -- with a hidden textarea -- to
// capture keyboard events, we can't use ModalHost since that traps focus, and
@ -963,12 +987,12 @@ export const MediaEditor = ({
'MediaEditor__control--selected': editMode === EditMode.Text,
})}
onClick={() => {
if (!fabricCanvas) {
return;
}
if (editMode === EditMode.Text) {
setEditMode(undefined);
const obj = fabricCanvas?.getActiveObject();
if (obj instanceof MediaEditorFabricIText) {
obj.exitEditing();
}
} else {
setEditMode(EditMode.Text);
}
@ -1069,12 +1093,37 @@ export const MediaEditor = ({
/>
</div>
<Button
disabled={!image || isSaving}
onClick={async () => {
if (!fabricCanvas) {
return;
}
const renderedCanvas = fabricCanvas.toCanvasElement();
const data = await canvasToBytes(renderedCanvas);
setEditMode(undefined);
setIsSaving(true);
let data: Uint8Array;
try {
fabricCanvas.discardActiveObject();
fabricCanvas.setDimensions({
width: image.width,
height: image.height,
});
fabricCanvas.setZoom(1);
const renderedCanvas = fabricCanvas.toCanvasElement();
fabricCanvas.setDimensions({
width: imageState.width * zoom,
height: imageState.height * zoom,
});
fabricCanvas.setZoom(zoom);
data = await canvasToBytes(renderedCanvas);
} catch (err) {
onClose();
throw err;
} finally {
setIsSaving(false);
}
onDone(data);
}}
theme={Theme.Dark}