marker.js Live Documentation: Using marker.js Live with React

Using marker.js Live with React

In this walkthrough we will create a simple React app (using Create React App), add an image to it, and then add marker.js Live to display annotations made with marker.js 2 on top of that image.

Follow along or just lookup the sections you are interested in below.

Create React App

Let’s create a simple React app as the basis for our project. We will use Create React App for this.

npx create-react-app my-react-mjslive-app --template typescript cd my-react-mjslive-app

NOTE:

We are using TypeScript in this walkthrough but feel free to remove the --template typescript part from the command above and just omit type declarations in the code examples below.

We will use class components in this walkthrough. So, we will start with this barebone App.tsx (App.js, if you aren’t using TypeScript).:

import React, { Component } from 'react'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <h1>marker.js Live Demo.</h1> </div> ); } } export default App;

Add an image

Now, let's add an image to our app. Grab the image below and save it to the public folder of the project. Let's call it desk.jpg.

Next we will add the image to our App component and create a ref for it, so that we can pass it to marker.js Live.

At this stage, our App file looks like this:

import React, { Component } from 'react'; import './App.css'; class App extends Component { imgRef = React.createRef<HTMLImageElement>(); render() { return ( <div className="App"> <h1>marker.js Live Demo.</h1> <img ref={this.imgRef} src="desk.jpg" alt="sample" style={{ maxWidth: '50%' }} /> </div> ); } } export default App;

Add marker.js Live

Now that we have our base project setup, it is time to add marker.js Live.

Run:

npm install markerjs-live

or

yarn add markerjs-live

After that we can import marker.js Live into our component and then wire it up.

import * as mjslive from 'markerjs-live';

Before we move on to adding marker.js Live code, we need an annotation data (config) for the annotations. You create it with marker.js 2 and here's the config we'll use in this walkthrough:

config: mjslive.MarkerAreaState = { width: 798, height: 775, markers: [ { fillColor: "transparent", strokeColor: "#FFFF00", strokeWidth: 3, strokeDasharray: "3", opacity: 1, left: 435, top: 738, width: 63, height: 34, rotationAngle: 0, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, typeName: "EllipseFrameMarker", notes: "https://en.wikipedia.org/wiki/Logo", state: "select" } as mjslive.MarkerBaseState, { bgColor: "#FFFF00", tipPosition: { x: -71.17532348632812, y: 66.67831420898438 }, color: "#7C3AED", fontFamily: 'Courier, "Courier New", monospace', padding: 5, text: "can't have logos", left: 567.4873962402344, top: 698.9164733886719, width: 151.55291748046875, height: 35.87835693359375, rotationAngle: 9.475395686551806, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 0.9863563850257626, b: 0.164624061785966, c: -0.164624061785966, d: 0.9863563850257626, e: 123.49474533415031, f: -93.85420974513181 }, typeName: "CalloutMarker", notes: "https://en.wikipedia.org/wiki/Logo", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 212, y1: 474, x2: 211, y2: 535, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 734, y1: 470, x2: 733, y2: 553, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { color: "#FFFFFF", fontFamily: "Helvetica, Arial, sans-serif", padding: 5, text: "these should be parallel", left: 382, top: 491, width: 208, height: 30, rotationAngle: 0, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, typeName: "TextMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { fillColor: "#2563EB", strokeColor: "transparent", strokeWidth: 0, strokeDasharray: "", opacity: 0.5, left: -38, top: 483, width: 195, height: 267, rotationAngle: 0, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, typeName: "HighlightMarker", notes: "https://en.wikipedia.org/wiki/Photograph_manipulation#%22Photoshop%22_as_a_verb", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 352, y1: 474, x2: 354, y2: 538, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 613, y1: 470, x2: 615, y2: 546, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState ] };

Now, let's create a showMarkers() method that we will then call to show the markers from the config:

showMarkers(target: HTMLImageElement) { const markerView = new mjslive.MarkerView(target); markerView.show(this.config); }

Now we just need to call this method when our image loads:

<img ref={this.imgRef} src="desk.jpg" alt="sample" style={{ maxWidth: '50%' }} onLoad={ ev => this.showMarkers(ev.target as HTMLImageElement)} />

And that's all it takes to integrate the basic marker.js Live functionality into a React app and dynamically display the annotations created with marker.js 2.

The complete code

Here's the complete final App.tsx for this walkthrough:

import React, { Component } from 'react'; import * as mjslive from 'markerjs-live'; import './App.css'; class App extends Component { imgRef = React.createRef<HTMLImageElement>(); config: mjslive.MarkerAreaState = { width: 798, height: 775, markers: [ { fillColor: "transparent", strokeColor: "#FFFF00", strokeWidth: 3, strokeDasharray: "3", opacity: 1, left: 435, top: 738, width: 63, height: 34, rotationAngle: 0, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, typeName: "EllipseFrameMarker", notes: "https://en.wikipedia.org/wiki/Logo", state: "select" } as mjslive.MarkerBaseState, { bgColor: "#FFFF00", tipPosition: { x: -71.17532348632812, y: 66.67831420898438 }, color: "#7C3AED", fontFamily: 'Courier, "Courier New", monospace', padding: 5, text: "can't have logos", left: 567.4873962402344, top: 698.9164733886719, width: 151.55291748046875, height: 35.87835693359375, rotationAngle: 9.475395686551806, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 0.9863563850257626, b: 0.164624061785966, c: -0.164624061785966, d: 0.9863563850257626, e: 123.49474533415031, f: -93.85420974513181 }, typeName: "CalloutMarker", notes: "https://en.wikipedia.org/wiki/Logo", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 212, y1: 474, x2: 211, y2: 535, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 734, y1: 470, x2: 733, y2: 553, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { color: "#FFFFFF", fontFamily: "Helvetica, Arial, sans-serif", padding: 5, text: "these should be parallel", left: 382, top: 491, width: 208, height: 30, rotationAngle: 0, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, typeName: "TextMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { fillColor: "#2563EB", strokeColor: "transparent", strokeWidth: 0, strokeDasharray: "", opacity: 0.5, left: -38, top: 483, width: 195, height: 267, rotationAngle: 0, visualTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, containerTransformMatrix: { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }, typeName: "HighlightMarker", notes: "https://en.wikipedia.org/wiki/Photograph_manipulation#%22Photoshop%22_as_a_verb", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 352, y1: 474, x2: 354, y2: 538, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState, { strokeColor: "#EF4444", strokeWidth: 3, strokeDasharray: "", x1: 613, y1: 470, x2: 615, y2: 546, typeName: "MeasurementMarker", notes: "https://en.wikipedia.org/wiki/Parallel_(geometry)", state: "select" } as mjslive.MarkerBaseState ] }; showMarkers(target: HTMLImageElement) { const markerView = new mjslive.MarkerView(target); markerView.show(this.config); } render() { return ( <div className="App"> <h1>marker.js Live Demo.</h1> <img ref={this.imgRef} src="desk.jpg" alt="sample" style={{ maxWidth: '50%' }} onLoad={ ev => this.showMarkers(ev.target as HTMLImageElement)} /> </div> ); } } export default App;

JavaScript version of this demo in CodeSandbox

Check out the JavaScript version of this demo embeded below, or click here to open it in CodeSandbox.

See also

Check out other documentation topics and demos for more advanced uses of marker.js Live that can be easily applied to your React apps.