UNPKG

@vikasietum_tecknology/record-rtc

Version:

record-rtc is a library based on recordrtc library. In this forked version of the original library we have optimized the memory management. The video recording is stored in IndexDB in chunks.

1,367 lines (1,084 loc) 126 kB
// Last time updated: 2017-07-03 1:56:26 PM UTC // _______________ // Canvas-Designer // https://github.com/muaz-khan/Canvas-Designer 'use strict'; (function() { var is = { isLine: false, isArrow: false, isArc: false, isDragLastPath: false, isDragAllPaths: false, isRectangle: false, isQuadraticCurve: false, isBezierCurve: false, isPencil: false, isMarker: true, isEraser: false, isText: false, isImage: false, set: function(shape) { var cache = this; cache.isLine = cache.isArrow = cache.isArc = cache.isDragLastPath = cache.isDragAllPaths = cache.isRectangle = cache.isQuadraticCurve = cache.isBezierCurve = cache.isPencil = cache.isMarker = cache.isEraser = cache.isText = cache.isImage = false; cache['is' + shape] = true; } }; function addEvent(element, eventType, callback) { if (eventType.split(' ').length > 1) { var events = eventType.split(' '); for (var i = 0; i < events.length; i++) { addEvent(element, events[i], callback); } return; } 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 = 2, strokeStyle = '#6c96c8', fillStyle = 'white', globalAlpha = 1, globalCompositeOperation = 'source-over', lineCap = 'round', font = '15px "Arial"', 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 = context.canvas; // either use "tempContext.canvas" or "context.canvas" context._clearRect = context.clearRect; context.clearRect = function(x, y, width, height) { context._clearRect(0, 0, context.canvas.width, context.canvas.height); fillStyle = 'white'; context.fillRect(0, 0, context.canvas.width, context.canvas.height); // fill white background }; 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' + drawArrow.toString() + '\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] === 'marker') { 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] = [this.strokeOrFill(p[2]) + '\ncontext.fillText(' + point[0] + ', ' + point[1] + ', ' + point[2] + ');']; } if (p[0] === 'arrow') { tempArray[i] = ['drawArrow(' + point[0] + ', ' + point[1] + ', ' + point[2] + ', ' + point[3] + ', \'' + p[2].join('\',\'') + '\');']; } 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 + '\n\n' + drawArrow.toString(); 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] === 'marker') { 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] === 'arrow') { 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' + drawArrow.toString() + '\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] === 'marker') { 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] === 'arrow') { output += 'drawArrow(' + getPoint(point[0], x, 'x') + ', ' + getPoint(point[1], y, 'y') + ', ' + getPoint(point[2], x, 'x') + ', ' + getPoint(point[3], y, 'y') + ', \'' + p[2].join('\',\'') + '\');\n'; } if (p[0] === 'text') { output += this.strokeOrFill(p[2]) + '\n' + 'context.fillText(' + point[0] + ', ' + getPoint(point[1], x, 'x') + ', ' + getPoint(point[2], y, 'y') + ');'; } 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 + '\n\n' + drawArrow.toString(); this.prevProps = null; }, forLoop: 'for(i; i < length; i++) {\n' + ' p = points[i];\n' + ' point = p[1];\n' + ' context.beginPath();\n\n' // globals + ' if(p[2]) { \n' + '\tcontext.lineWidth = p[2][0];\n' + '\tcontext.strokeStyle = p[2][1];\n' + '\tcontext.fillStyle = p[2][2];\n' + '\tcontext.globalAlpha = p[2][3];\n' + '\tcontext.globalCompositeOperation = p[2][4];\n' + '\tcontext.lineCap = p[2][5];\n' + '\tcontext.lineJoin = p[2][6];\n' + '\tcontext.font = p[2][7];\n' + ' }\n\n' // line + ' if(p[0] === "line") { \n' + '\tcontext.moveTo(point[0], point[1]);\n' + '\tcontext.lineTo(point[2], point[3]);\n' + ' }\n\n' // arrow + ' if(p[0] === "arrow") { \n' + '\tdrawArrow(point[0], point[1], point[2], point[3], p[2]);\n' + ' }\n\n' // pencil + ' if(p[0] === "pencil") { \n' + '\tcontext.moveTo(point[0], point[1]);\n' + '\tcontext.lineTo(point[2], point[3]);\n' + ' }\n\n' // marker + ' if(p[0] === "marker") { \n' + '\tcontext.moveTo(point[0], point[1]);\n' + '\tcontext.lineTo(point[2], point[3]);\n' + ' }\n\n' // text + ' if(p[0] === "text") { \n' + '\tcontext.fillText(point[0], point[1], point[2]);\n' + ' }\n\n' // eraser + ' if(p[0] === "eraser") { \n' + '\tcontext.moveTo(point[0], point[1]);\n' + '\tcontext.lineTo(point[2], point[3]);\n' + ' }\n\n' // arc + ' if(p[0] === "arc") context.arc(point[0], point[1], point[2], point[3], 0, point[4]); \n\n' // rect + ' if(p[0] === "rect") {\n' + '\tcontext.strokeRect(point[0], point[1], point[2], point[3]);\n' + '\tcontext.fillRect(point[0], point[1], point[2], point[3]);\n' + ' }\n\n' // quadratic + ' if(p[0] === "quadratic") {\n' + '\tcontext.moveTo(point[0], point[1]);\n' + '\tcontext.quadraticCurveTo(point[2], point[3], point[4], point[5]);\n' + ' }\n\n' // bezier + ' if(p[0] === "bezier") {\n' + '\tcontext.moveTo(point[0], point[1]);\n' + '\tcontext.bezierCurveTo(point[2], point[3], point[4], point[5], point[6], point[7]);\n' + ' }\n\n' // end-fill + ' context.stroke();\n' + ' context.fill();\n' + '}', strokeFillText: '\n\nfunction strokeOrFill(lineWidth, strokeStyle, fillStyle, globalAlpha, globalCompositeOperation, lineCap, lineJoin, font) { \n' + ' if(lineWidth) { \n' + '\tcontext.globalAlpha = globalAlpha;\n' + '\tcontext.globalCompositeOperation = globalCompositeOperation;\n' + '\tcontext.lineCap = lineCap;\n' + '\tcontext.lineJoin = lineJoin;\n' + '\tcontext.lineWidth = lineWidth;\n' + '\tcontext.strokeStyle = strokeStyle;\n' + '\tcontext.fillStyle = fillStyle;\n' + '\tcontext.font = font;\n' + ' } \n\n' + ' context.stroke();\n' + ' 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 drawArrow(mx, my, lx, ly, options) { function getOptions(opt) { opt = opt || {}; return [ opt.lineWidth || 2, opt.strokeStyle || '#6c96c8', opt.fillStyle || 'transparent', opt.globalAlpha || 1, opt.globalCompositeOperation || 'source-over', opt.lineCap || 'round', opt.lineJoin || 'round', opt.font || '15px "Arial"' ]; } function handleOptions(opt, isNoFillStroke) { opt = opt || 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]; context.font = opt[7]; if (!isNoFillStroke) { context.stroke(); context.fill(); } } var arrowSize = 10; var angle = Math.atan2(ly - my, lx - mx); context.beginPath(); context.moveTo(mx, my); context.lineTo(lx, ly); handleOptions(); context.beginPath(); context.moveTo(lx, ly); context.lineTo(lx - arrowSize * Math.cos(angle - Math.PI / 7), ly - arrowSize * Math.sin(angle - Math.PI / 7)); context.lineTo(lx - arrowSize * Math.cos(angle + Math.PI / 7), ly - arrowSize * Math.sin(angle + Math.PI / 7)); context.lineTo(lx, ly); context.lineTo(lx - arrowSize * Math.cos(angle - Math.PI / 7), ly - arrowSize * Math.sin(angle - Math.PI / 7)); handleOptions(); } function endLastPath() { var cache = is; if (cache.isArc) arcHandler.end(); else if (cache.isQuadraticCurve) quadraticHandler.end(); else if (cache.isBezierCurve) bezierHandler.end(); drawHelper.redraw(); if (textHandler.text && textHandler.text.length) { textHandler.appendPoints(); textHandler.onShapeUnSelected(); } textHandler.showOrHideTextTools('hide'); } 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'); } } // marker + pencil function hexToR(h) { return parseInt((cutHex(h)).substring(0, 2), 16) } function hexToG(h) { return parseInt((cutHex(h)).substring(2, 4), 16) } function hexToB(h) { return parseInt((cutHex(h)).substring(4, 6), 16) } function cutHex(h) { return (h.charAt(0) == "#") ? h.substring(1, 7) : h } function clone(obj) { if (obj === null || typeof(obj) !== 'object' || 'isActiveClone' in obj) return obj; if (obj instanceof Date) var temp = new obj.constructor(); //or new Date(obj); else var temp = obj.constructor(); for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { obj['isActiveClone'] = null; temp[key] = clone(obj[key]); delete obj['isActiveClone']; } } return temp; } function hexToRGB(h) { return [ hexToR(h), hexToG(h), hexToB(h) ] } var drawHelper = { redraw: function() { tempContext.clearRect(0, 0, innerWidth, innerHeight); context.clearRect(0, 0, innerWidth, innerHeight); var i, point, length = points.length; for (i = 0; i < length; i++) { point = points[i]; if (point && point.length && this[point[0]]) { this[point[0]](context, point[1], point[2]); } // else warn } }, getOptions: function(opt) { opt = opt || {}; return [ opt.lineWidth || lineWidth, opt.strokeStyle || strokeStyle, opt.fillStyle || fillStyle, opt.globalAlpha || globalAlpha, opt.globalCompositeOperation || globalCompositeOperation, opt.lineCap || lineCap, opt.lineJoin || lineJoin, opt.font || 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]; context.font = opt[7]; 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); }, marker: function(context, point, options) { context.beginPath(); context.moveTo(point[0], point[1]); context.lineTo(point[2], point[3]); this.handleOptions(context, options); }, arrow: function(context, point, options) { var mx = point[0]; var my = point[1]; var lx = point[2]; var ly = point[3]; var arrowSize = arrowHandler.arrowSize; if (arrowSize == 10) { arrowSize = (options ? options[0] : lineWidth) * 5; } var angle = Math.atan2(ly - my, lx - mx); context.beginPath(); context.moveTo(mx, my); context.lineTo(lx, ly); this.handleOptions(context, options); context.beginPath(); context.moveTo(lx, ly); context.lineTo(lx - arrowSize * Math.cos(angle - Math.PI / 7), ly - arrowSize * Math.sin(angle - Math.PI / 7)); context.lineTo(lx - arrowSize * Math.cos(angle + Math.PI / 7), ly - arrowSize * Math.sin(angle + Math.PI / 7)); context.lineTo(lx, ly); context.lineTo(lx - arrowSize * Math.cos(angle - Math.PI / 7), ly - arrowSize * Math.sin(angle - Math.PI / 7)); this.handleOptions(context, options); }, text: function(context, point, options) { this.handleOptions(context, options); context.fillStyle = textHandler.getFillColor(options[2]); context.fillText(point[0].substr(1, point[0].length - 2), point[1], point[2]); }, 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] === 'arrow') { 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') { if (dHelper.isPointInPath(x, y, point[0], point[1])) { g.pointsToMove = 'starting-points'; } if (dHelper.isPointInPath(x, y, point[2], point[3])) { g.pointsToMove = 'control-points'; } if (dHelper.isPointInPath(x, y, point[4], point[5])) { g.pointsToMove = 'ending-points'; } } if (p[0] === 'bezier') { if (dHelper.isPointInPath(x, y, point[0], point[1])) { g.pointsToMove = 'starting-points'; } if (dHelper.isPointInPath(x, y, point[2], point[3])) { g.pointsToMove = '1st-control-points'; } if (dHelper.isPointInPath(x, y, point[4], point[5])) { g.pointsToMove = '2nd-control-points'; } if (dHelper.isPointInPath(x, y, point[6], point[7])) { g.pointsToMove = 'ending-points'; } } } g.ismousedown = true; }, mouseup: function() { var g = this.global; if (is.isDragLastPath) { tempContext.clearRect(0, 0, innerWidth, innerHeight); context.clearRect(0, 0, innerWidth, innerHeight); this.end(); } g.ismousedown = false; }, mousemove: function(e) { var x = e.pageX - canvas.offsetLeft, y = e.pageY - canvas.offsetTop, g = this.global; drawHelper.redraw(); if (g.ismousedown) { this.dragShape(x, y); } if (is.isDragLastPath) this.init(); }, init: function() { if (!points.length) return; var p = points[points.length - 1], point = p[1], g = this.global; if (g.ismousedown) tempContext.fillStyle = 'rgba(255,85 ,154,.9)'; else tempContext.fillStyle = 'rgba(255,85 ,154,.4)'; if (p[0] === 'quadratic') { tempContext.beginPath(); tempContext.arc(point[0], point[1], 10, Math.PI * 2, 0, !1); tempContext.arc(point[2], point[3], 10, Math.PI * 2, 0, !1); tempContext.arc(point[4], point[5], 10, Math.PI * 2, 0, !1); tempContext.fill(); } if (p[0] === 'bezier') { tempContext.beginPath(); tempContext.arc(point[0], point[1], 10, Math.PI * 2, 0, !1); tempContext.arc(point[2], point[3], 10, Math.PI * 2, 0, !1); tempContext.arc(point[4], point[5], 10, Math.PI * 2, 0, !1); tempContext.arc(point[6], point[7], 10, Math.PI * 2, 0, !1); tempContext.fill(); } if (p[0] === 'line') { tempContext.beginPath(); tempContext.arc(point[0], point[1], 10, Math.PI * 2, 0, !1); tempContext.arc(point[2], point[3], 10, Math.PI * 2, 0, !1); tempContext.fill(); } if (p[0] === 'arrow') { tempContext.beginPath(); tempContext.arc(point[0], point[1], 10, Math.PI * 2, 0, !1); tempContext.arc(point[2], point[3], 10, Math.PI * 2, 0, !1); tempContext.fill(); } if (p[0] === 'text') { tempContext.font = "15px Verdana"; tempContext.fillText(point[0], point[1], point[2]); } if (p[0] === 'rect') { tempContext.beginPath(); tempContext.arc(point[0], point[1], 10, Math.PI * 2, 0, !1); tempContext.fill(); tempContext.beginPath(); tempContext.arc(point[0] + point[2], point[1], 10, Math.PI * 2, 0, !1); tempContext.fill(); tempContext.beginPath(); tempContext.arc(point[0], point[1] + point[3], 10, Math.PI * 2, 0, !1); tempContext.fill(); tempContext.beginPath(); tempContext.arc(point[0] + point[2], point[1] + point[3], 10, Math.PI * 2, 0, !1); tempContext.fill(); } if (p[0] === 'image') { tempContext.beginPath(); tempContext.arc(point[1], point[2], 10, Math.PI * 2, 0, !1); tempContext.fill(); tempContext.beginPath(); tempContext.arc(point[1] + point[3], point[2], 10, Math.PI * 2, 0, !1); tempContext.fill(); tempContext.beginPath(); tempContext.arc(point[1], point[2] + point[4], 10, Math.PI * 2, 0, !1); tempContext.fill(); tempContext.beginPath(); tempContext.arc(point[1] + point[3], point[2] + point[4], 10, Math.PI * 2, 0, !1); tempContext.fill(); } }, isPointInPath: function(x, y, first, second) { return x > first - 10 && x < first + 10 && y > second - 10 && y < second + 10; }, getPoint: function(point, prev, otherPoint) { if (point > prev) { point = otherPoint + (point - prev); } else { point = otherPoint - (prev - point); } return point; }, getXYWidthHeight: function(x, y, prevX, prevY, oldPoints) { if (oldPoints.pointsToMove == 'stretch-first') { if (x > prevX) { oldPoints.x = oldPoints.x + (x - prevX); oldPoints.width = oldPoints.width - (x - prevX); } else { oldPoints.x = oldPoints.x - (prevX - x); oldPoints.width = oldPoints.width + (prevX - x); } if (y > prevY) { oldPoints.y = oldPoints.y + (y - prevY); oldPoints.height = oldPoints.height - (y - prevY); } else { oldPoints.y = oldPoints.y - (prevY - y); oldPoints.height = oldPoints.height + (prevY - y); } } if (oldPoints.pointsToMove == 'stretch-second') { if (x > prevX) { oldPoints.width = oldPoints.width + (x - prevX); } else { oldPoints.width = oldPoints.width - (prevX - x); } if (y < prevY) { oldPoints.y = oldPoints.y + (y - prevY); oldPoints.height = oldPoints.height - (y - prevY); } else { oldPoints.y = oldPoints.y - (prevY - y); oldPoints.height = oldPoints.height + (prevY - y); } } if (oldPoints.pointsToMove == 'stretch-third') { if (x > prevX) { oldPoints.x = oldPoints.x + (x - prevX); oldPoints.width = oldPoints.width - (x - prevX); } else { oldPoints.x = oldPoints.x - (prevX - x); oldPoints.width = oldPoints.width + (prevX - x); } if (y < prevY) { oldPoints.height = oldPoints.height + (y - prevY); } else { oldPoints.height = oldPoints.height - (prevY - y); } } return oldPoints; }, dragShape: function(x, y) { if (!this.global.ismousedown) return; tempContext.clearRect(0, 0, innerWidth, innerHeight); if (is.isDragLastPath) { this.dragLastPath(x, y); } if (is.isDragAllPaths) { this.dragAllPaths(x, y); } var g = this.global; g.prevX = x; g.prevY = y; }, end: function() { if (!points.length) return; tempContext.clearRect(0, 0, innerWidth, innerHeight); var point = points[points.length - 1]; drawHelper[point[0]](context, point[1], point[2]); }, dragAllPaths: function(x, y) { var g = this.global, prevX = g.prevX, prevY = g.prevY, p, point, length = points.length, getPoint = this.getPoint, i = g.startingIndex; for (i; i < length; i++) { p = points[i]; point = p[1]; if (p[0] === 'line') { points[i] = [p[0], [ getPoint(x, prevX, point[0]), getPoint(y, prevY, point[1]), getPoint(x, prevX, point[2]), getPoint(y, prevY, point[3]) ], p[2] ]; } if (p[0] === 'arrow') { points[i] = [p[0], [ getPoint(x, prevX, point[0]), getPoint(y, prevY, point[1]), getPoint(x, prevX, point[2]), getPoint(y, prevY, point[3]) ], p[2] ]; } if (p[0] === 'text') { points[i] = [p[0], [ point[0], getPoint(x, prevX, point[1]), getPoint(y, prevY, point[2]) ], p[2] ]; } if (p[0] === 'arc') { points[i] = [p[0], [ getPoint(x, prevX, point[0]), getPoint(y, prevY, point[1]), point[2], point[3], point[4] ], p[2] ]; } if (p[0] === 'rect') { points[i] = [p[0], [ getPoint(x, prevX, point[0]), getPoint(y, prevY, point[1]), point[2], point[3] ], p[2] ]; } if (p[0] === 'image') { points[i] = [p[0], [ point[0], getPoint(x, prevX, point[1]), getPoint(y, prevY, point[2]), point[3], point[4], point[5] ], p[2] ]; } if (p[0] === 'quadratic') { points[i] = [p[0], [ getPoint(x, prevX, point[0]), getPoint(y, prevY, point[1]), getPoint(x, prevX, point[2]), getPoint(y, prevY, point[3]), getPoint(x, prevX, point[4]), getPoint(y, prevY, point[5]) ], p[2] ]; } if (p[0] === 'bezier') { points[i] = [p[0], [ getPoint(x, prevX, point[0]), getPoint(y, prevY, point[1]), getPoint(x, prevX, point[2]), getPoint(y, prevY, point[3]), getPoint(x, prevX, point[4]), getPoint(y, prevY, point[5]), getPoint(x, prevX, point[6]), getPoint(y, prevY, point[7]) ], p[2] ]; } } }, dragLastPath: function(x, y) { var g = this.global, prevX = g.prevX, prevY = g.prevY, p = points[points.length - 1], point = p[1], getPoint = this.getPoint, getXYWidthHeight = this.getXYWidthHeight, isMoveAllPoints = g.pointsToMove === 'all'; if (p[0] === 'line') { if (g.pointsToMove === 'head' || isMoveAllPoints) { point[0] = getPoint(x, prevX, point[0]); point[1] = getPoint(y, prevY, point[1]); } if (g.pointsToMove === 'tail' || isMoveAllPoints) { point[2] = getPoint(x, prevX, point[2]); point[3] = getPoint(y, prevY, point[3]); } points[points.length - 1] = [p[0], point, p[2]]; } if (p[0] === 'arrow') { if (g.pointsToMove === 'head' || isMoveAllPoints) { point[0] = getPoint(x, prevX, point[0]); point[1] = getPoint(y, prevY, point[1]); } if (g.pointsToMove === 'tail' || isMoveAllPoints) { point[2] = getPoint(x, prevX, point[2]); point[3] = getPoint(y, prevY, point[3]); } points[points.length - 1] = [p[0], point, p[2]]; } if (p[0] === 'text') { if (g.pointsToMove === 'head' || isMoveAllPoints) { point[1] = getPoint(x, prevX, point[1]); point[2] = getPoint(y, prevY, point[2]); } points[points.length - 1] = [p[0], point, p[2]]; } if (p[0] === 'arc') { point[0] = getPoint(x, prevX, point[0]); point[1] = getPoint(y, prevY, point[1]); points[points.length - 1] = [p[0], point, p[2]]; } if (p[0] === 'rect') { if (isMoveAllPoints) { point[0] = getPoint(x, prevX, point[0]); point[1] = getPoint(y, prevY, point[1]); } if (g.pointsToMove === 'stretch-first') { var newPoints = getXYWidthHeight(x, y, prevX, prevY, { x: point[0], y: point[1], width: point[2], height: point[3], pointsToMove: g.pointsToMove }); point[0] = newPoints.x; point[1] = newPoints.y; point[2] = newPoints.width; point[3] = newPoints.height; } if (g.pointsToMove === 'stretch-second') { var newPoints = getXYWidthHeight(x, y, prevX, prevY, { x: point[0], y: point[1], width: point[2], height: point[3], pointsToMove: g.pointsToMove }); point[1] = newPoints.y; point[2] = newPoints.width; point[3] = newPoints.height; } if (g.pointsToMove === 'stretch-third') { var newPoints = getXYWidthHeight(x, y, prevX, prevY, { x: point[0], y: point[1], width: point[2], height: point[3], pointsToMove: g.pointsToMove }); point[0] = newPoints.x; point[2] = newPoints.width; point[3] = newPoints.height; } if (g.pointsToMove === 'stretch-last') { point[2] = getPoint(x, prevX, point[2]); point[3] = getPoint(y, prevY, point[3]); } points[points.length - 1] = [p[0], point, p[2]];