Arranging: boxes on everything, handwriting movable, the Eraser's preview, a Circle shape, pixel-exact cues
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
03907da8c9
commit
24a6a2595b
10 files changed
+690
-126
No files matched your search
+27
-5
@@ -31,11 +31,11 @@ import { NOMINAL_PRESSURE } from './pen_input.js';
|
||||
import { POINT_SIZE } from './page_model.js';
|
||||
|
||||
/** The shapes, in the order of the menu. The first is the default. */
|
||||
export const SHAPES = /** @type {const} */ (['rectangle', 'ellipse', 'line', 'arrow']);
|
||||
export const SHAPES = /** @type {const} */ (['rectangle', 'circle', 'ellipse', 'line', 'arrow']);
|
||||
/** @typedef {typeof SHAPES[number]} Shape */
|
||||
|
||||
/** @type {Record<Shape, string>} What the button and the menu call each shape. */
|
||||
export const SHAPE_NAMES = { rectangle: 'Rectangle', ellipse: 'Ellipse', line: 'Line', arrow: 'Arrow' };
|
||||
export const SHAPE_NAMES = { rectangle: 'Rectangle', circle: 'Circle', ellipse: 'Ellipse', line: 'Line', arrow: 'Arrow' };
|
||||
|
||||
/** The key under which the browser remembers the chosen shape. */
|
||||
export const SHAPE_KEY = 'kokkoja_shape';
|
||||
@@ -149,7 +149,10 @@ export function ellipsePoints(x0, y0, x1, y1) {
|
||||
// Ramanujan's approximation of the circumference.
|
||||
const h = ((rx - ry) / (rx + ry)) ** 2 || 0;
|
||||
const circumference = Math.PI * (rx + ry) * (1 + 3 * h / (10 + Math.sqrt(4 - 3 * h)));
|
||||
const count = Math.max(LEAST_ELLIPSE_POINTS, Math.min(MOST_ELLIPSE_POINTS, Math.ceil(circumference / ELLIPSE_STEP)));
|
||||
// A multiple of four, so that a point lies at each end of both axes and
|
||||
// the rectangle around the points is exactly the ellipse's (Arrange's
|
||||
// box and a circle's proportions depend on it).
|
||||
const count = Math.max(LEAST_ELLIPSE_POINTS, Math.min(MOST_ELLIPSE_POINTS, 4 * Math.ceil(circumference / ELLIPSE_STEP / 4)));
|
||||
/** @type {number[]} */
|
||||
const points = [];
|
||||
for (let i = 0; i <= count; i++) {
|
||||
@@ -159,6 +162,21 @@ export function ellipsePoints(x0, y0, x1, y1) {
|
||||
return points;
|
||||
}
|
||||
|
||||
/**
|
||||
* A circle about its centre (cx, cy), the radius reaching the dragged
|
||||
* point (Andy, 2026-10-14: the centre first, then the radius in any
|
||||
* direction).
|
||||
* @param {number} cx
|
||||
* @param {number} cy
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @returns {number[]}
|
||||
*/
|
||||
export function circlePoints(cx, cy, x, y) {
|
||||
const radius = Math.hypot(x - cx, y - cy);
|
||||
return ellipsePoints(cx - radius, cy - radius, cx + radius, cy + radius);
|
||||
}
|
||||
|
||||
/**
|
||||
* An arrow from (x0, y0) to its tip at (x1, y1), as the outline of a
|
||||
* filled polygon: the shaft as wide as the line, the head wider, its
|
||||
@@ -202,7 +220,9 @@ export function arrowPoints(x0, y0, x1, y1, width) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The points of a shape dragged open from (x0, y0) to (x1, y1).
|
||||
* The points of a shape dragged open from (x0, y0) to (x1, y1): a
|
||||
* circle from its centre to a point of its edge, the others from one
|
||||
* corner of their rectangle to the opposite one.
|
||||
* @param {Shape} shape Not 'line', which is made of taps.
|
||||
* @param {number} x0
|
||||
* @param {number} y0
|
||||
@@ -214,6 +234,7 @@ export function arrowPoints(x0, y0, x1, y1, width) {
|
||||
export function draggedPoints(shape, x0, y0, x1, y1, width) {
|
||||
switch (shape) {
|
||||
case 'rectangle': return rectanglePoints(x0, y0, x1, y1);
|
||||
case 'circle': return circlePoints(x0, y0, x1, y1);
|
||||
case 'ellipse': return ellipsePoints(x0, y0, x1, y1);
|
||||
case 'arrow': return arrowPoints(x0, y0, x1, y1, width);
|
||||
default: return straightPoints([[x0, y0], [x1, y1]]);
|
||||
@@ -224,7 +245,8 @@ export function draggedPoints(shape, x0, y0, x1, y1, width) {
|
||||
* The points of a shape moved or resized by Arrange from the rectangle
|
||||
* around its points to another: every point carried along (a rectangle
|
||||
* stays a rectangle, an ellipse an ellipse, a line keeps its angles'
|
||||
* proportions), except an arrow, which is made afresh from its tail and
|
||||
* proportions; a circle is resized with its shape kept, so stays one),
|
||||
* except an arrow, which is made afresh from its tail and
|
||||
* tip carried along, so that its head and shaft keep the line's width.
|
||||
* @param {import('./page_model.js').Stroke} stroke
|
||||
* @param {import('./page_model.js').Rectangle} from
|
||||
|
||||
Reference in new issue
Block a user