From 212bfa06bd5e2dde1955b91c56848864dbc30424 Mon Sep 17 00:00:00 2001 From: Preet <833927+pshihn@users.noreply.github.com> Date: Mon, 22 Jun 2020 20:28:41 -0700 Subject: [PATCH] bracket annotation support (#50) --- src/model.ts | 4 +++- src/render.ts | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/model.ts b/src/model.ts index b82bb12..ee51853 100644 --- a/src/model.ts +++ b/src/model.ts @@ -9,9 +9,10 @@ export interface Rect { h: number; } -export type RoughAnnotationType = 'underline' | 'box' | 'circle' | 'highlight' | 'strike-through' | 'crossed-off'; +export type RoughAnnotationType = 'underline' | 'box' | 'circle' | 'highlight' | 'strike-through' | 'crossed-off' | 'bracket'; export type FullPadding = [number, number, number, number]; export type RoughPadding = number | [number, number] | FullPadding; +export type BracketType = 'left' | 'right' | 'top' | 'bottom'; export interface RoughAnnotationConfig extends RoughAnnotationConfigBase { type: RoughAnnotationType; @@ -25,6 +26,7 @@ export interface RoughAnnotationConfigBase { strokeWidth?: number; // default based on type padding?: RoughPadding; // defaults to 5px iterations?: number; // defaults to 2 + brackets?: BracketType | BracketType[]; // defaults to 'right' } export interface RoughAnnotation extends RoughAnnotationConfigBase { diff --git a/src/render.ts b/src/render.ts index 0367155..c7af094 100644 --- a/src/render.ts +++ b/src/render.ts @@ -1,6 +1,7 @@ -import { Rect, RoughAnnotationConfig, SVG_NS, FullPadding } from './model.js'; +import { Rect, RoughAnnotationConfig, SVG_NS, FullPadding, BracketType } from './model.js'; import { ResolvedOptions, OpSet } from 'roughjs/bin/core'; -import { line, rectangle, ellipse } from 'roughjs/bin/renderer'; +import { line, rectangle, ellipse, linearPath } from 'roughjs/bin/renderer'; +import { Point } from 'roughjs/bin/geometry'; type RoughOptionsType = 'highlight' | 'single' | 'double'; @@ -97,6 +98,55 @@ export function renderAnnotation(svg: SVGSVGElement, rect: Rect, config: RoughAn } break; } + case 'bracket': { + const o = getOptions('single', seed); + const brackets: BracketType[] = Array.isArray(config.brackets) ? config.brackets : (config.brackets ? [config.brackets] : ['right']); + const lx = rect.x - padding[3] * 2; + const rx = rect.x + rect.w + padding[1] * 2; + const ty = rect.y - padding[0] * 2; + const by = rect.y + rect.h + padding[2] * 2; + for (const br of brackets) { + let points: Point[]; + switch (br) { + case 'bottom': + points = [ + [lx, rect.y + rect.h], + [lx, by], + [rx, by], + [rx, rect.y + rect.h] + ]; + break; + case 'top': + points = [ + [lx, rect.y], + [lx, ty], + [rx, ty], + [rx, rect.y] + ]; + break; + case 'left': + points = [ + [rect.x, ty], + [lx, ty], + [lx, by], + [rect.x, by] + ]; + break; + case 'right': + points = [ + [rect.x + rect.w, ty], + [rx, ty], + [rx, by], + [rect.x + rect.w, by] + ]; + break; + } + if (points) { + opList.push(linearPath(points, false, o)); + } + } + break; + } case 'crossed-off': { const o = getOptions('single', seed); const x = rect.x;