Signature
- Responder
- View
- Signature
- View
Draw a series of continuous lines with the mouse or a finger. Press the Del key or click on the trash can to erase everything.
Move the pointer of the mouse outside the drawing area. Reload the page. The drawing was saved and restored.
In the console of the navigator, retrieve the image in PNG :
signature.widget.toDataURL()
"data:image/png;base64,iVBORw0KGgoAAAAN...="
- function Signature(options = false) {
- options = options || {};
- let lineColor = options.lineColor;
- let lineWidth = options.lineWidth;
- if (lineColor === undefined)
- lineColor = Signature.defaultLineColor;
- else if (!Validator.validateColor(lineColor))
- throw new TypeError();
- if (lineWidth === undefined)
- lineWidth = Signature.defaultLineWidth;
- else if (typeof lineWidth !== 'number')
- throw new TypeError();
- View.call(this);
- this._lineColor = lineColor;
- this._lineWidth = lineWidth;
- }
- Signature.prototype = Object.create(View.prototype);
- Object.defineProperty(Signature.prototype, 'constructor', { value: Signature, enumerable: false, writable: true });
- Signature.defaultLineColor = '#000000';
- Signature.defaultLineWidth = 5;
The Signature class inherits from the View class.
The constructor accepts two options : lineColor
, the color of the drawing line, and lineWidth
, its thickness. By default, the drawing line is black with a thickness of 5 pixels.
- Signature.prototype.erase = function() {
- if (this._widget) {
- this._widget.getContext('2d').clearRect(0, 0, this._widget.width, this._widget.height);
- }
- return this;
- };
erase
erases the widget of this
, a canvas, if defined.
- Signature.prototype.isBlank = function() {
- if (!this._widget)
- return true;
- const imgdata = this._widget.getContext('2d').getImageData(0, 0, this._widget.width, this._widget.height);
- return imgdata ? !new Uint32Array(imgdata.data.buffer).some(color => color != 0) : true;
- };
isBlank
returns true
if this
has no widget or if the widget, a canvas, has no content, false
otherwise.
- Signature.prototype.setWidget = function(w) {
- if (w.tagName != 'CANVAS')
- throw new TypeError();
- if (w.width == 0 || w.height == 0)
- throw new TypeError();
setWidget
redefines the method inherited from the View class.
w
, the widget of an instance of a Signature, must be a canvas with a width and a height.
- View.prototype.setWidget.call(this, w);
Calls the method setWidget
inherited from View with the canvas in argument.
- const ctx = w.getContext('2d');
- ctx.strokeStyle = this._lineColor;
- ctx.lineWidth = this._lineWidth;
- ctx.lineJoin = 'round';
- ctx.lineCap = 'round';
Initializes the properties of the drawing line in the 2D rendering context of the canvas.
- w.style.touchAction = 'none';
Blocks interactions by the user on the canvas on a touchscreen , I.e. moving or zooming the display.
- let x0 = 0;
- let y0 = 0;
x0
and y0
hold the last position of the drawing tool.
- function _stroke(e) {
- if (e.type === 'mousemove' || e.type === 'touchmove')
- return;
- let x = e.offsetX * (w.width / w.clientWidth);
- let y = e.offsetY * (w.height / w.clientHeight);
- if (x0 && y0) {
- ctx.beginPath();
- ctx.moveTo(x0, y0);
- ctx.lineTo(x, y);
- ctx.stroke();
- ctx.closePath();
- }
- x0 = x;
- y0 = y;
- }
The local function _stroke
is called every time the drawing tool is moved, i.e. every time a mousemove, a pointermove or a touchmove event is notified by the canvas.
If the event is of the type mousemove or touchmove, the function exits immediately.
Otherwise, i.e. the event is of the type pointermove, the function calculates the position of the pointer taking into account a possible resizing of the canvas, draws a line between the last position and the new position of the pointer, and memorizes the new position of the pointer.
- w.addEventListener('pointerdown', () => {
- w.addEventListener('pointermove', _stroke, false);
- }, false);
- w.addEventListener('pointerup', () => {
- w.removeEventListener('pointermove', _stroke, false), x0 = y0 = 0;
- }, false);
- return this;
- };
Adds the function _stroke
as a listener to the event pointermove when the user presses on the first button of the mouse or presses a pointer in the canvas or touches the canvas with one finger.
Removes the function _stroke
as a listener to the event pointermove and sets the last position of the drawing tool to 0 when the user stops pressing the first button of the mouse or with a pointer in the canvas or touching the canvas.
Test
- <?php $bg='#ffc'; ?>
- <?php $width=600; ?>
- <?php $height=400; ?>
- <?php $linewidth=5; ?>
- <?php $linecolor='#00f'; ?>
- <?php $trashcolor='#e02'; ?>
Defines the background color, the width and the height of the drawing area, the width and the color of the line, the color of the trash can.
- <?php $id=uniqid('id'); ?>
Defines the identifier of the <div>
which surrounds the test display.
- .test_display {
- display: inline-block;
- position: relative;
- margin: 1em 0 0;
- }
- .test_display canvas {
- background-color: <?php echo $bg; ?>;
- }
- .test_display i.fa-trash {
- position: absolute; bottom: 10px; right: 5px;
- padding: 10px; border-radius: 50%; background-color: #fff;
- color: <?php echo $trashcolor; ?>;
- cursor: pointer;
- }
Configures the look of the drawing area. Puts the trash can at the bottom right.
- <div id="<?php echo $id; ?>" class="noprint">
- <div class="test_display">
- <canvas width="<?php echo $width; ?>" height="<?php echo $height; ?>"></canvas>
- <i class="fas fa-trash"></i>
- </div>
- </div>
Creates the <div>
of the test display with a canvas and the image of a button.
- <?php head('javascript', '/objectivejs/Objective.js'); ?>
- <?php head('javascript', '/objectivejs/Responder.js'); ?>
- <?php head('javascript', '/objectivejs/View.js'); ?>
- <?php head('javascript', '/objectivejs/Validator.js'); ?>
- <?php head('javascript', '/objectivejs/Signature.js'); ?>
Includes the code of all the necessary classes.
REMINDER: The function head
of the iZend library adds a tag such as <script src="/objectivejs/Objective.js"></script>
to the <head>
section of the document in HTML. Adapt the code to your development environment.
- const signature = new Signature({lineColor: '<?php echo $linecolor; ?>', lineWidth: <?php echo $linewidth; ?>});
- const container = document.querySelector('#<?php echo $id; ?>');
- signature.setManagedWidget(container.querySelector('canvas'));
Creates an instance of Signature and configures its widget, the canvas.
- const trash = container.querySelector('i.fa-trash');
- trash.onclick = () => signature.erase();
Erases the signature if the trash can is clicked.
- signature.setAttribute('tabindex', 0);
- signature.addEventListener('keydown', (e) => {
- if (e.key === 'Delete')
- signature.erase();
- });
Erases the signature if the Del key is pressed in the canvas.
- const storage = sessionStorage;
Accesses the storage space of the page.
- const url = storage.getItem('signature');
- if (url !== null) {
- const img = new Image();
- img.onload = () => signature.widget.getContext('2d').drawImage(img, 0, 0);
- img.src = url;
- }
If a data URL is saved in the storage space, displays the image it contains in the canvas.
- signature.addEventListener('mouseout', () => storage.setItem('signature', signature.widget.toDataURL()));
Saves the image drawn in the canvas in the storage space as a data URL when the pointer leaves the drawing area.
Comments