UNPKG

recordrtc

Version:

RecordRTC is a server-less (entire client-side) JavaScript library can be used to record WebRTC audio/video media streams. It supports cross-browser audio/video recording.

1,372 lines (1,001 loc) 98.5 kB
// Last time updated at Monday, January 11th, 2016, 1:38:19 PM // _______________ // Canvas-Designer // https://github.com/muaz-khan/Canvas-Designer 'use strict'; (function() { // ------------------------------------------------------------- var is = { isLine: false, isArc: false, isDragLastPath: false, isDragAllPaths: false, isRectangle: false, isQuadraticCurve: false, isBezierCurve: false, isPencil: false, isEraser: false, isText: false, isImage: false, set: function(shape) { var cache = this; cache.isLine = cache.isArc = cache.isDragLastPath = cache.isDragAllPaths = cache.isRectangle = cache.isQuadraticCurve = cache.isBezierCurve = cache.isPencil = cache.isEraser = cache.isText = cache.isImage = false; cache['is' + shape] = true; } }; // ------------------------------------------------------------- function addEvent(element, eventType, callback) { if (element.addEventListener) { element.addEventListener(eventType, callback, !1); return true; } else if (element.attachEvent) return element.attachEvent('on' + eventType, callback); else element['on' + eventType] = callback; return this; } // ------------------------------------------------------------- function find(selector) { return document.getElementById(selector); } // ------------------------------------------------------------- var points = [], textarea = find('code-text'), lineWidth = 5, strokeStyle = 'red', fillStyle = 'white', globalAlpha = 1, globalCompositeOperation = 'source-over', lineCap = 'round', font = '35px Verdana', lineJoin = 'round'; // ------------------------------------------------------------- function getContext(id) { var canv = find(id), ctx = canv.getContext('2d'); canv.setAttribute('width', innerWidth); canv.setAttribute('height', innerHeight); ctx.lineWidth = lineWidth; ctx.strokeStyle = strokeStyle; ctx.fillStyle = fillStyle; ctx.font = font; return ctx; } // ------------------------------------------------------------- var context = getContext('main-canvas'), tempContext = getContext('temp-canvas'); window.canvasElementToBeRecorded = tempContext.canvas; tempContext.clearRect = function() {}; // ------------------------------------------------------------- var common = { // ------------------------------------------------------------- updateTextArea: function() { var c = common, toFixed = c.toFixed, getPoint = c.getPoint, isAbsolutePoints = find('is-absolute-points').checked, isShortenCode = find('is-shorten-code').checked; if (isAbsolutePoints && isShortenCode) c.absoluteShortened(); if (isAbsolutePoints && !isShortenCode) c.absoluteNOTShortened(toFixed); if (!isAbsolutePoints && isShortenCode) c.relativeShortened(toFixed, getPoint); if (!isAbsolutePoints && !isShortenCode) c.relativeNOTShortened(toFixed, getPoint); }, // ------------------------------------------------------------- toFixed: function(input) { return Number(input).toFixed(1); }, // ------------------------------------------------------------- getPoint: function(pointToCompare, compareWith, prefix) { if (pointToCompare > compareWith) pointToCompare = prefix + ' + ' + (pointToCompare - compareWith); else if (pointToCompare < compareWith) pointToCompare = prefix + ' - ' + (compareWith - pointToCompare); else pointToCompare = prefix; return pointToCompare; }, // ------------------------------------------------------------- absoluteShortened: function() { var output = '', length = points.length, i = 0, point; for (i; i < length; i++) { point = points[i]; output += this.shortenHelper(point[0], point[1], point[2]); } output = output.substr(0, output.length - 2); textarea.value = 'var points = [' + output + '], length = points.length, point, p, i = 0;\n\n' + this.forLoop; this.prevProps = null; }, // ------------------------------------------------------------- absoluteNOTShortened: function(toFixed) { var tempArray = [], i, point, p; for (i = 0; i < points.length; i++) { p = points[i]; point = p[1]; if (p[0] === 'pencil') { tempArray[i] = ['context.beginPath();\n' + 'context.moveTo(' + point[0] + ', ' + point[1] + ');\n' + 'context.lineTo(' + point[2] + ', ' + point[3] + ');\n' + this.strokeOrFill(p[2])]; } if (p[0] === 'eraser') { tempArray[i] = ['context.beginPath();\n' + 'context.moveTo(' + point[0] + ', ' + point[1] + ');\n' + 'context.lineTo(' + point[2] + ', ' + point[3] + ');\n' + this.strokeOrFill(p[2])]; } if (p[0] === 'line') { tempArray[i] = ['context.beginPath();\n' + 'context.moveTo(' + point[0] + ', ' + point[1] + ');\n' + 'context.lineTo(' + point[2] + ', ' + point[3] + ');\n' + this.strokeOrFill(p[2])]; } if (p[0] === 'text') { tempArray[i] = ['context.fillText(' + point[0] + ', ' + point[1] + ', ' + point[2] + ');\n' + this.strokeOrFill(p[2])]; } if (p[0] === 'arc') { tempArray[i] = ['context.beginPath(); \n' + 'context.arc(' + toFixed(point[0]) + ',' + toFixed(point[1]) + ',' + toFixed(point[2]) + ',' + toFixed(point[3]) + ', 0,' + point[4] + '); \n' + this.strokeOrFill(p[2])]; } if (p[0] === 'rect') { tempArray[i] = [this.strokeOrFill(p[2]) + '\n' + 'context.strokeRect(' + point[0] + ', ' + point[1] + ',' + point[2] + ',' + point[3] + ');\n' + 'context.fillRect(' + point[0] + ', ' + point[1] + ',' + point[2] + ',' + point[3] + ');']; } if (p[0] === 'quadratic') { tempArray[i] = ['context.beginPath();\n' + 'context.moveTo(' + point[0] + ', ' + point[1] + ');\n' + 'context.quadraticCurveTo(' + point[2] + ', ' + point[3] + ', ' + point[4] + ', ' + point[5] + ');\n' + this.strokeOrFill(p[2])]; } if (p[0] === 'bezier') { tempArray[i] = ['context.beginPath();\n' + 'context.moveTo(' + point[0] + ', ' + point[1] + ');\n' + 'context.bezierCurveTo(' + point[2] + ', ' + point[3] + ', ' + point[4] + ', ' + point[5] + ', ' + point[6] + ', ' + point[7] + ');\n' + this.strokeOrFill(p[2])]; } } textarea.value = tempArray.join('\n\n') + this.strokeFillText; this.prevProps = null; }, // ------------------------------------------------------------- relativeShortened: function(toFixed, getPoint) { var i = 0, point, p, length = points.length, output = '', x = 0, y = 0; for (i; i < length; i++) { p = points[i]; point = p[1]; if (i === 0) { x = point[0]; y = point[1]; } if (p[0] === 'text') { x = point[1]; y = point[2]; } if (p[0] === 'pencil') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), getPoint(point[2], x, 'x'), getPoint(point[3], y, 'y') ], p[2]); } if (p[0] === 'eraser') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), getPoint(point[2], x, 'x'), getPoint(point[3], y, 'y') ], p[2]); } if (p[0] === 'line') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), getPoint(point[2], x, 'x'), getPoint(point[3], y, 'y') ], p[2]); } if (p[0] === 'text') { output += this.shortenHelper(p[0], [ point[0], getPoint(point[1], x, 'x'), getPoint(point[2], y, 'y') ], p[2]); } if (p[0] === 'arc') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), point[2], point[3], point[4] ], p[2]); } if (p[0] === 'rect') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), getPoint(point[2], x, 'x'), getPoint(point[3], y, 'y') ], p[2]); } if (p[0] === 'quadratic') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), getPoint(point[2], x, 'x'), getPoint(point[3], y, 'y'), getPoint(point[4], x, 'x'), getPoint(point[5], y, 'y') ], p[2]); } if (p[0] === 'bezier') { output += this.shortenHelper(p[0], [ getPoint(point[0], x, 'x'), getPoint(point[1], y, 'y'), getPoint(point[2], x, 'x'), getPoint(point[3], y, 'y'), getPoint(point[4], x, 'x'), getPoint(point[5], y, 'y'), getPoint(point[6], x, 'x'), getPoint(point[7], y, 'y') ], p[2]); } } output = output.substr(0, output.length - 2); textarea.value = 'var x = ' + x + ', y = ' + y + ', points = [' + output + '], length = points.length, point, p, i = 0;\n\n' + this.forLoop; this.prevProps = null; }, // ------------------------------------------------------------- relativeNOTShortened: function(toFixed, getPoint) { var i, point, p, length = points.length, output = '', x = 0, y = 0; for (i = 0; i < length; i++) { p = points[i]; point = p[1]; if (i === 0) { x = point[0]; y = point[1]; if (p[0] === 'text') { x = point[1]; y = point[2]; } output = 'var x = ' + x + ', y = ' + y + ';\n\n'; } if (p[0] === 'arc') { output += 'context.beginPath();\n' + 'context.arc(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ', ' + point[2] + ', ' + point[3] + ', 0, ' + point[4] + ');\n' + this.strokeOrFill(p[2]); } if (p[0] === 'pencil') { output += 'context.beginPath();\n' + 'context.moveTo(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ');\n' + 'context.lineTo(' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ');\n' + this.strokeOrFill(p[2]); } if (p[0] === 'eraser') { output += 'context.beginPath();\n' + 'context.moveTo(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ');\n' + 'context.lineTo(' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ');\n' + this.strokeOrFill(p[2]); } if (p[0] === 'line') { output += 'context.beginPath();\n' + 'context.moveTo(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ');\n' + 'context.lineTo(' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ');\n' + this.strokeOrFill(p[2]); } if (p[0] === 'text') { output += 'context.fillText(' + point[0] + ', ' + getPoint(point[1], x, 'x') + ', ' + getPoint(point[2], y, 'y') + ');\n' + this.strokeOrFill(p[2]); } if (p[0] === 'rect') { output += this.strokeOrFill(p[2]) + '\n' + 'context.strokeRect(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ', ' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ');\n' + 'context.fillRect(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ', ' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ');'; } if (p[0] === 'quadratic') { output += 'context.beginPath();\n' + 'context.moveTo(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ');\n' + 'context.quadraticCurveTo(' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ', ' + getPoint(point[4], x, 'x') + ', ' + getPoint(point[5], y, 'y') + ');\n' + this.strokeOrFill(p[2]); } if (p[0] === 'bezier') { output += 'context.beginPath();\n' + 'context.moveTo(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ');\n' + 'context.bezierCurveTo(' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ', ' + getPoint(point[4], x, 'x') + ', ' + getPoint(point[5], y, 'y') + ', ' + getPoint(point[6], x, 'x') + ', ' + getPoint(point[7], y, 'y') + ');\n' + this.strokeOrFill(p[2]); } if (i !== length - 1) output += '\n\n'; } textarea.value = output + this.strokeFillText; this.prevProps = null; }, // ------------------------------------------------------------- forLoop: 'for(i; i < length; i++) {\n' + '\t p = points[i];\n' + '\t point = p[1];\n' + '\t context.beginPath();\n\n' // ------------------------------------------------------------- + '\t if(p[2]) { \n' + '\t\t context.lineWidth = p[2][0];\n' + '\t\t context.strokeStyle = p[2][1];\n' + '\t\t context.fillStyle = p[2][2];\n' + '\t\t context.globalAlpha = p[2][3];\n' + '\t\t context.globalCompositeOperation = p[2][4];\n' + '\t\t context.lineCap = p[2][5];\n' + '\t\t context.lineJoin = p[2][6];\n' + '\t\t context.font = p[2][7];\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "line") { \n' + '\t\t context.moveTo(point[0], point[1]);\n' + '\t\t context.lineTo(point[2], point[3]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "pencil") { \n' + '\t\t context.moveTo(point[0], point[1]);\n' + '\t\t context.lineTo(point[2], point[3]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "text") { \n' + '\t\t context.fillText(point[0], point[1], point[2]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "eraser") { \n' + '\t\t context.moveTo(point[0], point[1]);\n' + '\t\t context.lineTo(point[2], point[3]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "arc") context.arc(point[0], point[1], point[2], point[3], 0, point[4]); \n\n' // ------------------------------------------------------------- + '\t if(p[0] === "rect") {\n' + '\t\t context.strokeRect(point[0], point[1], point[2], point[3]);\n' + '\t\t context.fillRect(point[0], point[1], point[2], point[3]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "quadratic") {\n' + '\t\t context.moveTo(point[0], point[1]);\n' + '\t\t context.quadraticCurveTo(point[2], point[3], point[4], point[5]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t if(p[0] === "bezier") {\n' + '\t\t context.moveTo(point[0], point[1]);\n' + '\t\t context.bezierCurveTo(point[2], point[3], point[4], point[5], point[6], point[7]);\n' + '\t }\n\n' // ------------------------------------------------------------- + '\t context.stroke();\n' + '\t context.fill();\n' + '}', // ------------------------------------------------------------- strokeFillText: '\n\nfunction strokeOrFill(lineWidth, strokeStyle, fillStyle, globalAlpha, globalCompositeOperation, lineCap, lineJoin, font) { \n' + '\t if(lineWidth) { \n' + '\t\t context.globalAlpha = globalAlpha;\n' + '\t\t context.globalCompositeOperation = globalCompositeOperation;\n' + '\t\t context.lineCap = lineCap;\n' + '\t\t context.lineJoin = lineJoin;\n' + '\t\t context.lineWidth = lineWidth;\n' + '\t\t context.strokeStyle = strokeStyle;\n' + '\t\t context.fillStyle = fillStyle;\n' + '\t\t context.font = font;\n' + '\t } \n\n' + '\t context.stroke();\n' + '\t context.fill();\n' + '}', // ------------------------------------------------------------- strokeOrFill: function(p) { if (!this.prevProps || this.prevProps !== p.join(',')) { this.prevProps = p.join(','); return 'strokeOrFill("' + p.join('", "') + '");'; } return 'strokeOrFill();'; }, // ------------------------------------------------------------- prevProps: null, shortenHelper: function(name, p1, p2) { var result = '["' + name + '", [' + p1.join(', ') + ']'; if (!this.prevProps || this.prevProps !== p2.join(',')) { this.prevProps = p2.join(','); result += ', ["' + p2.join('", "') + '"]'; } return result + '], '; } // ------------------------------------------------------------- }; // ------------------------------------------------------------- function endLastPath() { var cache = is; if (cache.isArc) arcHandler.end(); else if (cache.isQuadraticCurve) quadraticHandler.end(); else if (cache.isBezierCurve) bezierHandler.end(); drawHelper.redraw(); } // ------------------------------------------------------------- var copiedStuff = [], isControlKeyPressed; // ------------------------------------------------------------- function copy() { endLastPath(); dragHelper.global.startingIndex = 0; if (find('copy-last').checked) { copiedStuff = points[points.length - 1]; setSelection(find('drag-last-path'), 'DragLastPath'); } else { copiedStuff = points; setSelection(find('drag-all-paths'), 'DragAllPaths'); } } // ------------------------------------------------------------- function paste() { endLastPath(); dragHelper.global.startingIndex = 0; if (find('copy-last').checked) { points[points.length] = copiedStuff; dragHelper.global = { prevX: 0, prevY: 0, startingIndex: points.length - 1 }; dragHelper.dragAllPaths(0, 0); setSelection(find('drag-last-path'), 'DragLastPath'); } else { dragHelper.global.startingIndex = points.length; points = points.concat(copiedStuff); setSelection(find('drag-all-paths'), 'DragAllPaths'); } } // ------------------------------------------------------------- // ------------------------------------------------------------- var tools = { line: true, pencil: true, dragSingle: true, dragMultiple: true, eraser: true, rectangle: true, arc: true, bezier: true, quadratic: true, text: true }; if (params.tools) { tools = JSON.parse(params.tools); } function setSelection(element, prop) { endLastPath(); hideContainers(); is.set(prop); var selected = document.getElementsByClassName('selected-shape')[0]; if (selected) selected.className = selected.className.replace(/selected-shape/g, ''); element.className += ' selected-shape'; } // ------------------------------------------------------------- (function() { var cache = {}; var lineCapSelect = find('lineCap-select'); var lineJoinSelect = find('lineJoin-select'); // ------------------------------------------------------------- function getContext(id) { var context = find(id).getContext('2d'); context.lineWidth = 2; context.strokeStyle = '#6c96c8'; return context; } // ------------------------------------------------------------- function bindEvent(context, shape) { if (shape === 'Pencil') { lineCap = lineJoin = 'round'; } /* Default: setting default selected shape!! */ if (params.selectedIcon) { params.selectedIcon = params.selectedIcon.split('')[0].toUpperCase() + params.selectedIcon.replace(params.selectedIcon.split('').shift(1), ''); if (params.selectedIcon === shape) { is.set(params.selectedIcon); } } else is.set('Pencil'); addEvent(context.canvas, 'click', function() { dragHelper.global.startingIndex = 0; setSelection(this, shape); if (this.id === 'drag-last-path') { find('copy-last').checked = true; find('copy-all').checked = false; } else if (this.id === 'drag-all-paths') { find('copy-all').checked = true; find('copy-last').checked = false; } if (this.id === 'image-icon') { var selector = new FileSelector(); selector.selectSingleFile(function(file) { if (!file) return; var reader = new FileReader(); reader.onload = function(event) { var image = new Image(); image.onload = function() { var index = imageHandler.images.length; imageHandler.lastImageURL = image.src; imageHandler.lastImageIndex = index; imageHandler.images.push(image); }; image.src = event.target.result; }; reader.readAsDataURL(file); }); } if (this.id === 'pencil-icon' || this.id === 'eraser-icon') { cache.lineCap = lineCap; cache.lineJoin = lineJoin; lineCap = lineJoin = 'round'; } else if (cache.lineCap && cache.lineJoin) { lineCap = cache.lineCap; lineJoin = cache.lineJoin; } if (this.id === 'eraser-icon') { cache.strokeStyle = strokeStyle; cache.fillStyle = fillStyle; cache.lineWidth = lineWidth; strokeStyle = 'White'; fillStyle = 'White'; lineWidth = 10; } else if (cache.strokeStyle && cache.fillStyle && typeof cache.lineWidth !== 'undefined') { strokeStyle = cache.strokeStyle; fillStyle = cache.fillStyle; lineWidth = cache.lineWidth; } }); } // ------------------------------------------------------------- var toolBox = find('tool-box'); toolBox.style.height = (innerHeight /* - toolBox.offsetTop - 77 */ ) + 'px'; // ------------------------------------------------------------- function decorateDragLastPath() { var context = getContext('drag-last-path'); var x = 10, y = 6, line = "line", points = [ [line, x, y, x + 5, y + 27], [line, x, y, x + 18, y + 19], [line, x + 17, y + 19, x + 9, y + 20], [line, x + 9, y + 20, x + 5, y + 27], [line, x + 16, y + 22, x + 16, y + 31], [line, x + 12, y + 27, x + 20, y + 27] ], length = points.length, point, i; for (i = 0; i < length; i++) { point = points[i]; if (point[0] === "line") { context.beginPath(); context.moveTo(point[1], point[2]); context.lineTo(point[3], point[4]); context.closePath(); context.stroke(); } } context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Last', 18, 12); bindEvent(context, 'DragLastPath'); } if (tools.dragSingle === true) { decorateDragLastPath(); } else document.getElementById('drag-last-path').style.display = 'none'; // ------------------------------------------------------------- function decorateDragAllPaths() { var context = getContext('drag-all-paths'); var x = 10, y = 6, line = "line", points = [ [line, x, y, x + 5, y + 27], [line, x, y, x + 18, y + 19], [line, x + 17, y + 19, x + 9, y + 20], [line, x + 9, y + 20, x + 5, y + 27], [line, x + 16, y + 22, x + 16, y + 31], [line, x + 12, y + 27, x + 20, y + 27] ], length = points.length, point, i; for (i = 0; i < length; i++) { point = points[i]; if (point[0] === "line") { context.beginPath(); context.moveTo(point[1], point[2]); context.lineTo(point[3], point[4]); context.closePath(); context.stroke(); } } context.fillStyle = 'Gray'; context.font = '10px Verdana'; context.fillText('All', 20, 12); bindEvent(context, 'DragAllPaths'); } if (tools.dragMultiple === true) { decorateDragAllPaths(); } else document.getElementById('drag-all-paths').style.display = 'none'; // ------------------------------------------------------------- function decorateLine() { var context = getContext('line'); context.moveTo(0, 0); context.lineTo(40, 40); context.stroke(); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Line', 16, 12); bindEvent(context, 'Line'); } if (tools.line === true) { decorateLine(); } else document.getElementById('line').style.display = 'none'; // ------------------------------------------------------------- function decoratePencil() { var context = getContext('pencil-icon'); context.lineWidth = 5; context.lineCap = 'round'; context.moveTo(35, 20); context.lineTo(5, 35); context.stroke(); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Pencil', 6, 12); bindEvent(context, 'Pencil'); } if (tools.pencil === true) { decoratePencil(); } else document.getElementById('pencil-icon').style.display = 'none'; // ------------------------------------------------------------- function decorateEraser() { var context = getContext('eraser-icon'); context.lineWidth = 9; context.lineCap = 'round'; context.moveTo(35, 20); context.lineTo(5, 25); context.stroke(); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Eraser', 6, 12); bindEvent(context, 'Eraser'); } if (tools.eraser === true) { decorateEraser(); } else document.getElementById('eraser-icon').style.display = 'none'; // ------------------------------------------------------------- function decorateText() { var context = getContext('text-icon'); context.font = '22px Verdana'; context.strokeText('T', 15, 30); bindEvent(context, 'Text'); } if (tools.text === true) { decorateText(); } else document.getElementById('text-icon').style.display = 'none'; // ------------------------------------------------------------- function decorateImage() { var context = getContext('image-icon'); var image = new Image(); image.onload = function() { context.drawImage(image, 4, 4, 32, 32); bindEvent(context, 'Image'); }; image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAADFBMVEVYWFhVVVUAAABUVFTqqlXjAAAAA3RSTlMxdACUjPeLAAAATElEQVR42u3SQQrAMAwDQSn7/z+XFExTcOxroN3zgC4STecApy1gpP2gBgZXQMwKwJ23QITYACLlQBC9gAFNwJMXoJhVc7lBA/gsuAArEgqPcT12VgAAAABJRU5ErkJggg=='; } if (tools.image === true) { decorateImage(); } else document.getElementById('image-icon').style.display = 'none'; // ------------------------------------------------------------- function decorateArc() { var context = getContext('arc'); context.arc(20, 20, 16.3, Math.PI * 2, 0, 1); context.stroke(); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Arc', 10, 24); bindEvent(context, 'Arc'); } if (tools.arc === true) { decorateArc(); } else document.getElementById('arc').style.display = 'none'; // ------------------------------------------------------------- function decorateRect() { var context = getContext('rectangle'); context.strokeRect(5, 5, 30, 30); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Rect', 8, 24); bindEvent(context, 'Rectangle'); } if (tools.rectangle === true) { decorateRect(); } else document.getElementById('rectangle').style.display = 'none'; // ------------------------------------------------------------- function decorateQuadratic() { var context = getContext('quadratic-curve'); context.moveTo(0, 0); context.quadraticCurveTo(50, 10, 30, 40); context.stroke(); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('quad..', 2, 24); bindEvent(context, 'QuadraticCurve'); } if (tools.quadratic === true) { decorateQuadratic(); } else document.getElementById('quadratic-curve').style.display = 'none'; // ------------------------------------------------------------- function decorateBezier() { var context = getContext('bezier-curve'); var x = 0, y = 4; context.moveTo(x, y); context.bezierCurveTo(x + 86, y + 16, x - 45, y + 24, x + 48, y + 34); context.stroke(); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Bezier', 10, 8); bindEvent(context, 'BezierCurve'); } if (tools.bezier === true) { decorateBezier(); } else document.getElementById('bezier-curve').style.display = 'none'; // ------------------------------------------------------------- function tempStrokeTheLine(context, width, mx, my, lx, ly) { context.beginPath(); context.lineWidth = width; context.moveTo(mx, my); context.lineTo(lx, ly); context.stroke(); } function decorateLineWidth() { var context = getContext('line-width'); tempStrokeTheLine(context, 2, 5, 15, 35, 15); tempStrokeTheLine(context, 3, 5, 20, 35, 20); tempStrokeTheLine(context, 4, 5, 26, 35, 26); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Line', 8, 12); context.fillText('Width', 6, 38); var lineWidthContainer = find('line-width-container'), lineWidthText = find('line-width-text'), btnLineWidthDone = find('line-width-done'), h1 = document.getElementsByTagName('h1')[0], canvas = context.canvas; addEvent(canvas, 'click', function() { hideContainers(); lineWidthContainer.style.display = 'block'; lineWidthContainer.style.top = (canvas.offsetTop + 1) + 'px'; lineWidthContainer.style.left = (canvas.offsetLeft + canvas.clientWidth) + 'px'; lineWidthText.focus(); }); addEvent(btnLineWidthDone, 'click', function() { lineWidthContainer.style.display = 'none'; lineWidth = lineWidthText.value; }); } decorateLineWidth(); // ------------------------------------------------------------- function decorateColors() { var context = getContext('colors'); context.fillStyle = 'red'; context.fillRect(5, 3, 30, 10); context.fillStyle = 'green'; context.fillRect(5, 15, 30, 10); context.fillStyle = 'blue'; context.fillRect(5, 27, 30, 10); var colorsContainer = find('colors-container'), strokeStyleText = find('stroke-style'), fillStyleText = find('fill-style'), btnColorsDone = find('colors-done'), h1 = document.getElementsByTagName('h1')[0], canvas = context.canvas; addEvent(canvas, 'click', function() { hideContainers(); colorsContainer.style.display = 'block'; colorsContainer.style.top = (canvas.offsetTop + 1) + 'px'; colorsContainer.style.left = (canvas.offsetLeft + canvas.clientWidth) + 'px'; strokeStyleText.focus(); }); addEvent(btnColorsDone, 'click', function() { colorsContainer.style.display = 'none'; strokeStyle = strokeStyleText.value; fillStyle = fillStyleText.value; }); } decorateColors(); // ------------------------------------------------------------- function decorateAdditionalOptions() { var context = getContext('additional'); context.fillStyle = '#6c96c8'; context.font = '35px Verdana'; context.fillText('»', 10, 27); context.fillStyle = 'Gray'; context.font = '9px Verdana'; context.fillText('Extras!', 2, 38); var additionalContainer = find('additional-container'), btnAdditionalClose = find('additional-close'), h1 = document.getElementsByTagName('h1')[0], canvas = context.canvas, globalAlphaSelect = find('globalAlpha-select'), globalCompositeOperationSelect = find('globalCompositeOperation-select'); addEvent(canvas, 'click', function() { hideContainers(); additionalContainer.style.display = 'block'; additionalContainer.style.top = (canvas.offsetTop + 1) + 'px'; additionalContainer.style.left = (canvas.offsetLeft + canvas.clientWidth) + 'px'; }); addEvent(btnAdditionalClose, 'click', function() { additionalContainer.style.display = 'none'; globalAlpha = globalAlphaSelect.value; globalCompositeOperation = globalCompositeOperationSelect.value; lineCap = lineCapSelect.value; lineJoin = lineJoinSelect.value; }); } decorateAdditionalOptions(); // ------------------------------------------------------------- var designPreview = find('design-preview'), codePreview = find('code-preview'); // ------------------------------------------------------------- // todo: use this function in share-drawings.js // to sync buttons' states window.selectBtn = function(btn, isSkipWebRTCMessage) { codePreview.className = designPreview.className = ''; if (btn == designPreview) designPreview.className = 'preview-selected'; else codePreview.className = 'preview-selected'; if (!isSkipWebRTCMessage && window.connection && connection.numberOfConnectedUsers >= 1) { connection.send({ btnSelected: btn.id }); } else { // to sync buttons' UI-states if (btn == designPreview) btnDesignerPreviewClicked(); else btnCodePreviewClicked(); } }; // ------------------------------------------------------------- addEvent(designPreview, 'click', function() { selectBtn(designPreview); btnDesignerPreviewClicked(); }); function btnDesignerPreviewClicked() { codeText.parentNode.style.display = 'none'; optionsContainer.style.display = 'none'; hideContainers(); endLastPath(); } // ------------------------------------------------------------- addEvent(codePreview, 'click', function() { selectBtn(codePreview); btnCodePreviewClicked(); }); function btnCodePreviewClicked() { codeText.parentNode.style.display = 'block'; optionsContainer.style.display = 'block'; codeText.focus(); common.updateTextArea(); setHeightForCodeAndOptionsContainer(); hideContainers(); endLastPath(); } // ------------------------------------------------------------- var codeText = find('code-text'), optionsContainer = find('options-container'); // ------------------------------------------------------------- function setHeightForCodeAndOptionsContainer() { codeText.style.width = (innerWidth - optionsContainer.clientWidth - 30) + 'px'; codeText.style.height = (innerHeight - 40) + 'px'; codeText.style.marginLeft = (optionsContainer.clientWidth) + 'px'; optionsContainer.style.height = (innerHeight) + 'px'; } // ------------------------------------------------------------- var isAbsolute = find('is-absolute-points'), isShorten = find('is-shorten-code'); addEvent(isShorten, 'change', common.updateTextArea); addEvent(isAbsolute, 'change', common.updateTextArea); // ------------------------------------------------------------- })(); // ------------------------------------------------------------- function hideContainers() { var additionalContainer = find('additional-container'), colorsContainer = find('colors-container'), lineWidthContainer = find('line-width-container'); additionalContainer.style.display = colorsContainer.style.display = lineWidthContainer.style.display = 'none'; } // ------------------------------------------------------------- // ------------------------------------------------------------- var drawHelper = { // ------------------------------------------------------------- redraw: function(skipSync) { return; context.clearRect(0, 0, innerWidth, innerHeight); var i, point, length = points.length; for (i = 0; i < length; i++) { if(i == 0 && window.screenVideoElement) { context.drawImage(window.screenVideoElement, 0, -50, context.canvas.width, context.canvas.height); } else { point = points[i]; this[point[0]](context, point[1], point[2]); } } }, // ------------------------------------------------------------- getOptions: function() { return [lineWidth, strokeStyle, fillStyle, globalAlpha, globalCompositeOperation, lineCap, lineJoin, font]; }, // ------------------------------------------------------------- handleOptions: function(context, opt, isNoFillStroke) { opt = opt || this.getOptions(); context.globalAlpha = opt[3]; context.globalCompositeOperation = opt[4]; context.lineCap = opt[5]; context.lineJoin = opt[6]; context.lineWidth = opt[0]; context.strokeStyle = opt[1]; context.fillStyle = opt[2]; if (!isNoFillStroke) { context.stroke(); context.fill(); } }, // ------------------------------------------------------------- line: function(context, point, options) { context.beginPath(); context.moveTo(point[0], point[1]); context.lineTo(point[2], point[3]); this.handleOptions(context, options); }, // ------------------------------------------------------------- text: function(context, point, options) { var oldFillStyle = fillStyle; context.fillStyle = fillStyle === 'transparent' || fillStyle === 'White' ? 'Black' : fillStyle; context.font = '15px Verdana'; context.fillText(point[0].substr(1, point[0].length - 2), point[1], point[2]); fillStyle = oldFillStyle; this.handleOptions(context, options); }, // ------------------------------------------------------------- arc: function(context, point, options) { context.beginPath(); context.arc(point[0], point[1], point[2], point[3], 0, point[4]); this.handleOptions(context, options); }, // ------------------------------------------------------------- rect: function(context, point, options) { this.handleOptions(context, options, true); context.strokeRect(point[0], point[1], point[2], point[3]); context.fillRect(point[0], point[1], point[2], point[3]); }, // ------------------------------------------------------------- image: function(context, point, options) { this.handleOptions(context, options, true); var image = imageHandler.images[point[5]]; if (!image) { var image = new Image(); image.onload = function() { var index = imageHandler.images.length; imageHandler.lastImageURL = image.src; imageHandler.lastImageIndex = index; imageHandler.images.push(image); context.drawImage(image, point[1], point[2], point[3], point[4]); }; image.src = point[0]; return; } context.drawImage(image, point[1], point[2], point[3], point[4]); }, // ------------------------------------------------------------- quadratic: function(context, point, options) { context.beginPath(); context.moveTo(point[0], point[1]); context.quadraticCurveTo(point[2], point[3], point[4], point[5]); this.handleOptions(context, options); }, // ------------------------------------------------------------- bezier: function(context, point, options) { context.beginPath(); context.moveTo(point[0], point[1]); context.bezierCurveTo(point[2], point[3], point[4], point[5], point[6], point[7]); this.handleOptions(context, options); } // ------------------------------------------------------------- }; // ------------------------------------------------------------- // ------------------------------------------------------------- var dragHelper = { // ------------------------------------------------------------- global: { prevX: 0, prevY: 0, ismousedown: false, pointsToMove: 'all', startingIndex: 0 }, // ------------------------------------------------------------- mousedown: function(e) { // ------------------------------------------------------------- if (isControlKeyPressed) { copy(); paste(); isControlKeyPressed = false; } // ------------------------------------------------------------- var dHelper = dragHelper, g = dHelper.global; var x = e.pageX - canvas.offsetLeft, y = e.pageY - canvas.offsetTop; g.prevX = x; g.prevY = y; g.pointsToMove = 'all'; if (points.length) { var p = points[points.length - 1], point = p[1]; if (p[0] === 'line') { if (dHelper.isPointInPath(x, y, point[0], point[1])) { g.pointsToMove = 'head'; } if (dHelper.isPointInPath(x, y, point[2], point[3])) { g.pointsToMove = 'tail'; } } if (p[0] === 'rect') { if (dHelper.isPointInPath(x, y, point[0], point[1])) { g.pointsToMove = 'stretch-first'; } if (dHelper.isPointInPath(x, y, point[0] + point[2], point[1])) { g.pointsToMove = 'stretch-second'; } if (dHelper.isPointInPath(x, y, point[0], point[1] + point[3])) { g.pointsToMove = 'stretch-third'; } if (dHelper.isPointInPath(x, y, point[0] + point[2], point[1] + point[3])) { g.pointsToMove = 'stretch-last'; } } if (p[0] === 'image') { if (dHelper.isPointInPath(x, y, point[1], point[2])) { g.pointsToMove = 'stretch-first'; } if (dHelper.isPointInPath(x, y, point[1] + point[3], point[2])) { g.pointsToMove = 'stretch-second'; } if (dHelper.isPointInPath(x, y, point[1], point[2] + point[4])) { g.pointsToMove = 'stretch-third'; } if (dHelper.isPointInPath(x, y, point[1] + point[3], point[2] + point[4])) { g.pointsToMove = 'stretch-last'; } } if (p[0] === 'quadratic') {