@procore/markup-viewer v3.0.1
Markup Viewer
Getting Started
Installation
npm i -S @procore/markup-viewer
Importing
// index.js
import MarkupViewer, {
tools,
EVENT_CONSTANTS,
TRIGGER_CONSTANTS,
} from '@procore/markup-viewer';Usage
const options = { tools, htmlText: '<div></div>' };
const markupViewer = new MarkupViewer(options);Creating a new instance of MarkupViewer adds all of the DOM elements needed to display the viewer on the page.
OptionsObject:
Keys:
- tools
object- pass in the tools that should be available to in the markupViewer - initialHtmlTextt
string- A valid HTML string, representing the page to be shown
Events
An instance of MarkupViewer exposes the following methods, which ar responsible for all interactions with the markupViewer.
on(eventKey, callback)off(eventKey, callback)trigger(eventKey, callbackArg)
By default, a set of events keys are exported as constants from MarkupViewer.
TRIGGER_CONSTANTS- Use these when to tell
markupViewerwhat to do.
- Use these when to tell
EVENT_CONSTANTS- Use these for listening for information from
markupViewer
- Use these for listening for information from
Every constant in TRIGGER_CONSTANTS has a pair in EVENT_CONSTANTS to be used as an acknowledgement or to respond to updated data.
Example
// index.js
import MarkupViewer, {
tools,
EVENT_CONSTANTS,
TRIGGER_CONSTANTS,
} from '@procore/markup-viewer';
const options = {
tools: {
rect: tools.rect,
},
};
const markupViewer = new MarkupViewer(options);
// Function to be called after the shape is drawn
// Payload contains: { e: last mouseEvent, svg: string representing the shape }
const rectCB = (payload) => console.log(payload);
// Subscribe to the rect tool
markupViewer.on(EVENT_CONSTANTS.DRAW_COMPLETE, rectCB);
// Activate the rect tool
// Can take an options object as an optional second parameter
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, { toolKey: 'rect' });Later:
// Clean up subscription if you are done with it
markupViewer.off(EVENT_CONSTANTS.DRAW_COMPLETE, rectCB);Working with Redux
For convenience, EVENT_CONSTANTS contains a super-listener for subscribing to all markupViewer events. When markupViewer is triggered, two events will be broadcast. EVENT_CONSTANTS.MARKUP_VIEWER_EVENTS will pass an object formatted like a Redux action to the provided callback. The type will be the specific event, and the payload will be the same payload that would be received for the individual event.
Subscriptions/listeners need to be set up before an event is triggered. When using Redux, it is typically easier to set up a single listener to EVENT_CONSTANTS.MARKUP_VIEWER_EVENT right when an app starts.
The following is an example of two different options for listening to events:
// Subscribe just to individual event
markupViewer.on(EVENT_CONSTANTS.SELECT_TOOL, (payload) => console.log(payload));
// When triggered, will log: { toolKey: 'rect }
// Subscribe to all markupViewer events
markupViewer.on(EVENT_CONSTANTS.MARKUP_VIEWER_EVENT, ({ type, payload }) =>
console.log({ type, payload })
);
// When triggered, will log: { type: EVENT_CONSTANTS.SELECT_TOOL, payload: { toolKey: 'rect } }
// Triggers both of the above listeners.
markupViewer.trigger(TRIGGER_CONSTANTS.SELECT_TOOL, { toolKey: 'rect' });Tools
The following tools are included to be used out of the box:
- rect
- freehand
- selection
- stamp
You can also create your own tools, either by extending ClickDrag, or by using ClickDrag as a template for your own use case.
When activated, a new instance of a tool is constructed with the following arguments:
- viewer
- events
- options (user-defined)
Attributes
When activated, rect and freehand will respond to the TRIGGER_CONSTANTS.UPDATE_ATTRIBUTES event:
markupViewer.trigger(TRIGGER_CONSTANTS.UPDATE_ATTRIBUTES, {
fill: '#00FF00',
stroke: '#00FF00',
'fill-opacity': 0.5,
'stroke-width': 4,
});Example: setting color of shape
import MarkupViewer, { tools, EVENT_CONSTANTS, TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const options = {
tools: {
rect: tools.rect,
},
};
const markupViewer = new MarkupViewer(options);
// Properties can be passed in when the tool is activated
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, {
toolKey: 'rect',
options: {
fill: '#00FF00',
stroke: '#00FF00',
'fill-opacity': 0.5,
'stroke-width': 4,
}
);
// --------
// Alternatively, properties can be set after a tool is activated
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, { toolKey: 'rect' });
markupViewer.trigger(TRIGGER_CONSTANTS.UPDATE_ATTRIBUTES, {
fill: '#FF0000',
stroke: '#FF0000',
});Constants for events
TRIGGER_CONSTANTS
SET_PAGE
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const options = { htmlText: '<div></div>' };
markupViewer.trigger(TRIGGER_CONSTANTS.SET_PAGE, options);ZOOM_IN
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const zoomAmount = 0.05;
markupViewer.trigger(TRIGGER_CONSTANTS.ZOOM_IN, zoomAmount);ZOOM_OUT
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const zoomAmount = 0.05;
markupViewer.trigger(TRIGGER_CONSTANTS.ZOOM_OUT, zoomAmount);RESET_ZOOM
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
markupViewer.trigger(TRIGGER_CONSTANTS.RESET_ZOOM);SET_ACTIVE_TOOL
Rect
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const toolKey = 'rect';
const options = {
fill: '#ff0000',
'fill-opacity': 0.5,
stroke: '#0000ff',
'stroke-opacity': 1,
'stroke-width': 4,
};
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, { toolKey, options });Freehand
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const toolKey = 'freehand';
const options = {
stroke: '#0000ff',
'stroke-opacity': 1,
'stroke-width': 4,
};
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, { toolKey, options });Selection
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const toolKey = 'selection';
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, { toolKey });Stamp
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const stamp = {
url: 'someImage.svg',
width: 100,
height: 100,
};
const options = {
stamp,
};
const toolKey = 'stamp';
markupViewer.trigger(TRIGGER_CONSTANTS.SET_ACTIVE_TOOL, { toolKey, options });CANCEL_ACTIVE_TOOL
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
markupViewer.trigger(TRIGGER_CONSTANTS.CANCEL_ACTIVE_TOOL);UPDATE_ATTRIBUTES
Will only trigger successfully if there is an active tool that supports updating attributes (rect/freehand)
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const options = {
fill: '#ff0000',
'fill-opacity': 0.5,
stroke: '#0000ff',
'stroke-opacity': 1,
'stroke-width': 4,
};
markupViewer.trigger(TRIGGER_CONSTANTS.UPDATE_ATTRIBUTES, options);CREATE_MARKUP_ELEMENTS
Typically used for rendering a markupElement from a server-event
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const markupElements = [
{
id: 123,
type: 'rect',
svg: '<rect width="10" height="10" x="0" y="0"></rect>',
},
];
markupViewer.trigger(TRIGGER_CONSTANTS.CREATE_MARKUP_ELEMENTS, markupElement);REMOVE_MARKUP_ELEMENTS
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const markupElements = ['abc-123'];
markupViewer.trigger(TRIGGER_CONSTANTS.REMOVE_MARKUP_ELEMENTS, markupElements);UPDATE_MARKUP_ELEMENTS
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const uuid = 'abc-123';
const svg = '<rect></rect>';
const id = 321;
markupViewer.trigger(TRIGGER_CONSTANTS.UPDATE_MARKUP_ELEMENT, [
{
uuid,
svg,
id,
},
]);UPDATE_SHAPE_ATTRIBUTES
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const markupElements = ['abc-123', 'def-456', 'ghi-789'];
const attributes = {
fill: '#ff0000',
'fill-opacity': 0.5,
stroke: '#0000ff',
'stroke-opacity': 1,
'stroke-width': 4,
};
markupViewer.trigger(TRIGGER_CONSTANTS.UPDATE_SHAPE_ATTRIBUTES, {
markupElements,
attributes,
});UPDATE_MARKUP_ELEMENT_SELECTION
import { TRIGGER_CONSTANTS } from '@procore/markup-viewer';
const markupElements = ['abc-123', 'def-456', 'ghi-789'];
markupViewer.trigger(TRIGGER_CONSTANTS, markupElements);EVENT_CONSTANTS
SET_PAGE
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.SET_PAGE, callback);payload:
- none
ZOOM_IN
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.ZOOM_IN, callback);payload:
{
zoomLevel: 1.05
}ZOOM_OUT
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.ZOOM_OUT, callback);payload:
{
zoomLevel: 0.95
}RESET_ZOOM
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.RESET_ZOOM, callback);payload:
{
zoomLevel: 0.95
}SET_ACTIVE_TOOL
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.SET_ACTIVE_TOOL, callback);payload:
{
toolKey: 'rect',
options
}CANCEL_ACTIVE_TOOL
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.CANCEL_ACTIVE_TOOL, callback);payload:
undefined
UPDATE_ATTRIBUTES
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.UPDATE_ATTRIBUTES, callback);payload:
{
fill: '#ff0000',
'fill-opacity': 0.5,
stroke: '#0000ff',
'stroke-opacity': 1,
'stroke-width': 4,
}CREATE_MARKUP_ELEMENTS
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.CREATE_MARKUP_ELEMENTS, callback);payload:
[
{
uuid: 'abc-123',
id: 123,
svg: '<rect></rect>',
type: 'rect',
attributes: {}
}
]REMOVE_MARKUP_ELEMENTS
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.REMOVE_MARKUP_ELEMENTS, callback);payload:
[
'abc-123'
]UPDATE_MARKUP_ELEMENTS
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.UPDATE_MARKUP_ELEMENTS, callback);payload:
[
{
uuid: 'abc-123',
id: 123,
svg: '<rect></rect>',
type: 'rect',
attributes: {}
}
]UPDATE_SHAPE_ATTRIBUTES
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.UPDATE_SHAPE_ATTRIBUTES, callback);payload:
[
{
uuid: 'abc-123',
id: 123,
svg: '<rect></rect>',
type: 'rect',
attributes: {}
}
]UPDATE_MARKUP_ELEMENT_SELECTION
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.UPDATE_MARKUP_ELEMENT_SELECTION, callback);payload:
[
'abc-123',
'def-456',
'ghi-789'
]DRAW_COMPLETE
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.DRAW_COMPLETE, callback);payload:
{
uuid: 'abc-123',
svg: '<rect></rect>',
type: 'rect',
attributes: {}
}MARKUP_VIEWER_EVENT
This event is a 'super event'. This event is fired for every event in EVENT_CONSTANTS. Its payload is an object formatted for easy use in Redux-like environments, with type and payload keys. type will be a constant from EVENT_CONSTANTS; payload will be the associated payload listed above.
import { EVENT_CONSTANTS } from '@procore/markup-viewer';
const callback = (payload) => console.log(payload);
markupViewer.on(EVENT_CONSTANTS.MARKUP_VIEWER_EVENT, callback);payload:
{
type: EVENT_CONSTANTS.*,
payload
}2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago