aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2021-10-26 20:40:58 -0400
committerbobzel <zzzman@gmail.com>2021-10-26 20:40:58 -0400
commitb30b1cb301ed742a128d5e17eea9c954d1fe0c22 (patch)
tree78bd96ec757329e74a92c244f0241de90c02beb9
parent48d5e650ddc8caa8252561bbc91961f2f4677d6e (diff)
fix to ink rotation to preserve rotation center between rotations.
-rw-r--r--src/client/views/DocumentDecorations.tsx11
-rw-r--r--src/client/views/InkingStroke.tsx17
-rw-r--r--src/client/views/nodes/DocumentView.tsx5
3 files changed, 25 insertions, 8 deletions
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 5b44a0552..3b992e0d1 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -1,7 +1,7 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Tooltip } from '@material-ui/core';
-import { action, computed, observable, reaction, runInAction } from "mobx";
+import { action, computed, observable, reaction } from "mobx";
import { observer } from "mobx-react";
import { DateField } from '../../fields/DateField';
import { AclAdmin, AclEdit, DataSym, Doc, DocListCast, Field, HeightSym, WidthSym } from "../../fields/Doc";
@@ -27,8 +27,6 @@ import { LightboxView } from './LightboxView';
import { DocumentView } from "./nodes/DocumentView";
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import React = require("react");
-import { dark } from '@material-ui/core/styles/createPalette';
-import { color } from 'd3-color';
@observer
export class DocumentDecorations extends React.Component<{ PanelWidth: number, PanelHeight: number, boundsLeft: number, boundsTop: number }, { value: string }> {
@@ -71,9 +69,10 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
x: Math.min(rect.left, bounds.x),
y: Math.min(rect.top, bounds.y),
r: Math.max(rect.right, bounds.r),
- b: Math.max(rect.bottom, bounds.b)
+ b: Math.max(rect.bottom, bounds.b),
+ c: rect.center
},
- { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE });
+ { x: Number.MAX_VALUE, y: Number.MAX_VALUE, r: Number.MIN_VALUE, b: Number.MIN_VALUE, c: undefined as ({ X: number, Y: number } | undefined) });
}
@action
@@ -195,7 +194,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number, P
@action
onRotateDown = (e: React.PointerEvent): void => {
this._rotateUndo = UndoManager.StartBatch("rotatedown");
- const pt = { x: (this.Bounds.x + this.Bounds.r) / 2, y: (this.Bounds.y + this.Bounds.b) / 2 };
+ const pt = { x: this.Bounds.c?.X ?? (this.Bounds.x + this.Bounds.r) / 2, y: this.Bounds.c?.Y ?? (this.Bounds.y + this.Bounds.b) / 2 };
setupMoveUpEvents(this, e,
(e: PointerEvent, down: number[], delta: number[]) => {
const movement = { X: delta[0], Y: e.clientY - down[1] };
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index d312331d0..b039579ce 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -21,6 +21,7 @@ import { InkStrokeProperties } from "./InkStrokeProperties";
import { InkTangentHandles } from "./InkTangentHandles";
import { FieldView, FieldViewProps } from "./nodes/FieldView";
import Color = require("color");
+import { Transform } from "../util/Transform";
type InkDocument = makeInterface<[typeof documentSchema]>;
const InkDocument = makeInterface(documentSchema);
@@ -56,6 +57,22 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
this._selDisposer?.();
}
+ getCenter = (xf: Transform) => {
+ const { inkData, inkScaleX, inkScaleY, inkStrokeWidth, inkTop, inkLeft } = this.inkScaledData();
+ const angle = -NumCast(this.layoutDoc.rotation);
+ const newPoints = inkData.map(pt => {
+ const newX = Math.cos(angle) * pt.X - Math.sin(angle) * pt.Y * inkScaleY / inkScaleX;
+ const newY = Math.sin(angle) * pt.X * inkScaleX / inkScaleY + Math.cos(angle) * pt.Y;
+ return { X: newX, Y: newY };
+ });
+ const crx = (Math.max(...newPoints.map(np => np.X)) + Math.min(...newPoints.map(np => np.X))) / 2;
+ const cry = (Math.max(...newPoints.map(np => np.Y)) + Math.min(...newPoints.map(np => np.Y))) / 2;
+ const cx = Math.cos(-angle) * crx - Math.sin(-angle) * cry * inkScaleY / inkScaleX;
+ const cy = Math.sin(-angle) * crx * inkScaleX / inkScaleY + Math.cos(-angle) * cry;
+ const tc = xf.transformPoint((cx - inkLeft - inkStrokeWidth / 2) * inkScaleX + inkStrokeWidth / 2, (cy - inkTop - inkStrokeWidth / 2) * inkScaleY + inkStrokeWidth / 2);
+ return { X: tc[0], Y: tc[1] };
+ }
+
analyzeStrokes() {
const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 949e0e168..cbb77f369 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -97,6 +97,7 @@ export interface DocComponentView {
annotationKey?: string;
getTitle?: () => string;
getScrollHeight?: () => number;
+ getCenter?: (xf: Transform) => { X: number, Y: number };
search?: (str: string, bwd?: boolean, clear?: boolean) => boolean;
}
export interface DocumentViewSharedProps {
@@ -1179,9 +1180,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
const [[left, top], [right, bottom]] = [xf.transformPoint(0, 0), xf.transformPoint(this.panelWidth, this.panelHeight)];
if (this.docView.props.LayoutTemplateString?.includes(LinkAnchorBox.name)) {
const docuBox = this.docView.ContentDiv.getElementsByClassName("linkAnchorBox-cont");
- if (docuBox.length) return docuBox[0].getBoundingClientRect();
+ if (docuBox.length) return { ...docuBox[0].getBoundingClientRect(), center: undefined };
}
- return { left, top, right, bottom };
+ return { left, top, right, bottom, center: this.ComponentView?.getCenter?.(xf) };
}
public iconify() {