bigbluebutton-Github/bigbluebutton-html5/imports/ui/components/whiteboard/annotations/pencil/component.jsx
James Jung 204921e043 Make code more readable, and make clicking the mouse right button not to draw annotation
Seperate the function 'contextMenuHandler' of drawing listeners into the service for reusability

Call the 'UndoAnnotation' method from Whiteboard-toolbar's service to use inside Whiteboard-overlay's draw listeners,
rather than initializing the same method inside Whiteboard-overlay's service to use

Make drawing annotations using the mouse right button inactive
2018-07-23 17:25:06 -04:00

169 lines
5.6 KiB
JavaScript
Executable File

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import AnnotationHelpers from '../helpers';
export default class PencilDrawComponent extends Component {
static getInitialCoordinates(annotation, slideWidth, slideHeight) {
const { points } = annotation;
let i = 2;
let path = '';
if (points && points.length >= 2) {
path = `M${(points[0] / 100) * slideWidth
}, ${(points[1] / 100) * slideHeight}`;
while (i < points.length) {
path = `${path} L${(points[i] / 100) * slideWidth
}, ${(points[i + 1] / 100) * slideHeight}`;
i += 2;
}
}
return { path, points };
}
static getFinalCoordinates(annotation, slideWidth, slideHeight) {
const { points, commands } = annotation;
let path = '';
let i;
let j;
for (i = 0, j = 0; i < commands.length; i += 1) {
switch (commands[i]) {
// MOVE_TO - consumes 1 pair of values
case 1:
path = `${path} M${(points[j] / 100) * slideWidth} ${(points[j + 1] / 100) * slideHeight}`;
j += 2;
break;
// LINE_TO - consumes 1 pair of values
case 2:
path = `${path} L${(points[j] / 100) * slideWidth} ${(points[j + 1] / 100) * slideHeight}`;
j += 2;
break;
// QUADRATIC_CURVE_TO - consumes 2 pairs of values
// 1st pair is a control point, second is a coordinate
case 3:
path = `${path} Q${(points[j] / 100) * slideWidth}, ${
(points[j + 1] / 100) * slideHeight}, ${(points[j + 2] / 100) * slideWidth}, ${
(points[j + 3] / 100) * slideHeight}`;
j += 4;
break;
// CUBIC_CURVE_TO - consumes 3 pairs of values
// 1st and 2nd are control points, 3rd is an end coordinate
case 4:
path = `${path} C${(points[j] / 100) * slideWidth}, ${
(points[j + 1] / 100) * slideHeight}, ${(points[j + 2] / 100) * slideWidth}, ${
(points[j + 3] / 100) * slideHeight}, ${(points[j + 4] / 100) * slideWidth}, ${
(points[j + 5] / 100) * slideHeight}`;
j += 6;
break;
default:
break;
}
}
// If that's just one coordinate at the end (dot) - we want to display it.
// So adding L with the same X and Y values to the path
if (path && points.length === 2) {
path = `${path} L${(points[0] / 100) * slideWidth} ${(points[1] / 100) * slideHeight}`;
}
return { path, points };
}
constructor(props) {
super(props);
const { annotation, slideWidth, slideHeight } = this.props;
this.path = this.getCoordinates(annotation, slideWidth, slideHeight);
this.getCurrentPath = this.getCurrentPath.bind(this);
this.getCoordinates = this.getCoordinates.bind(this);
}
shouldComponentUpdate(nextProps) {
return this.props.version !== nextProps.version;
}
componentWillUpdate(nextProps) {
const { annotation, slideWidth, slideHeight } = nextProps;
if (annotation.points.length !== this.props.annotation.points.length) {
this.path = this.getCoordinates(annotation, slideWidth, slideHeight);
}
}
getCoordinates(annotation, slideWidth, slideHeight) {
if ((!annotation || annotation.points.length === 0)
|| (annotation.status === 'DRAW_END' && !annotation.commands)) {
return undefined;
}
let data;
// Final message, display smoothes coordinates
if (annotation.status === 'DRAW_END') {
data = PencilDrawComponent.getFinalCoordinates(annotation, slideWidth, slideHeight);
// Not a final message, but rendering it for the first time, creating a new path
} else if (!this.path) {
data = PencilDrawComponent.getInitialCoordinates(annotation, slideWidth, slideHeight);
// If it's not the first 2 cases - means we just got an update, updating the coordinates
} else {
data = this.updateCoordinates(annotation, slideWidth, slideHeight);
}
this.points = data.points;
return data.path;
}
getCurrentPath() {
return this.path ? this.path : 'M -1 -1';
}
updateCoordinates(annotation, slideWidth, slideHeight) {
const { points } = annotation;
let i = this.points.length;
let path = '';
while (i < points.length) {
path = `${path} L${(points[i] / 100) * slideWidth
}, ${(points[i + 1] / 100) * slideHeight}`;
i += 2;
}
path = this.path + path;
return { path, points };
}
render() {
const { annotation, slideWidth } = this.props;
return (
<path
fill="none"
stroke={AnnotationHelpers.getFormattedColor(annotation.color)}
d={this.getCurrentPath()}
strokeWidth={AnnotationHelpers.getStrokeWidth(annotation.thickness, slideWidth)}
strokeLinejoin="round"
strokeLinecap="round"
style={{ WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)' }}
/>
);
}
}
PencilDrawComponent.propTypes = {
// Defines a version of the shape, so that we know if we need to update the component or not
version: PropTypes.number.isRequired,
// Defines an annotation object, which contains all the basic info we need to draw with a pencil
annotation: PropTypes.shape({
points: PropTypes.arrayOf(PropTypes.number).isRequired,
color: PropTypes.number.isRequired,
thickness: PropTypes.number.isRequired,
}).isRequired,
// Defines the width of the slide (svg coordinate system), which needed in calculations
slideWidth: PropTypes.number.isRequired,
// Defines the height of the slide (svg coordinate system), which needed in calculations
slideHeight: PropTypes.number.isRequired,
};