jcanvas
Version:
jCanvas brings jQuery's powerful syntax and capability to the HTML5 canvas. Quickly create canvas-based apps that can utilize layers, animations, events, and much more. jCanvas works on all modern browsers and platforms, including iOS and Android.
106 lines (97 loc) • 2.24 kB
text/typescript
/**
* @license jCanvas Crescents
* Copyright 2013-2024 Caleb Evans
* Released under the MIT license
*/
import $ from "jquery";
// Cache some functions and constants
const pow = Math.pow,
sqrt = Math.sqrt,
PI = Math.PI;
// Get the topmost intersection point of two circles
function getIntersection(
x0: number,
y0: number,
r0: number,
x1: number,
y1: number,
r1: number
): [number, number] | null {
const dx = x1 - x0,
dy = y1 - y0,
d = sqrt(pow(dx, 2) + pow(dy, 2)),
a = (pow(d, 2) + pow(r0, 2) - pow(r1, 2)) / (2 * d),
x2 = x0 + (dx * a) / d,
y2 = y0 + (dy * a) / d,
h = sqrt(pow(r0, 2) - pow(a, 2)),
rx = -dy * (h / d),
ry = dx * (h / d),
xi = x2 + rx,
yi = y2 + ry;
// Check if circles do not intersect or overlap completely
if (d > r0 + r1 || d < Math.abs(r0 - r1)) {
return null;
}
return [xi, yi];
}
$.jCanvas.extend({
name: "drawCrescent",
type: "crescent",
props: {
eclipse: 0.5,
},
fn: function (ctx, params) {
const dist = 2 * params.radius * (1 - params.eclipse);
const intersection = getIntersection(
params.x,
params.y,
params.radius,
params.x + dist,
params.y,
params.radius
);
if (!intersection) {
return;
}
const x = intersection[0] - params.x;
const y = intersection[1] - params.y;
const t = Math.atan2(y, x);
let start: number;
let end: number;
if (params.eclipse <= 0) {
// Show full circle if circle is not eclipsed
start = 0;
end = 2 * PI;
} else {
// Otherwise, show eclipsed circle
start = t;
end = -t;
}
// If circle is not fully eclipsed
if (params.eclipse < 1) {
// Draw crescent shape
// Enable shape transformation
$.jCanvas.transformShape(this, ctx, params);
ctx.beginPath();
// Draw full circle
ctx.arc(params.x, params.y, params.radius, start, end, false);
// If circle is eclipsed to some degree
if (params.eclipse > 0) {
// Draw crescent region in circle
ctx.arc(
params.x + dist,
params.y,
params.radius,
PI + start,
PI + end,
true
);
}
// Enable jCanvas events
$.jCanvas.detectEvents(this, ctx, params);
// Always close path
params.closed = true;
$.jCanvas.closePath(this, ctx, params);
}
},
});