mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 23:12:21 -04:00
Fix wrong mask position after merging groups (#2682)
This commit is contained in:
parent
bae8038178
commit
bccc5b0995
1 changed files with 39 additions and 22 deletions
|
@ -2,6 +2,7 @@
|
||||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
import type { Canvas, Object as FabricObject } from "fabric";
|
import type { Canvas, Object as FabricObject } from "fabric";
|
||||||
|
import { fabric } from "fabric";
|
||||||
|
|
||||||
import { makeMaskTransparent } from "../tools/lib";
|
import { makeMaskTransparent } from "../tools/lib";
|
||||||
import type { Size } from "../types";
|
import type { Size } from "../types";
|
||||||
|
@ -10,7 +11,10 @@ import { Ellipse } from "./ellipse";
|
||||||
import { Polygon } from "./polygon";
|
import { Polygon } from "./polygon";
|
||||||
import { Rectangle } from "./rectangle";
|
import { Rectangle } from "./rectangle";
|
||||||
|
|
||||||
export function exportShapesToClozeDeletions(occludeInactive: boolean): { clozes: string; noteCount: number } {
|
export function exportShapesToClozeDeletions(occludeInactive: boolean): {
|
||||||
|
clozes: string;
|
||||||
|
noteCount: number;
|
||||||
|
} {
|
||||||
const shapes = baseShapesFromFabric(occludeInactive);
|
const shapes = baseShapesFromFabric(occludeInactive);
|
||||||
|
|
||||||
let clozes = "";
|
let clozes = "";
|
||||||
|
@ -28,14 +32,15 @@ function baseShapesFromFabric(occludeInactive: boolean): ShapeOrShapes[] {
|
||||||
const canvas = globalThis.canvas as Canvas;
|
const canvas = globalThis.canvas as Canvas;
|
||||||
makeMaskTransparent(canvas, false);
|
makeMaskTransparent(canvas, false);
|
||||||
const objects = canvas.getObjects() as FabricObject[];
|
const objects = canvas.getObjects() as FabricObject[];
|
||||||
return objects.map((object) => {
|
return objects
|
||||||
return fabricObjectToBaseShapeOrShapes(canvas, object, occludeInactive);
|
.map((object) => {
|
||||||
}).filter((o): o is ShapeOrShapes => o !== null);
|
return fabricObjectToBaseShapeOrShapes(
|
||||||
}
|
canvas,
|
||||||
|
object,
|
||||||
interface TopAndLeftOffset {
|
occludeInactive,
|
||||||
top: number;
|
);
|
||||||
left: number;
|
})
|
||||||
|
.filter((o): o is ShapeOrShapes => o !== null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convert a single Fabric object/group to one or more BaseShapes. */
|
/** Convert a single Fabric object/group to one or more BaseShapes. */
|
||||||
|
@ -43,9 +48,10 @@ function fabricObjectToBaseShapeOrShapes(
|
||||||
size: Size,
|
size: Size,
|
||||||
object: FabricObject,
|
object: FabricObject,
|
||||||
occludeInactive: boolean,
|
occludeInactive: boolean,
|
||||||
groupOffset: TopAndLeftOffset = { top: 0, left: 0 },
|
parentObject?: FabricObject,
|
||||||
): ShapeOrShapes | null {
|
): ShapeOrShapes | null {
|
||||||
let shape: Shape;
|
let shape: Shape;
|
||||||
|
|
||||||
switch (object.type) {
|
switch (object.type) {
|
||||||
case "rect":
|
case "rect":
|
||||||
shape = new Rectangle(object);
|
shape = new Rectangle(object);
|
||||||
|
@ -57,28 +63,37 @@ function fabricObjectToBaseShapeOrShapes(
|
||||||
shape = new Polygon(object);
|
shape = new Polygon(object);
|
||||||
break;
|
break;
|
||||||
case "group":
|
case "group":
|
||||||
// Positions inside a group are relative to the group, so we
|
return object._objects.map((child) => {
|
||||||
// need to pass in an offset. We do not support nested groups.
|
return fabricObjectToBaseShapeOrShapes(
|
||||||
groupOffset = {
|
size,
|
||||||
left: object.left + object.width / 2,
|
child,
|
||||||
top: object.top + object.height / 2,
|
occludeInactive,
|
||||||
};
|
object,
|
||||||
return object._objects.map((obj) => {
|
);
|
||||||
return fabricObjectToBaseShapeOrShapes(size, obj, occludeInactive, groupOffset);
|
|
||||||
});
|
});
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
shape.occludeInactive = occludeInactive;
|
shape.occludeInactive = occludeInactive;
|
||||||
shape.left += groupOffset.left;
|
if (parentObject) {
|
||||||
shape.top += groupOffset.top;
|
const newPosition = fabric.util.transformPoint(
|
||||||
|
{ x: shape.left, y: shape.top },
|
||||||
|
parentObject.calcTransformMatrix(),
|
||||||
|
);
|
||||||
|
shape.left = newPosition.x;
|
||||||
|
shape.top = newPosition.y;
|
||||||
|
}
|
||||||
|
|
||||||
shape.makeNormal(size);
|
shape.makeNormal(size);
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** generate cloze data in form of
|
/** generate cloze data in form of
|
||||||
{{c1::image-occlusion:rect:top=.1:left=.23:width=.4:height=.5}} */
|
{{c1::image-occlusion:rect:top=.1:left=.23:width=.4:height=.5}} */
|
||||||
function shapeOrShapesToCloze(shapeOrShapes: ShapeOrShapes, index: number): string {
|
function shapeOrShapesToCloze(
|
||||||
|
shapeOrShapes: ShapeOrShapes,
|
||||||
|
index: number,
|
||||||
|
): string {
|
||||||
let text = "";
|
let text = "";
|
||||||
function addKeyValue(key: string, value: string) {
|
function addKeyValue(key: string, value: string) {
|
||||||
if (Number.isNaN(Number(value))) {
|
if (Number.isNaN(Number(value))) {
|
||||||
|
@ -89,7 +104,9 @@ function shapeOrShapesToCloze(shapeOrShapes: ShapeOrShapes, index: number): stri
|
||||||
|
|
||||||
let type: string;
|
let type: string;
|
||||||
if (Array.isArray(shapeOrShapes)) {
|
if (Array.isArray(shapeOrShapes)) {
|
||||||
return shapeOrShapes.map((shape) => shapeOrShapesToCloze(shape, index)).join("");
|
return shapeOrShapes
|
||||||
|
.map((shape) => shapeOrShapesToCloze(shape, index))
|
||||||
|
.join("");
|
||||||
} else if (shapeOrShapes instanceof Rectangle) {
|
} else if (shapeOrShapes instanceof Rectangle) {
|
||||||
type = "rect";
|
type = "rect";
|
||||||
} else if (shapeOrShapes instanceof Ellipse) {
|
} else if (shapeOrShapes instanceof Ellipse) {
|
||||||
|
|
Loading…
Reference in a new issue