diff --git a/README.md b/README.md index c334bbc..10cf31d 100644 --- a/README.md +++ b/README.md @@ -90,9 +90,9 @@ String value representing the color of the annotation sketch. Default value is ` #### strokeWidth Width of the annotation strokes. Default value is `1`. - #### padding Padding between the element and roughly where the annotation is drawn. Default value is `5` (in pixels). +If you wish to specify different `top`, `left`, `right`, `bottom` paddings, you can set the value to an array akin to CSS style padidng `[top, right, bottom, left]` or just `[top & bottom, left & right]`. ## Annotation Object diff --git a/src/model.ts b/src/model.ts index 85f439e..48aafe8 100644 --- a/src/model.ts +++ b/src/model.ts @@ -10,6 +10,8 @@ export interface Rect { } export type RoughAnnotationType = 'underline' | 'box' | 'circle' | 'highlight' | 'strike-through' | 'crossed-off'; +export type FullPadding = [number, number, number, number]; +export type RoughPadding = number | [number, number] | FullPadding; export interface RoughAnnotationConfig { type: RoughAnnotationType; @@ -18,7 +20,7 @@ export interface RoughAnnotationConfig { animationDelay?: number; // default = 0 color?: string; // defaults to currentColor strokeWidth?: number; // default based on type - padding?: number; // defaults to 5px + padding?: RoughPadding; // defaults to 5px iterations?: number; // defaults to 2 } diff --git a/src/render.ts b/src/render.ts index b012ac5..106be7e 100644 --- a/src/render.ts +++ b/src/render.ts @@ -1,4 +1,4 @@ -import { Rect, RoughAnnotationConfig, SVG_NS, DEFAULT_ANIMATION_DURATION } from './model.js'; +import { Rect, RoughAnnotationConfig, SVG_NS, DEFAULT_ANIMATION_DURATION, FullPadding } from './model.js'; import { ResolvedOptions, OpSet } from 'roughjs/bin/core'; import { line, rectangle, ellipse } from 'roughjs/bin/renderer'; @@ -29,16 +29,42 @@ const highlightOptions = JSON.parse(JSON.stringify(defaultOptions)); highlightOptions.roughness = 3; highlightOptions.disableMultiStroke = true; +function parsePadding(config: RoughAnnotationConfig): FullPadding { + const p = config.padding; + if (p || (p === 0)) { + if (typeof p === 'number') { + return [p, p, p, p]; + } else if (Array.isArray(p)) { + const pa = p as number[]; + if (pa.length) { + switch (pa.length) { + case 4: + return [...pa] as FullPadding; + case 1: + return [pa[0], pa[0], pa[0], pa[0]]; + case 2: + return [...pa, ...pa] as FullPadding; + case 3: + return [...pa, pa[1]] as FullPadding; + default: + return [pa[0], pa[1], pa[2], pa[3]]; + } + } + } + } + return [5, 5, 5, 5]; +} + export function renderAnnotation(svg: SVGSVGElement, rect: Rect, config: RoughAnnotationConfig, animationGroupDelay: number) { const opList: OpSet[] = []; let strokeWidth = config.strokeWidth || 2; - const padding = (config.padding === 0) ? 0 : (config.padding || 5); + const padding = parsePadding(config); const animate = (config.animate === undefined) ? true : (!!config.animate); const iterations = config.iterations || 2; switch (config.type) { case 'underline': { - const y = rect.y + rect.h + padding; + const y = rect.y + rect.h + padding[2]; for (let i = 0; i < iterations; i++) { if (i % 2) { opList.push(line(rect.x + rect.w, y, rect.x, y, singleStrokeOptions)); @@ -60,10 +86,10 @@ export function renderAnnotation(svg: SVGSVGElement, rect: Rect, config: RoughAn break; } case 'box': { - const x = rect.x - padding; - const y = rect.y - padding; - const width = rect.w + (2 * padding); - const height = rect.h + (2 * padding); + const x = rect.x - padding[3]; + const y = rect.y - padding[0]; + const width = rect.w + (padding[1] + padding[3]); + const height = rect.h + (padding[0] + padding[2]); for (let i = 0; i < iterations; i++) { opList.push(rectangle(x, y, width, height, singleStrokeOptions)); } @@ -91,11 +117,10 @@ export function renderAnnotation(svg: SVGSVGElement, rect: Rect, config: RoughAn break; } case 'circle': { - const p2 = padding * 2; - const width = rect.w + (2 * p2); - const height = rect.h + (2 * p2); - const x = rect.x - p2 + (width / 2); - const y = rect.y - p2 + (height / 2); + const width = rect.w + (padding[1] + padding[3]); + const height = rect.h + (padding[0] + padding[2]); + const x = rect.x - padding[3] + (width / 2); + const y = rect.y - padding[0] + (height / 2); const fullItr = Math.floor(iterations / 2); const singleItr = iterations - (fullItr * 2); for (let i = 0; i < fullItr; i++) {