Skip to content

Commit 212bfa0

Browse files
authored
bracket annotation support (#50)
1 parent e1d7e1b commit 212bfa0

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

src/model.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ export interface Rect {
99
h: number;
1010
}
1111

12-
export type RoughAnnotationType = 'underline' | 'box' | 'circle' | 'highlight' | 'strike-through' | 'crossed-off';
12+
export type RoughAnnotationType = 'underline' | 'box' | 'circle' | 'highlight' | 'strike-through' | 'crossed-off' | 'bracket';
1313
export type FullPadding = [number, number, number, number];
1414
export type RoughPadding = number | [number, number] | FullPadding;
15+
export type BracketType = 'left' | 'right' | 'top' | 'bottom';
1516

1617
export interface RoughAnnotationConfig extends RoughAnnotationConfigBase {
1718
type: RoughAnnotationType;
@@ -25,6 +26,7 @@ export interface RoughAnnotationConfigBase {
2526
strokeWidth?: number; // default based on type
2627
padding?: RoughPadding; // defaults to 5px
2728
iterations?: number; // defaults to 2
29+
brackets?: BracketType | BracketType[]; // defaults to 'right'
2830
}
2931

3032
export interface RoughAnnotation extends RoughAnnotationConfigBase {

src/render.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import { Rect, RoughAnnotationConfig, SVG_NS, FullPadding } from './model.js';
1+
import { Rect, RoughAnnotationConfig, SVG_NS, FullPadding, BracketType } from './model.js';
22
import { ResolvedOptions, OpSet } from 'roughjs/bin/core';
3-
import { line, rectangle, ellipse } from 'roughjs/bin/renderer';
3+
import { line, rectangle, ellipse, linearPath } from 'roughjs/bin/renderer';
4+
import { Point } from 'roughjs/bin/geometry';
45

56
type RoughOptionsType = 'highlight' | 'single' | 'double';
67

@@ -97,6 +98,55 @@ export function renderAnnotation(svg: SVGSVGElement, rect: Rect, config: RoughAn
9798
}
9899
break;
99100
}
101+
case 'bracket': {
102+
const o = getOptions('single', seed);
103+
const brackets: BracketType[] = Array.isArray(config.brackets) ? config.brackets : (config.brackets ? [config.brackets] : ['right']);
104+
const lx = rect.x - padding[3] * 2;
105+
const rx = rect.x + rect.w + padding[1] * 2;
106+
const ty = rect.y - padding[0] * 2;
107+
const by = rect.y + rect.h + padding[2] * 2;
108+
for (const br of brackets) {
109+
let points: Point[];
110+
switch (br) {
111+
case 'bottom':
112+
points = [
113+
[lx, rect.y + rect.h],
114+
[lx, by],
115+
[rx, by],
116+
[rx, rect.y + rect.h]
117+
];
118+
break;
119+
case 'top':
120+
points = [
121+
[lx, rect.y],
122+
[lx, ty],
123+
[rx, ty],
124+
[rx, rect.y]
125+
];
126+
break;
127+
case 'left':
128+
points = [
129+
[rect.x, ty],
130+
[lx, ty],
131+
[lx, by],
132+
[rect.x, by]
133+
];
134+
break;
135+
case 'right':
136+
points = [
137+
[rect.x + rect.w, ty],
138+
[rx, ty],
139+
[rx, by],
140+
[rect.x + rect.w, by]
141+
];
142+
break;
143+
}
144+
if (points) {
145+
opList.push(linearPath(points, false, o));
146+
}
147+
}
148+
break;
149+
}
100150
case 'crossed-off': {
101151
const o = getOptions('single', seed);
102152
const x = rect.x;

0 commit comments

Comments
 (0)