1Webviewer(...).then((instance) => {
2 const { Core, UI } = instance;
3 const { Annotations, annotationManager, Tools, documentViewer } = Core;
4
5 // Beginning Custom Annotation Class
6 class RotatablePath extends Annotations.CustomAnnotation {
7 constructor() {
8 super('rotatable-path');
9 this.Subject = 'RotatablePath';
10 this.path = [
11 new Annotations.Point(this.X, this.Y),
12 new Annotations.Point(this.X + this.Width, this.Y),
13 new Annotations.Point(this.X + this.Width, this.Y + this.Height),
14 new Annotations.Point(this.X, this.Y + this.Height),
15 ];
16 this.selectionModel = RotatableSelectionModel;
17 }
18
19 getPath() {
20 return this.path;
21 }
22
23 setPath(newPath) {
24 this.path = newPath;
25 }
26
27 draw(ctx, pageMatrix) {
28 this.setStyles(ctx, pageMatrix);
29
30 ctx.beginPath();
31 ctx.moveTo(this.path[0].x, this.path[0].y);
32 ctx.lineTo(this.path[1].x, this.path[1].y);
33 ctx.lineTo(this.path[2].x, this.path[2].y);
34 ctx.lineTo(this.path[3].x, this.path[3].y);
35 ctx.lineTo(this.path[0].x, this.path[0].y);
36 ctx.lineTo(this.path[2].x, this.path[2].y);
37 ctx.moveTo(this.path[1].x, this.path[1].y);
38 ctx.lineTo(this.path[3].x, this.path[3].y);
39 ctx.stroke();
40 }
41
42 resize(rect) {
43 const { x1, y1 } = rect;
44 const deltaX = x1 - this['X'];
45 const deltaY = y1 - this['Y'];
46 if (deltaX === 0 && deltaY === 0) {
47 return;
48 }
49 for (let i = 0; i < this.path.length; i++) {
50 this.path[i].translate(deltaX, deltaY);
51 }
52
53 this.adjustRect();
54 }
55
56 adjustRect() {
57 let minX = this.path[0]['x'];
58 let minY = this.path[0]['y'];
59 let maxX = this.path[0]['x'];
60 let maxY = this.path[0]['y'];
61
62 this.path.forEach((point) => {
63 if (point.x < minX) {
64 minX = point.x;
65 }
66 if (point.x > maxX) {
67 maxX = point.x;
68 }
69 if (point.y < minY) {
70 minY = point.y;
71 }
72 if (point.y > maxY) {
73 maxY = point.y;
74 }
75 });
76
77 this['X'] = minX;
78 this['Y'] = minY;
79 this['Width'] = maxX - minX;
80 this['Height'] = maxY - minY;
81 }
82
83 serialize(element, pageMatrix) {
84 this.setCustomData('trn-path', JSON.stringify(this.path));
85
86 return Annotations.CustomAnnotation.prototype.serialize.apply(this, arguments);
87 }
88
89 deserialize(element) {
90 Annotations.CustomAnnotation.prototype.deserialize.apply(this, arguments);
91
92 this.path = JSON.parse(this.getCustomData('trn-path'));
93 }
94 }
95
96 RotatablePath.prototype.elementName = 'rotatable-path';
97
98 annotationManager.registerAnnotationType(RotatablePath.prototype.elementName, RotatablePath);
99 // End Custom Annotation Class
100
101 // Beginning Control Handle
102 class RotatablePathControlHandle extends Annotations.PathControlHandle {
103 constructor(x, y, width, height, pathIndex) {
104 super(x, y, width, height, pathIndex);
105
106 this.pathIndex = pathIndex;
107 }
108
109 move(annotation, deltaX, deltaY) {
110 annotation.path[this.pathIndex] = new Annotations.Point(annotation.path[this.pathIndex].x + deltaX, annotation.path[this.pathIndex].y + deltaY);
111
112 annotation.adjustRect();
113
114 return true;
115 }
116 }
117 // End Control Handle
118
119 // Beginning Selection Model
120 class RotatableSelectionModel extends Annotations.SelectionModel {
121 constructor(annotation, canModify, isSelected, documentViewer) {
122 super(annotation, canModify, isSelected, documentViewer);
123
124 const controlHandles = this.getControlHandles();
125
126 if (canModify) {
127 for (let i = 0; i < annotation.path.length; i++) {
128 controlHandles.push(new RotatablePathControlHandle(annotation.path[i].x, annotation.path[i].y, Annotations.ControlHandle['handleWidth'], Annotations.ControlHandle['handleWidth'], i));
129 }
130 }
131 }
132 }
133 // End Selection Model
134
135 // Beginning Tool
136 class RotatableCreateTool extends Tools.GenericAnnotationCreateTool {
137 constructor(documentViewer) {
138 super(documentViewer, RotatablePath);
139 }
140
141 mouseMove(e) {
142 super.mouseMove(e);
143
144 if (this.annotation) {
145 this.annotation.path[0].x = this.annotation.X;
146 this.annotation.path[0].y = this.annotation.Y;
147 this.annotation.path[1].x = this.annotation.X + this.annotation.Width;
148 this.annotation.path[1].y = this.annotation.Y;
149 this.annotation.path[2].x = this.annotation.X + this.annotation.Width;
150 this.annotation.path[2].y = this.annotation.Y + this.annotation.Height;
151 this.annotation.path[3].x = this.annotation.X;
152 this.annotation.path[3].y = this.annotation.Y + this.annotation.Height;
153
154 annotationManager.redrawAnnotation(this.annotation);
155 }
156 }
157 }
158
159 const rotatableToolName = 'AnnotationCreateRotatable';
160
161 const rotatableTool = new RotatableCreateTool(documentViewer);
162 UI.registerTool({
163 toolName: rotatableToolName,
164 toolObject: rotatableTool,
165 buttonImage: '<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" viewBox="0 0 64 64">' +
166 '<line x1="9.37" x2="54.63" y1="9.37" y2="9.37" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/>' +
167 '<line x1="9.37" x2="9.37" y1="54.63" y2="9.37" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/>' +
168 '<line x1="54.63" x2="54.63" y1="9.37" y2="54.63" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/>' +
169 '<line x1="9.37" x2="54.63" y1="54.63" y2="54.63" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/>' +
170 '<line x1="9.37" x2="54.63" y1="9.37" y2="54.63" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/>' +
171 '<line x1="9.37" x2="54.63" y1="54.63" y2="9.37" fill="none" stroke="#010101" stroke-miterlimit="10" stroke-width="4"/>' +
172 '</svg>',
173 buttonName: 'rotatableToolButton',
174 tooltip: 'Rotatable'
175 }, RotatablePath);
176
177 UI.setHeaderItems((header) => {
178 header.getHeader('toolbarGroup-Shapes').get('freeHandToolGroupButton').insertBefore({
179 type: 'toolButton',
180 toolName: rotatableToolName
181 });
182 });
183 // End Tool
184});