Revert "Revert "Wait for other callbacks before load SVG code"" (#772)

* Add back bitmap jumping fix

* Cancel previous async action if a new one is queued, and move zoomToFit call until after import

* Make bitmap load cancellable too
This commit is contained in:
DD Liu 2018-11-20 14:10:25 -05:00 committed by GitHub
parent 6d69e7c65f
commit badc549fdc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -25,8 +25,10 @@ class PaperCanvas extends React.Component {
constructor (props) { constructor (props) {
super(props); super(props);
bindAll(this, [ bindAll(this, [
'clearQueuedImport',
'setCanvas', 'setCanvas',
'importSvg', 'importSvg',
'initializeSvg',
'maybeZoomToFit', 'maybeZoomToFit',
'switchCostume' 'switchCostume'
]); ]);
@ -65,9 +67,21 @@ class PaperCanvas extends React.Component {
} }
} }
componentWillUnmount () { componentWillUnmount () {
this.clearQueuedImport();
this.props.saveZoomLevel(); this.props.saveZoomLevel();
paper.remove(); paper.remove();
} }
clearQueuedImport () {
if (this.queuedImport) {
window.clearTimeout(this.queuedImport);
this.queuedImport = null;
}
if (this.queuedImageToLoad) {
this.queuedImageToLoad.src = '';
this.queuedImageToLoad.onload = null;
this.queuedImageToLoad = null;
}
}
switchCostume (format, image, rotationCenterX, rotationCenterY, oldZoomLevelId, newZoomLevelId) { switchCostume (format, image, rotationCenterX, rotationCenterY, oldZoomLevelId, newZoomLevelId) {
if (oldZoomLevelId && oldZoomLevelId !== newZoomLevelId) { if (oldZoomLevelId && oldZoomLevelId !== newZoomLevelId) {
this.props.saveZoomLevel(); this.props.saveZoomLevel();
@ -94,6 +108,9 @@ class PaperCanvas extends React.Component {
this.importImage(format, image, rotationCenterX, rotationCenterY); this.importImage(format, image, rotationCenterX, rotationCenterY);
} }
importImage (format, image, rotationCenterX, rotationCenterY) { importImage (format, image, rotationCenterX, rotationCenterY) {
// Stop any in-progress imports
this.clearQueuedImport();
if (!image) { if (!image) {
this.props.changeFormat(Formats.VECTOR_SKIP_CONVERT); this.props.changeFormat(Formats.VECTOR_SKIP_CONVERT);
performSnapshot(this.props.undoSnapshot, Formats.VECTOR_SKIP_CONVERT); performSnapshot(this.props.undoSnapshot, Formats.VECTOR_SKIP_CONVERT);
@ -104,7 +121,11 @@ class PaperCanvas extends React.Component {
// import bitmap // import bitmap
this.props.changeFormat(Formats.BITMAP_SKIP_CONVERT); this.props.changeFormat(Formats.BITMAP_SKIP_CONVERT);
const imgElement = new Image(); const imgElement = new Image();
this.queuedImageToLoad = imgElement;
imgElement.onload = () => { imgElement.onload = () => {
if (!this.queuedImageToLoad) return;
this.queuedImageToLoad = null;
getRaster().drawImage( getRaster().drawImage(
imgElement, imgElement,
(ART_BOARD_WIDTH / 2) - rotationCenterX, (ART_BOARD_WIDTH / 2) - rotationCenterX,
@ -120,7 +141,6 @@ class PaperCanvas extends React.Component {
} else if (format === 'svg') { } else if (format === 'svg') {
this.props.changeFormat(Formats.VECTOR_SKIP_CONVERT); this.props.changeFormat(Formats.VECTOR_SKIP_CONVERT);
this.importSvg(image, rotationCenterX, rotationCenterY); this.importSvg(image, rotationCenterX, rotationCenterY);
this.maybeZoomToFit();
} else { } else {
log.error(`Didn't recognize format: ${format}. Use 'jpg', 'png' or 'svg'.`); log.error(`Didn't recognize format: ${format}. Use 'jpg', 'png' or 'svg'.`);
this.props.changeFormat(Formats.VECTOR_SKIP_CONVERT); this.props.changeFormat(Formats.VECTOR_SKIP_CONVERT);
@ -171,59 +191,68 @@ class PaperCanvas extends React.Component {
performSnapshot(paperCanvas.props.undoSnapshot, Formats.VECTOR_SKIP_CONVERT); performSnapshot(paperCanvas.props.undoSnapshot, Formats.VECTOR_SKIP_CONVERT);
return; return;
} }
const itemWidth = item.bounds.width; item.remove();
const itemHeight = item.bounds.height;
// Remove viewbox // Without the callback, rasters' load function has not been called yet, and they are
if (item.clipped) { // positioned incorrectly
let mask; paperCanvas.queuedImport =
for (const child of item.children) { window.setTimeout(() => {
if (child.isClipMask()) { paperCanvas.initializeSvg(item, rotationCenterX, rotationCenterY, viewBox);
mask = child; }, 0);
break;
}
}
item.clipped = false;
mask.remove();
}
// Reduce single item nested in groups
if (item instanceof paper.Group && item.children.length === 1) {
item = item.reduce();
}
ensureClockwise(item);
scaleWithStrokes(item, 2, new paper.Point()); // Import at 2x
if (typeof rotationCenterX !== 'undefined' && typeof rotationCenterY !== 'undefined') {
let rotationPoint = new paper.Point(rotationCenterX, rotationCenterY);
if (viewBox && viewBox.length >= 2 && !isNaN(viewBox[0]) && !isNaN(viewBox[1])) {
rotationPoint = rotationPoint.subtract(viewBox[0], viewBox[1]);
}
item.translate(new paper.Point(ART_BOARD_WIDTH / 2, ART_BOARD_HEIGHT / 2)
.subtract(rotationPoint.multiply(2)));
} else {
// Center
item.translate(new paper.Point(ART_BOARD_WIDTH / 2, ART_BOARD_HEIGHT / 2)
.subtract(itemWidth, itemHeight));
}
if (isGroup(item)) {
// Fixes an issue where we may export empty groups
for (const child of item.children) {
if (isGroup(child) && child.children.length === 0) {
child.remove();
}
}
ungroupItems([item]);
}
// Without the callback, the transforms sometimes don't finish applying before the
// snapshot is taken.
window.setTimeout(
() => performSnapshot(paperCanvas.props.undoSnapshot, Formats.VECTOR_SKIP_CONVERT), 0);
} }
}); });
} }
initializeSvg (item, rotationCenterX, rotationCenterY, viewBox) {
if (this.queuedImport) this.queuedImport = null;
const itemWidth = item.bounds.width;
const itemHeight = item.bounds.height;
// Remove viewbox
if (item.clipped) {
let mask;
for (const child of item.children) {
if (child.isClipMask()) {
mask = child;
break;
}
}
item.clipped = false;
mask.remove();
}
// Reduce single item nested in groups
if (item instanceof paper.Group && item.children.length === 1) {
item = item.reduce();
}
ensureClockwise(item);
scaleWithStrokes(item, 2, new paper.Point()); // Import at 2x
if (typeof rotationCenterX !== 'undefined' && typeof rotationCenterY !== 'undefined') {
let rotationPoint = new paper.Point(rotationCenterX, rotationCenterY);
if (viewBox && viewBox.length >= 2 && !isNaN(viewBox[0]) && !isNaN(viewBox[1])) {
rotationPoint = rotationPoint.subtract(viewBox[0], viewBox[1]);
}
item.translate(new paper.Point(ART_BOARD_WIDTH / 2, ART_BOARD_HEIGHT / 2)
.subtract(rotationPoint.multiply(2)));
} else {
// Center
item.translate(new paper.Point(ART_BOARD_WIDTH / 2, ART_BOARD_HEIGHT / 2)
.subtract(itemWidth, itemHeight));
}
paper.project.activeLayer.insertChild(0, item);
if (isGroup(item)) {
// Fixes an issue where we may export empty groups
for (const child of item.children) {
if (isGroup(child) && child.children.length === 0) {
child.remove();
}
}
ungroupItems([item]);
}
performSnapshot(this.props.undoSnapshot, Formats.VECTOR_SKIP_CONVERT);
this.maybeZoomToFit();
}
setCanvas (canvas) { setCanvas (canvas) {
this.canvas = canvas; this.canvas = canvas;
if (this.props.canvasRef) { if (this.props.canvasRef) {