drawing an arc on Canvas #418
-
Hi, Does anybody know a way to draw a simple I've tried below but the const arc1 = arc([200, 200], 160, 0, 0, Math.PI);
const arc2 = pathFromCubics(
asCubic(arc([200, 200], 200, 0, 0, Math.PI)),
);
// from @thi.ng/hiccup-canvas
draw(ctx, group({ stroke: "pink", weight: 12 }, [arc1, arc2])); |
Beta Was this translation helpful? Give feedback.
Replies: 8 comments 6 replies
-
Hi @cdaein, there's another way to draw elliptic arcs, but currently it's not compatible with using thi.ng/geom arcs (you'll have to use plain hiccup syntax for those shapes). I will explain below. Here's how you can draw elliptic arcs right now: draw(ctx, [
"ellipse",
{ stroke: "#000" },
// center
[300, 300],
// radii (x, y)
[200, 100],
// x-axis rotation
0.5,
// start angle (radians)
0,
// end angle (radians)
Math.PI * 1.5,
// counterclockwise flag
false
]); This is an old known issue (#69, also see related section in readme) and apart from the initial oversight on my part, it's actually much more down to incompatibilities between the HTML Canvas API and how arcs are defined in SVG (incl. as part of SVG paths) and therefore also with the same discrepancies between thi.ng/geom & hiccup-canvas. Multiple aspects to that (e.g. defining arcs from center vs end points), but somewhere (likely in hiccup-canvas) a breaking change will need to be introduced, something I've been putting off so far, also because it's been a pretty low priority for me. But I will take another look at it! Just for reference (also for myself): |
Beta Was this translation helpful? Give feedback.
-
I appreciate your response! In this case, const arc1 = [
"arc",
{ stroke: "black" },
[400, 400],
200,
0,
Math.PI,
false,
];
draw(ctx, arc1); If I may ask you a follow up question, is there a type that goes with the hiccup shape format instead of treating as a regular array? |
Beta Was this translation helpful? Give feedback.
-
Hey, of course you can! If you mean class wrappers for arcs (and other shape types), yes, they are're all defined here: https://github.com/thi-ng/umbrella/tree/develop/packages/geom/src/api There you can also see how these types can convert themselves to hiccup format by implementing the generic umbrella/packages/geom/src/api/circle.ts Lines 25 to 27 in 83d5610 ...or a more complex case: umbrella/packages/geom/src/api/arc.ts Lines 87 to 107 in 83d5610 Each of these classes has one or more corresponding factory functions, e.g. Is that what you meant? As I tried to explain (sorry if I wasn't doing a good job), the current issue with arcs (and the reason for having to use plain hiccup arrays) is that still existing issue/incompatibility between canvas API & SVG. But this only applies to (elliptic) arcs, i.e. what the above linked |
Beta Was this translation helpful? Give feedback.
-
Your explanation was perfect to understand the canvas/svg incompatibility as to how elliptic arc works. // IHiccupShape type doesn't work here
const arc1: IHiccupShape = [
"arc",
{ stroke: "black" },
[400, 400],
200,
0,
Math.PI,
false,
]; |
Beta Was this translation helpful? Give feedback.
-
Oh sorry, I see what you mean now - my bad... Here's the definition of the umbrella/packages/geom-api/src/shape.ts Line 39 in 83d5610 Since you only seem to be interested in circular arcs, I think for the time being (until this underlying issue will be fixed), you could use a temporary "circular arc" shape type, something like: import type { Attribs, IHiccupShape } from "@thi.ng/geom-api";
import { __copyAttribs } from "@thi.ng/geom/internal/copy";
import { TAU } from "@thi.ng/math/api";
import { set2, type Vec } from "@thi.ng/vectors";
export class CircularArc implements IHiccupShape {
constructor(
public pos: Vec = [0, 0],
public r = 1,
public start = 0,
public end = TAU,
public ccw = false,
public attribs?: Attribs
) {}
get type() {
return "arc";
}
copy(): CircularArc {
return new CircularArc(set2([], this.pos), this.r, this.start, this.end, this.ccw, __copyAttribs(this));
}
withAttribs(attribs: Attribs): CircularArc {
return new CircularArc(this.pos, this.r, this.start, this.end, this.ccw, attribs);
}
toHiccup() {
// temporary situation only: "arc" shape type ID is already used by
// elliptic arcs in thi.ng/geom & thi.ng/hiccup-svg, but refers to
// circular arcs in thi.ng/hiccup-canvas - this is BAD!!!
// this all needs to be resolved asap!
return ["arc", this.attribs, this.pos, this.r, this.start, this.end, this.ccw];
}
} This type at least conforms to the Also, I haven't tested this above class yet, but hope this works. Please let me know! :) |
Beta Was this translation helpful? Give feedback.
-
Thank you! I was looking for something like: type HiccupArc = [
"arc",
{ [key: string]: any },
Vec,
number,
number,
number,
boolean,
];
const arc2: HiccupArc = [
"arc",
{ stroke: "black", weight: 40 },
[400, 400],
100,
0,
Math.PI,
false,
]; but with your class implementation, I can now make it work like: const arc1 = new CircularArc([400, 400], 200, 0, Math.PI, false, {
stroke: "black",
weight: 40,
});
draw(ctx, arc1); |
Beta Was this translation helpful? Give feedback.
-
@cdaein An exciting update on this: I just fixed #69 and the next release (maybe later today or tomorrow) will support both paths with elliptic arc segments and/or holes (at last!). I've updated the readme already: https://github.com/thi-ng/umbrella/tree/develop/packages/hiccup-canvas#path |
Beta Was this translation helpful? Give feedback.
-
Thank you for the update! I was just trying out the circular arc with const arc1 = arc([200, 200], 160, 0, 0, Math.PI * 0.5);
const arc2 = pathFromCubics(
asCubic(arc([200, 200], 200, 0, 0, Math.PI * 0.5)),
);
draw(ctx, group({ stroke: "pink", weight: 12 }, [arc1]));
draw(ctx, group({ stroke: "lightgreen", weight: 12 }, [arc2])); |
Beta Was this translation helpful? Give feedback.
Hi @cdaein, there's another way to draw elliptic arcs, but currently it's not compatible with using thi.ng/geom arcs (you'll have to use plain hiccup syntax for those shapes). I will explain below. Here's how you can draw elliptic arcs right now:
This is an old known issue (#69, also see related section in readme) and apart from the initial oversight on my part, it's actually much more down to incompatibilities between the HTML Canvas API and how arcs are defin…