Make circle (shift-oval) tool work for any direction dragged (#774)

This commit is contained in:
Florrie 2018-11-28 14:16:20 -04:00 committed by DD Liu
parent ada81cbd88
commit a04f1276f8
5 changed files with 61 additions and 11 deletions

View file

@ -3,6 +3,7 @@ import Modes from '../../lib/modes';
import {commitOvalToBitmap} from '../bitmap'; import {commitOvalToBitmap} from '../bitmap';
import {getRaster} from '../layer'; import {getRaster} from '../layer';
import {clearSelection} from '../selection'; import {clearSelection} from '../selection';
import {getSquareDimensions} from '../math';
import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import BoundingBoxTool from '../selection-tools/bounding-box-tool';
import NudgeTool from '../selection-tools/nudge-tool'; import NudgeTool from '../selection-tools/nudge-tool';
@ -151,13 +152,17 @@ class OvalTool extends paper.Tool {
const downPoint = new paper.Point(event.downPoint.x, event.downPoint.y); const downPoint = new paper.Point(event.downPoint.x, event.downPoint.y);
const point = new paper.Point(event.point.x, event.point.y); const point = new paper.Point(event.point.x, event.point.y);
const squareDimensions = getSquareDimensions(event.downPoint, event.point);
if (event.modifiers.shift) { if (event.modifiers.shift) {
this.oval.size = new paper.Point(event.downPoint.x - event.point.x, event.downPoint.x - event.point.x); this.oval.size = squareDimensions.size.abs();
} else { } else {
this.oval.size = downPoint.subtract(point); this.oval.size = downPoint.subtract(point);
} }
if (event.modifiers.alt) { if (event.modifiers.alt) {
this.oval.position = downPoint; this.oval.position = downPoint;
} else if (event.modifiers.shift) {
this.oval.position = squareDimensions.position;
} else { } else {
this.oval.position = downPoint.subtract(this.oval.size.multiply(0.5)); this.oval.position = downPoint.subtract(this.oval.size.multiply(0.5));
} }

View file

@ -3,6 +3,7 @@ import Modes from '../../lib/modes';
import {commitRectToBitmap} from '../bitmap'; import {commitRectToBitmap} from '../bitmap';
import {getRaster} from '../layer'; import {getRaster} from '../layer';
import {clearSelection} from '../selection'; import {clearSelection} from '../selection';
import {getSquareDimensions} from '../math';
import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import BoundingBoxTool from '../selection-tools/bounding-box-tool';
import NudgeTool from '../selection-tools/nudge-tool'; import NudgeTool from '../selection-tools/nudge-tool';
@ -133,10 +134,11 @@ class RectTool extends paper.Tool {
const dimensions = event.point.subtract(event.downPoint); const dimensions = event.point.subtract(event.downPoint);
const baseRect = new paper.Rectangle(event.downPoint, event.point); const baseRect = new paper.Rectangle(event.downPoint, event.point);
const squareDimensions = getSquareDimensions(event.downPoint, event.point);
if (event.modifiers.shift) { if (event.modifiers.shift) {
baseRect.height = baseRect.width; baseRect.size = squareDimensions.size.abs();
dimensions.y = event.downPoint.y > event.point.y ? -Math.abs(baseRect.width) : Math.abs(baseRect.width);
} }
if (this.rect) this.rect.remove(); if (this.rect) this.rect.remove();
this.rect = new paper.Shape.Rectangle(baseRect); this.rect = new paper.Shape.Rectangle(baseRect);
if (this.filled) { if (this.filled) {
@ -152,6 +154,8 @@ class RectTool extends paper.Tool {
if (event.modifiers.alt) { if (event.modifiers.alt) {
this.rect.position = event.downPoint; this.rect.position = event.downPoint;
} else if (event.modifiers.shift) {
this.rect.position = squareDimensions.position;
} else { } else {
this.rect.position = event.downPoint.add(dimensions.multiply(.5)); this.rect.position = event.downPoint.add(dimensions.multiply(.5));
} }

View file

@ -131,6 +131,39 @@ const scaleWithStrokes = function (root, factor, pivot) {
root.scale(factor, pivot); root.scale(factor, pivot);
}; };
/**
* Get the size and position of a square, as in if the user were holding the shift key down while drawing the shape,
* from the point where the drag started and the point where the mouse is currently positioned. (Note: This also works
* for shapes like circles ("square ovals"), which fill the same dimensions.)
* @param {!paper.Point} startPos The point where the user started dragging
* @param {!paper.Point} eventPoint The point where the user has currently dragged to
* @return {object} Information about the size and position of how the square should be drawn
*/
const getSquareDimensions = function (startPos, eventPoint) {
// These variables are used for determining the relative quadrant that the shape will appear in.
// So if you drag up and right, it'll show up above and to the right of where you started dragging, etc.
let offsetX = eventPoint.x - startPos.x;
let offsetY = eventPoint.y - startPos.y;
// If the offset variables are zero, the shape ends up having zero width or height, which is bad.
// Deal with this by forcing them to be non-zero (we arbitrarily choose 1; any non-zero value would work).
offsetX = offsetX ? offsetX : 1;
offsetY = offsetY ? offsetY : 1;
// The length of the shape is the greater of the X and Y offsets.
const offsetDistance = eventPoint.subtract(startPos).abs();
const length = Math.max(offsetDistance.x, offsetDistance.y);
const size = new paper.Point(
length * offsetX / Math.abs(offsetX),
length * offsetY / Math.abs(offsetY)
);
const position = startPos.add(size.multiply(0.5));
return {size, position};
};
export { export {
HANDLE_RATIO, HANDLE_RATIO,
checkPointsClose, checkPointsClose,
@ -138,6 +171,7 @@ export {
expandBy, expandBy,
getRandomInt, getRandomInt,
getRandomBoolean, getRandomBoolean,
getSquareDimensions,
scaleWithStrokes, scaleWithStrokes,
snapDeltaToAngle, snapDeltaToAngle,
sortItemsByZIndex sortItemsByZIndex

View file

@ -2,6 +2,7 @@ import paper from '@scratch/paper';
import Modes from '../../lib/modes'; import Modes from '../../lib/modes';
import {styleShape} from '../style-path'; import {styleShape} from '../style-path';
import {clearSelection} from '../selection'; import {clearSelection} from '../selection';
import {getSquareDimensions} from '../math';
import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import BoundingBoxTool from '../selection-tools/bounding-box-tool';
import NudgeTool from '../selection-tools/nudge-tool'; import NudgeTool from '../selection-tools/nudge-tool';
@ -88,17 +89,20 @@ class OvalTool extends paper.Tool {
const downPoint = new paper.Point(event.downPoint.x, event.downPoint.y); const downPoint = new paper.Point(event.downPoint.x, event.downPoint.y);
const point = new paper.Point(event.point.x, event.point.y); const point = new paper.Point(event.point.x, event.point.y);
const squareDimensions = getSquareDimensions(event.downPoint, event.point);
if (event.modifiers.shift) { if (event.modifiers.shift) {
this.oval.size = new paper.Point(event.downPoint.x - event.point.x, event.downPoint.x - event.point.x); this.oval.size = squareDimensions.size.abs();
} else { } else {
this.oval.size = downPoint.subtract(point); this.oval.size = downPoint.subtract(point);
} }
if (event.modifiers.alt) { if (event.modifiers.alt) {
this.oval.position = downPoint; this.oval.position = downPoint;
} else if (event.modifiers.shift) {
this.oval.position = squareDimensions.position;
} else { } else {
this.oval.position = downPoint.subtract(this.oval.size.multiply(0.5)); this.oval.position = downPoint.subtract(this.oval.size.multiply(0.5));
} }
} }
handleMouseUp (event) { handleMouseUp (event) {
if (event.event.button > 0 || !this.active) return; // only first mouse button if (event.event.button > 0 || !this.active) return; // only first mouse button

View file

@ -2,6 +2,7 @@ import paper from '@scratch/paper';
import Modes from '../../lib/modes'; import Modes from '../../lib/modes';
import {styleShape} from '../style-path'; import {styleShape} from '../style-path';
import {clearSelection} from '../selection'; import {clearSelection} from '../selection';
import {getSquareDimensions} from '../math';
import BoundingBoxTool from '../selection-tools/bounding-box-tool'; import BoundingBoxTool from '../selection-tools/bounding-box-tool';
import NudgeTool from '../selection-tools/nudge-tool'; import NudgeTool from '../selection-tools/nudge-tool';
@ -85,18 +86,20 @@ class RectTool extends paper.Tool {
this.rect.remove(); this.rect.remove();
} }
const dimensions = event.point.subtract(event.downPoint);
const rect = new paper.Rectangle(event.downPoint, event.point); const rect = new paper.Rectangle(event.downPoint, event.point);
const squareDimensions = getSquareDimensions(event.downPoint, event.point);
if (event.modifiers.shift) { if (event.modifiers.shift) {
rect.height = rect.width; rect.size = squareDimensions.size.abs();
dimensions.y = event.downPoint.y > event.point.y ? -Math.abs(rect.width) : Math.abs(rect.width);
} }
this.rect = new paper.Path.Rectangle(rect);
this.rect = new paper.Path.Rectangle(rect);
if (event.modifiers.alt) { if (event.modifiers.alt) {
this.rect.position = event.downPoint; this.rect.position = event.downPoint;
} else if (event.modifiers.shift) {
this.rect.position = squareDimensions.position;
} else { } else {
this.rect.position = event.downPoint.add(dimensions.multiply(.5)); const dimensions = event.point.subtract(event.downPoint);
this.rect.position = event.downPoint.add(dimensions.multiply(0.5));
} }
styleShape(this.rect, this.colorState); styleShape(this.rect, this.colorState);