@meta2d/core
Version:
@meta2d/core: Powerful, Beautiful, Simple, Open - Web-Based 2D At Its Best .
227 lines • 6.81 kB
JavaScript
import { Direction } from '../../data';
import { facePen, getToAnchor } from '../../pen';
import { distance, PrevNextType, rotatePoint } from '../../point';
import { s8 } from '../../utils';
export function curve(store, pen, mousedwon) {
if (!pen.calculative.worldAnchors) {
pen.calculative.worldAnchors = [];
}
if (mousedwon) {
if (pen.calculative.activeAnchor) {
pen.calculative.activeAnchor.next = {
penId: pen.id,
x: mousedwon.x,
y: mousedwon.y,
};
if (distance(pen.calculative.activeAnchor.next, pen.calculative.activeAnchor) < 5) {
pen.calculative.activeAnchor.next = undefined;
}
else {
pen.calculative.activeAnchor.prev = {
...pen.calculative.activeAnchor.next,
};
rotatePoint(pen.calculative.activeAnchor.prev, 180, pen.calculative.activeAnchor);
}
}
}
else {
const from = pen.calculative.worldAnchors[0];
if (!from.next) {
const fromFace = facePen(from, store.pens[from.connectTo]);
calcCurveCP(from, fromFace, 50);
from.prev = undefined;
}
const to = pen.calculative.worldAnchors[pen.calculative.worldAnchors.length - 1];
if (to && to !== from && !to.prev) {
const toFace = facePen(to, store.pens[to.connectTo]);
calcCurveCP(to, toFace, -50);
to.next = undefined;
}
}
}
function calcCurveCP(pt, d, dis) {
switch (d) {
case Direction.Up:
pt.prev = {
penId: pt.penId,
x: pt.x,
y: pt.y + dis,
};
pt.next = {
penId: pt.penId,
x: pt.x,
y: pt.y - dis,
};
break;
case Direction.Right:
pt.prev = {
penId: pt.penId,
x: pt.x - dis,
y: pt.y,
};
pt.next = {
penId: pt.penId,
x: pt.x + dis,
y: pt.y,
};
break;
case Direction.Bottom:
pt.prev = {
penId: pt.penId,
x: pt.x,
y: pt.y - dis,
};
pt.next = {
penId: pt.penId,
x: pt.x,
y: pt.y + dis,
};
break;
case Direction.Left:
pt.prev = {
penId: pt.penId,
x: pt.x + dis,
y: pt.y,
};
pt.next = {
penId: pt.penId,
x: pt.x - dis,
y: pt.y,
};
break;
}
}
// Get a point in quadratic.
// pos - The position of point in quadratic. It is expressed as a percentage(0 - 1).
export function getQuadraticPoint(step, from, cp, to) {
const pos = 1 - step;
const x = pos * pos * from.x + 2 * pos * step * cp.x + step * step * to.x;
const y = pos * pos * from.y + 2 * pos * step * cp.y + step * step * to.y;
return { x, y, step };
}
// Get a point in bezier.
// pos - The position of point in bezier. It is expressed as a percentage(0 - 1).
export function getBezierPoint(step, from, cp1, cp2, to) {
const { x: x1, y: y1 } = from;
const { x: x2, y: y2 } = to;
const { x: cx1, y: cy1 } = cp1;
const { x: cx2, y: cy2 } = cp2;
const pos = 1 - step;
const x = x1 * pos * pos * pos +
3 * cx1 * step * pos * pos +
3 * cx2 * step * step * pos +
x2 * step * step * step;
const y = y1 * pos * pos * pos +
3 * cy1 * step * pos * pos +
3 * cy2 * step * step * pos +
y2 * step * step * step;
return { x, y, step };
}
function lerp(pt1, pt2, t) {
return {
x: pt1.x + t * (pt2.x - pt1.x),
y: pt1.y + t * (pt2.y - pt1.y),
};
}
export function getSplitAnchor(pen, pt, index) {
let from = pen.calculative.worldAnchors[index];
let to = pen.calculative.worldAnchors[index + 1];
if (!to && pen.close) {
to = pen.calculative.worldAnchors[0];
}
const t = pt.step;
let anchor;
if (from.next && to.prev) {
const p0 = from;
const p1 = from.next;
const p2 = to.prev;
const p3 = to;
const p4 = lerp(p0, p1, t);
const p5 = lerp(p1, p2, t);
const p6 = lerp(p2, p3, t);
const p7 = lerp(p4, p5, t);
const p8 = lerp(p5, p6, t);
anchor = lerp(p7, p8, t);
p7.penId = pen.id;
anchor.prev = p7;
p8.penId = pen.id;
anchor.next = p8;
from.next.x = p4.x;
from.next.y = p4.y;
to.prev.x = p6.x;
to.prev.y = p6.y;
}
else if (from.next || to.prev) {
const p0 = from;
const p1 = from.next || to.prev;
const p2 = to;
const p3 = lerp(p0, p1, t);
const p4 = lerp(p1, p2, t);
anchor = pt;
p3.penId = pen.id;
p4.penId = pen.id;
anchor.prev = p3;
anchor.next = p4;
from.next = undefined;
to.prev = undefined;
}
else {
// 并非贝塞尔点,即 from 和 to 之间是一条直线
anchor = pt;
}
anchor.penId = pen.id;
anchor.id = s8();
anchor.prevNextType = PrevNextType.Bilateral;
return anchor;
}
export function mind(store, pen, mousedwon) {
if (!pen.calculative.worldAnchors) {
pen.calculative.worldAnchors = [];
}
if (pen.calculative.worldAnchors.length < 2) {
return;
}
let from = pen.calculative.activeAnchor;
let to = mousedwon || getToAnchor(pen);
if (!from || !to) {
return;
}
const dis = 20;
const fromPen = store.pens[from.connectTo];
let fromFace = facePen(from, fromPen);
if (fromFace === Direction.None) {
if (to.x > from.x) {
fromFace = Direction.Right;
}
else {
fromFace = Direction.Left;
}
}
from.next = {
id: s8(),
penId: pen.id,
x: from.x,
y: from.y,
prevNextType: 2,
};
to.prev = { id: s8(), penId: pen.id, x: to.x, y: to.y, prevNextType: 2 };
switch (fromFace) {
case Direction.Up:
from.next.y -= dis;
to.prev.y = from.y;
break;
case Direction.Bottom:
from.next.y += dis;
to.prev.y = from.y;
break;
case Direction.Left:
from.next.x -= dis;
to.prev.x = from.x;
break;
default:
from.next.x += dis;
to.prev.x = from.x;
break;
}
}
//# sourceMappingURL=curve.js.map