From 602dd9dc2c0b1e3f773438ba60659dc95d9b1d40 Mon Sep 17 00:00:00 2001 From: Tadej Novak Date: Sun, 7 Dec 2014 16:30:57 +0100 Subject: [PATCH] Update detector rendering and attach SVG export JS file --- js/detector.js | 16 +- js/external/canvas2svg.js | 989 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 997 insertions(+), 8 deletions(-) create mode 100644 js/external/canvas2svg.js diff --git a/js/detector.js b/js/detector.js index bca5ac7..20de167 100644 --- a/js/detector.js +++ b/js/detector.js @@ -90,6 +90,7 @@ var detector = { detector.core.canvas = document.getElementById('detector-core'); detector.core.ctx = detector.core.canvas.getContext('2d'); + //detector.core.ctx = new C2S(400,400); detector.events.canvas = document.getElementById('detector-events'); detector.events.ctx = detector.events.canvas.getContext('2d'); @@ -180,9 +181,8 @@ var detector = ctx.lineTo(cx + detector.radius.mucal * Math.cos(Math.PI * i * muSplit) * detector.ratio, cy + detector.radius.mucal * Math.sin(Math.PI * i * muSplit) * detector.ratio); } ctx.stroke(); - ctx.globalCompositeOperation = 'destination-out'; + ctx.fillStyle = '#FFFFFF'; ctx.fill(); - ctx.globalCompositeOperation = 'source-over'; ctx.beginPath(); @@ -193,10 +193,9 @@ var detector = ctx.stroke(); ctx.beginPath(); - ctx.globalCompositeOperation = 'destination-out'; + ctx.fillStyle = '#FFFFFF'; ctx.arc(cx, cy, detector.radius.lightRingSpace * detector.ratio, 0, Math.PI * 2, true); ctx.fill(); - ctx.globalCompositeOperation = 'source-over'; ctx.beginPath(); ctx.strokeStyle = detector.colors.lightRingLine; @@ -206,10 +205,9 @@ var detector = ctx.stroke(); ctx.beginPath(); - ctx.globalCompositeOperation = 'destination-out'; + ctx.fillStyle = '#FFFFFF'; ctx.arc(cx, cy, detector.radius.darkRing1Space * detector.ratio, 0, Math.PI * 2, true); ctx.fill(); - ctx.globalCompositeOperation = 'source-over'; ctx.beginPath(); ctx.strokeStyle = detector.colors.darkRingLine @@ -219,10 +217,9 @@ var detector = ctx.stroke(); ctx.beginPath(); - ctx.globalCompositeOperation = 'destination-out'; + ctx.fillStyle = '#FFFFFF'; ctx.arc(cx, cy, detector.radius.ecal * detector.ratio, 0, Math.PI * 2, true); ctx.fill(); - ctx.globalCompositeOperation = 'source-over'; ctx.strokeStyle = detector.colors.hcalLine; @@ -234,6 +231,7 @@ var detector = ctx.lineTo(cx + detector.radius.hcal * Math.cos(Math.PI * i / calSplit) * detector.ratio, cy + detector.radius.hcal * Math.sin(Math.PI * i / calSplit) * detector.ratio); ctx.arc(cx, cy, detector.radius.hcal * detector.ratio, Math.PI * i / calSplit, Math.PI * (i+1) / calSplit, false); ctx.lineTo(cx + detector.radius.ecal * Math.cos(Math.PI * (i+1) / calSplit) * detector.ratio, cy + detector.radius.ecal * Math.sin(Math.PI * (i+1) / calSplit) * detector.ratio); + ctx.lineTo(cx + detector.radius.ecal * Math.cos(Math.PI * i / calSplit) * detector.ratio, cy + detector.radius.ecal * Math.sin(Math.PI * i / calSplit) * detector.ratio); ctx.closePath(); ctx.fill(); ctx.stroke(); @@ -323,3 +321,5 @@ window.requestAnimFrame = (function(){ window.setTimeout(callback, 1000 / 60); }; })(); + +(function() { detector.init(400); })(); diff --git a/js/external/canvas2svg.js b/js/external/canvas2svg.js new file mode 100644 index 0000000..d276d1c --- /dev/null +++ b/js/external/canvas2svg.js @@ -0,0 +1,989 @@ +/*!! + * Canvas 2 Svg v1.0.6 + * A low level canvas to SVG converter. Uses a mock canvas context to build an SVG document. + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + * Author: + * Kerry Liu + * + * Copyright (c) 2014 Gliffy Inc. + */ + +;(function() { + "use strict"; + + var STYLES, ctx, CanvasGradient, CanvasPattern, namedEntities; + + //helper function to format a string + function format(str, args) { + var keys = Object.keys(args), i; + for (i=0; i 1) { + options = defaultOptions; + options.width = arguments[0]; + options.height = arguments[1]; + } else if( !o ) { + options = defaultOptions; + } else { + options = o; + } + + if(!(this instanceof ctx)) { + //did someone call this without new? + return new ctx(options); + } + + //setup options + this.width = options.width || defaultOptions.width; + this.height = options.height || defaultOptions.height; + this.enableMirroring = options.enableMirroring !== undefined ? options.enableMirroring : defaultOptions.enableMirroring; + + this.canvas = this; ///point back to this instance! + this.__canvas = document.createElement("canvas"); + this.__ctx = this.__canvas.getContext("2d"); + + this.__setDefaultStyles(); + this.__stack = [this.__getStyleState()]; + this.__groupStack = []; + + //the root svg element + this.__root = document.createElementNS("http://www.w3.org/2000/svg", "svg"); + this.__root.setAttribute("version", 1.1); + this.__root.setAttribute("xmlns", "http://www.w3.org/2000/svg"); + this.__root.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink"); + this.__root.setAttribute("width", this.width); + this.__root.setAttribute("height", this.height); + + //make sure we don't generate the same ids in defs + this.__ids = {}; + + //defs tag + this.__defs = document.createElementNS("http://www.w3.org/2000/svg", "defs"); + this.__root.appendChild(this.__defs); + + //also add a group child. the svg element can't use the transform attribute + this.__currentElement = document.createElementNS("http://www.w3.org/2000/svg", "g"); + this.__root.appendChild(this.__currentElement); + + }; + + /** + * Creates the specified svg element + * @private + */ + ctx.prototype.__createElement = function(elementName, properties, resetFill) { + var element = document.createElementNS("http://www.w3.org/2000/svg", elementName), + keys = Object.keys(properties), i, key; + if(resetFill) { + //if fill or stroke is not specified, the svg element should not display. By default SVG's fill is black. + element.setAttribute("fill", "none"); + element.setAttribute("stroke", "none"); + } + for(i=0; i Math.PI ? 0 : 1; + } else { + largeArcFlag = diff > Math.PI ? 1 : 0; + } + + this.moveTo(startX, startY); + this.__addPathCommand(format("A {rx} {ry} {xAxisRotation} {largeArcFlag} {sweepFlag} {endX} {endY}", + {rx:radius, ry:radius, xAxisRotation:0, largeArcFlag:largeArcFlag, sweepFlag:sweepFlag, endX:endX, endY:endY})); + + }; + + /** + * Generates a ClipPath from the clip command. + */ + ctx.prototype.clip = function(){ + var group = this.__closestGroupOrSvg(), + clipPath = document.createElementNS("http://www.w3.org/2000/svg", "clipPath"), + id = randomString(this.__ids), + newGroup = document.createElementNS("http://www.w3.org/2000/svg", "g"); + + group.removeChild(this.__currentElement); + clipPath.setAttribute("id", id); + clipPath.appendChild(this.__currentElement); + + this.__defs.appendChild(clipPath); + + //set the clip path to this group + group.setAttribute("clip-path", format("url(#{id})", {id:id})); + + //clip paths can be scaled and transformed, we need to add another wrapper group to avoid later transformations + // to this path + group.appendChild(newGroup); + + this.__currentElement = newGroup; + + }; + + /** + * Draws a canvas, image or mock context to this canvas. + * Note that all svg dom manipulation uses node.childNodes rather than node.children for IE support. + * http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#dom-context-2d-drawimage + */ + ctx.prototype.drawImage = function(){ + //convert arguments to a real array + var args = Array.prototype.slice.call(arguments), + image=args[0], + dx, dy, dw, dh, sx=0, sy=0, sw, sh, parent, svg, defs, group, + currentElement, svgImage, canvas, context, id; + + if(args.length === 3) { + dx = args[1]; + dy = args[2]; + sw = image.width; + sh = image.height; + dw = sw; + dh = sh; + } else if(args.length === 5) { + dx = args[1]; + dy = args[2]; + dw = args[3]; + dh = args[4]; + sw = image.width; + sh = image.height; + } else if(args.length === 9) { + sx = args[1]; + sy = args[2]; + sw = args[3]; + sh = args[4]; + dx = args[5]; + dy = args[6]; + dw = args[7]; + dh = args[8]; + } else { + throw new Error("Inavlid number of arguments passed to drawImage: " + arguments.length); + } + + parent = this.__closestGroupOrSvg(); + currentElement = this.__currentElement; + + if(image instanceof ctx) { + //canvas2svg mock canvas context. In the future we may want to clone nodes instead. + //also I'm currently ignoring dw, dh, sw, sh, sx, sy for a mock context. + svg = image.getSvg(); + defs = svg.childNodes[0]; + while(defs.childNodes.length) { + id = defs.childNodes[0].getAttribute("id"); + this.__ids[id] = id; + this.__defs.appendChild(defs.childNodes[0]); + } + group = svg.childNodes[1]; + parent.appendChild(group); + this.__currentElement = group; + this.translate(dx, dy); + this.__currentElement = currentElement; + } else if(image.nodeName === "CANVAS" || image.nodeName === "IMG") { + //canvas or image + svgImage = document.createElementNS("http://www.w3.org/2000/svg", "image"); + svgImage.setAttribute("width", dw); + svgImage.setAttribute("height", dh); + svgImage.setAttribute("preserveAspectRatio", "none"); + + if(sx || sy || sw !== image.width || sh !== image.height) { + //crop the image using a temporary canvas + canvas = document.createElement("canvas"); + canvas.width = dw; + canvas.height = dh; + context = canvas.getContext("2d"); + context.drawImage(image, sx, sy, sw, sh, 0, 0, dw, dh); + image = canvas; + } + + svgImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", + image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src")); + parent.appendChild(svgImage); + this.__currentElement = svgImage; + this.translate(dx, dy); + this.__currentElement = currentElement; + } + }; + + /** + * Generates a pattern tag + */ + ctx.prototype.createPattern = function(image, repetition){ + var pattern = document.createElementNS("http://www.w3.org/2000/svg", "pattern"), id = randomString(this.__ids), + img; + pattern.setAttribute("id", id); + pattern.setAttribute("width", image.width); + pattern.setAttribute("height", image.height); + if(image.nodeName === "CANVAS" || image.nodeName === "IMG") { + img = document.createElementNS("http://www.w3.org/2000/svg", "image"); + img.setAttribute("width", image.width); + img.setAttribute("height", image.height); + img.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", + image.nodeName === "CANVAS" ? image.toDataURL() : image.getAttribute("src")); + pattern.appendChild(img); + this.__defs.appendChild(pattern); + } else if(image instanceof ctx) { + pattern.appendChild(image.__root.childNodes[1]); + this.__defs.appendChild(pattern); + } + return new CanvasPattern(pattern, this); + }; + + /** + * Not yet implemented + */ + ctx.prototype.drawFocusRing = function(){}; + ctx.prototype.createImageData = function(){}; + ctx.prototype.getImageData = function(){}; + ctx.prototype.putImageData = function(){}; + ctx.prototype.globalCompositeOperation = function(){}; + ctx.prototype.arcTo = function(){}; + ctx.prototype.setTransform = function(){}; + + //add options for alternative namespace + window.C2S = ctx; + +}());