aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/util/InteractionUtils.tsx2
-rw-r--r--src/client/views/InkStrokeProperties.ts119
-rw-r--r--src/client/views/InkingStroke.scss18
-rw-r--r--src/client/views/InkingStroke.tsx93
-rw-r--r--src/fields/InkField.ts24
5 files changed, 177 insertions, 79 deletions
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 01d00db30..ba935e3bf 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -208,7 +208,7 @@ export namespace InteractionUtils {
<polyline
points={strpts}
style={{
- filter: drawHalo ? "url(#inkSelectionHalo)" : undefined,
+ // filter: drawHalo ? "url(#inkSelectionHalo)" : undefined,
fill: fill ? fill : "none",
opacity: strokeWidth !== width ? 0.5 : undefined,
pointerEvents: pevents as any,
diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts
index 533fdf006..5c5395984 100644
--- a/src/client/views/InkStrokeProperties.ts
+++ b/src/client/views/InkStrokeProperties.ts
@@ -2,12 +2,11 @@ import { action, computed, observable } from "mobx";
import { ColorState } from 'react-color';
import { Doc, Field, Opt } from "../../fields/Doc";
import { Document } from "../../fields/documentSchemas";
-import { InkField, InkData } from "../../fields/InkField";
+import { InkField, InkData, PointData } from "../../fields/InkField";
import { Cast, NumCast } from "../../fields/Types";
import { DocumentType } from "../documents/DocumentTypes";
import { SelectionManager } from "../util/SelectionManager";
import { undoBatch } from "../util/UndoManager";
-import { bool } from "sharp";
export class InkStrokeProperties {
static Instance: InkStrokeProperties | undefined;
@@ -15,15 +14,15 @@ export class InkStrokeProperties {
private _lastFill = "#D0021B";
private _lastLine = "#D0021B";
private _lastDash = "2";
- private _inkDocs: { x: number, y: number, width: number, height: number }[] = [];
- // Indicates whether the ink is locked.
@observable _lock = false;
- // Indicates whether the ink's format is being currently edited (displaying of control points).
@observable _controlBtn = false;
- // Stores the index of the current selected control point of the ink instance.
@observable _currPoint = -1;
+ constructor() {
+ InkStrokeProperties.Instance = this;
+ }
+
getField(key: string) {
return this.selectedInk?.reduce((p, i) =>
(p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>);
@@ -79,10 +78,6 @@ export class InkStrokeProperties {
});
}
- constructor() {
- InkStrokeProperties.Instance = this;
- }
-
/**
* Adds a new control point to the ink instance when editing its format.
* @param x The x-coordinate of the current new point.
@@ -213,36 +208,100 @@ export class InkStrokeProperties {
}
/**
- * Handles the movement / scaling of control points of an ink instance.
- * @param xDiff The movement of the control point's x-coordinate.
- * @param yDiff The movement of the control point's y-coordinate.
- * @param controlNum The index of the current control point selected.
- * @returns The changed x- and y-coordinates of the control points.
+ * Handles the movement/scaling of a control point.
*/
@undoBatch
@action
- control = (xDiff: number, yDiff: number, controlNum: number) =>
- this.applyFunction((doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => {
+ moveControl = (deltaX: number, deltaY: number, controlIndex: number) =>
+ this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
const newPoints: { X: number, Y: number }[] = [];
- const order = controlNum % 4;
+ const order = controlIndex % 4;
for (var i = 0; i < ink.length; i++) {
- newPoints.push(
- (controlNum === i ||
- (order === 0 && i === controlNum + 1) ||
- (order === 0 && controlNum !== 0 && i === controlNum - 2) ||
- (order === 0 && controlNum !== 0 && i === controlNum - 1) ||
- (order === 3 && i === controlNum - 1) ||
- (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) ||
- (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) ||
- ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1))
- ) ?
- { X: ink[i].X - xDiff / ptsXscale, Y: ink[i].Y - yDiff / ptsYscale } :
- { X: ink[i].X, Y: ink[i].Y });
+ const leftHandlePoint = order === 0 && i === controlIndex + 1;
+ const rightHandlePoint = order === 0 && controlIndex !== 0 && i === controlIndex - 2;
+ if (controlIndex === i ||
+ leftHandlePoint ||
+ rightHandlePoint ||
+ (order === 0 && controlIndex !== 0 && i === controlIndex - 1) ||
+ (order === 3 && i === controlIndex - 1) ||
+ (order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 1) ||
+ (order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 2) ||
+ ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlIndex === 0 || controlIndex === ink.length - 1))) {
+ newPoints.push({ X: ink[i].X - deltaX / xScale, Y: ink[i].Y - deltaY / yScale });
+ } else {
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ }
}
return newPoints;
});
/**
+ * Rotates the target point about the origin point for a given angle (radians).
+ */
+ @action
+ rotatePoint = (target: PointData, origin: PointData, angle: number) => {
+ target.X -= origin.X;
+ target.Y -= origin.Y;
+ const newX = Math.cos(angle) * target.X - Math.sin(angle) * target.Y;
+ const newY = Math.sin(angle) * target.X + Math.cos(angle) * target.Y;
+ target.X = newX + origin.X;
+ target.Y = newY + origin.Y;
+ return target
+ }
+
+ /**
+ * Finds the angle difference (in radians) between two vectors relative to an arbitrary origin.
+ */
+ angleChange = (a: PointData, b: PointData, origin: PointData) => {
+ // Finding vector representation of inputted points relative to new origin.
+ let vectorA = { X: a.X - origin.X, Y: a.Y - origin.Y };
+ let vectorB = { X: b.X - origin.X, Y: b.Y - origin.Y };
+ const crossProduct = vectorB.X * vectorA.Y - vectorB.Y * vectorA.X;
+ // Determining whether rotation is clockwise or counterclockwise.
+ const sign = crossProduct < 0 ? 1 : -1;
+ const magnitudeA = Math.sqrt(vectorA.X * vectorA.X + vectorA.Y * vectorA.Y);
+ const magnitudeB = Math.sqrt(vectorB.X * vectorB.X + vectorB.Y * vectorB.Y);
+ // Normalizing the vectors.
+ vectorA = { X: vectorA.X / magnitudeA, Y: vectorA.Y / magnitudeA };
+ vectorB = { X: vectorB.X / magnitudeB, Y: vectorB.Y / magnitudeB };
+ const dotProduct = vectorB.X * vectorA.X + vectorB.Y * vectorA.Y;
+ const theta = Math.acos(dotProduct);
+ return sign * theta;
+ }
+
+ /**
+ * Handles the movement/scaling of a handle point.
+ */
+ @undoBatch
+ @action
+ moveHandle = (deltaX: number, deltaY: number, handleIndex: number) =>
+ this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => {
+ const newPoints: { X: number, Y: number }[] = [];
+ const order = handleIndex % 4;
+ let newHandlePoint = { X: 0, Y: 0 };
+
+ for (var i = 0; i < ink.length; i++) {
+ if (handleIndex === i) {
+ newHandlePoint = { X: ink[i].X - deltaX / xScale, Y: ink[i].Y - deltaY / yScale };
+ newPoints.push({ X: newHandlePoint.X, Y: newHandlePoint.Y });
+ } else {
+ newPoints.push({ X: ink[i].X, Y: ink[i].Y });
+ }
+ }
+
+ if (handleIndex !== 1 && handleIndex !== ink.length - 2) {
+ const oldHandlePoint = ink[handleIndex];
+ let oppositeHandlePoint = order === 1 ? ink[handleIndex - 3] : ink[handleIndex + 3];
+ const controlPoint = order === 1 ? ink[handleIndex - 1] : ink[handleIndex + 1];
+ const angle = this.angleChange(oldHandlePoint, newHandlePoint, controlPoint);
+ oppositeHandlePoint = this.rotatePoint(oppositeHandlePoint, controlPoint, angle);
+ order === 1 ? newPoints[handleIndex - 3] = oppositeHandlePoint : newPoints[handleIndex + 3] = oppositeHandlePoint;
+ }
+
+ return newPoints;
+ });
+
+ /**
* Changes the color of the border of the ink instance.
* @param color The new hex value to change the border to.
* @returns true.
diff --git a/src/client/views/InkingStroke.scss b/src/client/views/InkingStroke.scss
index 30ab1967e..f67b1779d 100644
--- a/src/client/views/InkingStroke.scss
+++ b/src/client/views/InkingStroke.scss
@@ -1,11 +1,11 @@
.inkingStroke {
- mix-blend-mode: multiply;
- stroke-linejoin: round;
- stroke-linecap: round;
- overflow: visible !important;
- transform-origin: top left;
+ mix-blend-mode: multiply;
+ stroke-linejoin: round;
+ stroke-linecap: round;
+ overflow: visible !important;
+ transform-origin: top left;
- svg:not(:root) {
- overflow: visible !important;
- }
-} \ No newline at end of file
+ svg:not(:root) {
+ overflow: visible !important;
+ }
+}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 859e53b97..163eb05b0 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -2,7 +2,7 @@ import { action } from "mobx";
import { observer } from "mobx-react";
import { Doc } from "../../fields/Doc";
import { documentSchema } from "../../fields/documentSchemas";
-import { InkData, InkField, InkTool } from "../../fields/InkField";
+import { InkData, InkField, InkTool, ControlPoint, HandlePoint, HandleLine } from "../../fields/InkField";
import { makeInterface } from "../../fields/Schema";
import { Cast, StrCast } from "../../fields/Types";
import { TraceMobx } from "../../fields/util";
@@ -28,33 +28,51 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); }
- private analyzeStrokes = () => {
+ analyzeStrokes = () => {
const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]);
}
- public static toggleMask = action((inkDoc: Doc) => {
+ @action
+ public static toggleMask = (inkDoc: Doc) => {
inkDoc.isInkMask = !inkDoc.isInkMask;
inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined;
inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined;
inkDoc.color = "#9b9b9bff";
inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined;
- });
+ };
/**
* Handles the movement of a selected control point when the user clicks and drags.
- * @param e React Pointer Event.
- * @param controlNum The number of the currently selected control point.
+ * @param controlNum The index of the currently selected control point.
*/
@action
onControlDown = (e: React.PointerEvent, controlNum: number): void => {
if (InkStrokeProperties.Instance) {
- InkStrokeProperties.Instance.control(0, 0, 1);
+ InkStrokeProperties.Instance.moveControl(0, 0, 1);
+ const controlUndo = UndoManager.StartBatch("DocDecs set radius");
+ const screenScale = this.props.ScreenToLocalTransform().Scale;
+ setupMoveUpEvents(this, e,
+ (e: PointerEvent, down: number[], delta: number[]) => {
+ InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlNum);
+ return false;
+ },
+ () => controlUndo?.end(), emptyFunction);
+ }
+ }
+
+ /**
+ * Handles the movement of a selected handle point when the user clicks and drags.
+ * @param controlNum The index of the currently selected handle point.
+ */
+ onHandleDown = (e: React.PointerEvent, handleNum: number): void => {
+ if (InkStrokeProperties.Instance) {
+ InkStrokeProperties.Instance.moveControl(0, 0, 1);
const controlUndo = UndoManager.StartBatch("DocDecs set radius");
const screenScale = this.props.ScreenToLocalTransform().Scale;
setupMoveUpEvents(this, e,
(e: PointerEvent, down: number[], delta: number[]) => {
- InkStrokeProperties.Instance?.control(-delta[0] * screenScale, -delta[1] * screenScale, controlNum);
+ InkStrokeProperties.Instance?.moveHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleNum);
return false;
},
() => controlUndo?.end(), emptyFunction);
@@ -69,7 +87,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
changeCurrPoint = (i: number) => {
if (InkStrokeProperties.Instance) {
InkStrokeProperties.Instance._currPoint = i;
- document.addEventListener("keydown", this.delPts, true);
+ document.addEventListener("keydown", this.onDelete, true);
}
}
@@ -78,7 +96,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
* @param e Keyboard Event.
*/
@action
- delPts = (e: KeyboardEvent) => {
+ onDelete = (e: KeyboardEvent) => {
if (["-", "Backspace", "Delete"].includes(e.key)) {
if (InkStrokeProperties.Instance?.deletePoints()) e.stopPropagation();
}
@@ -101,7 +119,6 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const formatInstance = InkStrokeProperties.Instance;
if (!formatInstance) return (null);
const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? [];
- // const strokeWidth = Number(StrCast(this.layoutDoc.strokeWidth, ActiveInkWidth()));
const strokeWidth = Number(this.layoutDoc.strokeWidth);
const xs = data.map(p => p.X);
const ys = data.map(p => p.Y);
@@ -118,12 +135,18 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const scaleX = width === strokeWidth ? 1 : (this.props.PanelWidth() - strokeWidth) / (width - strokeWidth);
const scaleY = height === strokeWidth ? 1 : (this.props.PanelHeight() - strokeWidth) / (height - strokeWidth);
const strokeColor = StrCast(this.layoutDoc.color, "");
+ const dotsize = Math.max(width * scaleX, height * scaleY) / 40;
// Visually renders the polygonal line made by the user.
const points = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth,
StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5 && lineBot - lineTop > 1 && lineRgt - lineLft > 1, false);
+
+ const selectedLine = InteractionUtils.CreatePolyline(data, lineLft - strokeWidth * 3, lineTop - strokeWidth * 3, "#1F85DE", strokeWidth / 6, strokeWidth / 6,
+ StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"),
+ StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
+ StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5 && lineBot - lineTop > 1 && lineRgt - lineLft > 1, false);
// Invisible polygonal line that enables the ink to be selected by the user.
const hpoints = InteractionUtils.CreatePolyline(data, left, top,
@@ -136,10 +159,13 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker),
StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false);
- const controlPoints: { X: number, Y: number, I: number }[] = [];
- const handlePoints: { X: number, Y: number, I: number, dot1: number, dot2: number }[] = [];
- const handleLine: { X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, dot1: number, dot2: number }[] = [];
+ const controlPoints: ControlPoint[] = [];
+ const handlePoints: HandlePoint[] = [];
+ const handleLine: HandleLine[] = [];
+ // check the purpose of this conditional
if (data.length >= 4) {
+
+ // create separate functions for these
for (var i = 0; i <= data.length - 4; i += 4) {
controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
controlPoints.push({ X: data[i + 3].X, Y: data[i + 3].Y, I: i + 3 });
@@ -147,29 +173,21 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 });
}
- handleLine.push({ X1: data[0].X, Y1: data[0].Y, X2: data[0].X, Y2: data[0].Y, X3: data[1].X, Y3: data[1].Y, dot1: 0, dot2: 0 });
+ // first (single) handle line
+ handleLine.push({ X1: data[0].X, Y1: data[0].Y, X2: data[1].X, Y2: data[1].Y, dot1: 0, dot2: 0 });
for (var i = 2; i < data.length - 4; i += 4) {
- handleLine.push({ X1: data[i].X, Y1: data[i].Y, X2: data[i + 1].X, Y2: data[i + 1].Y, X3: data[i + 3].X, Y3: data[i + 3].Y, dot1: i + 1, dot2: i + 2 });
+ handleLine.push({ X1: data[i].X, Y1: data[i].Y, X2: data[i + 3].X, Y2: data[i + 3].Y, dot1: i + 1, dot2: i + 2 });
}
- handleLine.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[data.length - 1].X, Y2: data[data.length - 1].Y, X3: data[data.length - 1].X, Y3: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 });
+ // last (single) handle line
+ handleLine.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[data.length - 1].X, Y2: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 });
for (var i = 0; i <= data.length - 4; i += 4) {
handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? i : i - 1 });
handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 });
}
}
- // if (data.length <= 4) {
- // handlePoints = [];
- // handleLine = [];
- // controlPoints = [];
- // for (var i = 0; i < data.length; i++) {
- // controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i });
- // }
-
- // }
- const dotsize = Math.max(width * scaleX, height * scaleY) / 40;
// Additional points (controls) added by the user via click when editing the ink's format.
const addpoints = apoints.map((pts, i) =>
@@ -178,27 +196,24 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
onPointerDown={(e) => { formatInstance.addPoints(pts.X, pts.Y, apoints, i, controlPoints); }} pointerEvents="all" cursor="all-scroll"
/>
</svg>);
- // Green circles that allow the user to edit the curvature of the line using the selected point as the anchor.
+ // Blue circles that allow the user to edit the curvature of the line using the selected control point as the anchor.
const handles = handlePoints.map((pts, i) =>
<svg height="10" width="10" key={`hdl${i}`}>
- <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth} strokeWidth={0} fill="green"
- onPointerDown={(e) => this.onControlDown(e, pts.I)} pointerEvents="all" cursor="default" display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
+ <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 2} strokeWidth={0} fill="#1F85DE"
+ onPointerDown={(e) => this.onHandleDown(e, pts.I)} pointerEvents="all" cursor="default" display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
</svg>);
- // Points (red circles) of the ink that are made visible to user when editing its format.
+ // Control points of the ink (blue outlined squares) that are made visible to user when editing its format.
const controls = controlPoints.map((pts, i) =>
<svg height="10" width="10" key={`ctrl${i}`}>
- <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 2} strokeWidth={0} fill="red"
+ <rect x={(pts.X - left) * scaleX} y={(pts.Y - top) * scaleY} height={strokeWidth} width={strokeWidth} strokeWidth={strokeWidth / 6} stroke="#1F85DE" fill={formatInstance && formatInstance._currPoint === pts.I ? "#1F85DE" : "white"}
onPointerDown={(e) => { this.changeCurrPoint(pts.I); this.onControlDown(e, pts.I); }} pointerEvents="all" cursor="default"
/>
</svg>);
- // Set of two green lines (each with a handle at the end) that are rendered perpendicular to the current selected point while editing.
+ // Set of two blue lines (each with a handle at the end) that are rendered perpendicular to the current selected point while editing.
const handleLines = handleLine.map((pts, i) =>
- <svg height="100" width="100" key={`line${i}`} >
+ <svg height="100" width="100" key={`line${i}`}>
<line x1={(pts.X1 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y1={(pts.Y1 - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
- x2={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="green" strokeWidth={dotsize / 6}
- display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
- <line x1={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y1={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2}
- x2={(pts.X3 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y3 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="green" strokeWidth={dotsize / 6}
+ x2={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="#1F85DE" strokeWidth={dotsize / 10}
display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} />
</svg>);
@@ -227,8 +242,8 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
{formatInstance._controlBtn && this.props.isSelected() ? addpoints : ""}
{formatInstance._controlBtn && this.props.isSelected() ? handleLines : ""}
{formatInstance._controlBtn && this.props.isSelected() ? handles : ""}
+ {this.props.isSelected() ? selectedLine : ""}
{formatInstance._controlBtn && this.props.isSelected() ? controls : ""}
-
</svg>
);
}
diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts
index b79a03146..c158dac42 100644
--- a/src/fields/InkField.ts
+++ b/src/fields/InkField.ts
@@ -13,6 +13,7 @@ export enum InkTool {
Stamp = "stamp"
}
+
// Defines a point in an ink as a pair of x- and y-coordinates.
export interface PointData {
X: number;
@@ -22,6 +23,29 @@ export interface PointData {
// Defines an ink as an array of points.
export type InkData = Array<PointData>;
+export interface ControlPoint {
+ X: number;
+ Y: number;
+ I: number;
+}
+
+export interface HandlePoint {
+ X: number;
+ Y: number;
+ I: number;
+ dot1: number;
+ dot2: number;
+}
+
+export interface HandleLine {
+ X1: number;
+ Y1: number;
+ X2: number;
+ Y2: number;
+ dot1: number;
+ dot2: number;
+}
+
const pointSchema = createSimpleSchema({
X: true, Y: true
});