1var svg_crowbar = function (svg_el, options){ 2 3 // TODO: should probably do some checking to make sure that svg_el is 4 // actually a <svg> and throw a friendly error otherwise 5 6 7 // get options passed to svg_crowbar 8 var filename = options.filename || "download.png"; 9 var width = options.width; // TODO: add fallback value based on svg attributes 10 var height = options.height; // TODO: add fallback value based on svg attributes 11 var crowbar_el = options.crowbar_el; // TODO: element for preparing the canvas element 12 13 // apply the stylesheet to the svg to be sure to capture all of the stylings 14 applyStylesheets(svg_el) 15 16 // grab the html from the svg and encode the svg in a data url 17 var html = svg_el.outerHTML; 18 var imgsrc = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(html))); 19 20 // create a canvas element that has the right dimensions 21 crowbar_el.innerHTML = ( 22 '<canvas width="' + width + '" height="' + height + '"></canvas>' 23 ) 24 var ua = navigator.userAgent.toLowerCase(); 25 // if (ua.indexOf('safari') != -1) { 26 // if (ua.indexOf('chrome') > -1) { 27 // } else { 28 // crowbar_el.innerHTML = ( 29 // '<canvas width="' + 1300 + '" height="' + 1000 + '"></canvas>' 30 // ) 31 // } 32 // } 33 34 var canvas = crowbar_el.querySelector("canvas"); 35 // var canvas = document.createElement("canvas"); 36 var context = canvas.getContext("2d"); 37 var image = new Image; 38 image.src = imgsrc; 39 40 image.onload = function() { 41 42 43 // draw the image in the context of the canvas and then get the 44 // image data from the canvas 45 // 46 // TODO: the resulting canvas image is a little on the grainy side. 47 // up until this point the image is lossless, so it definitely has 48 // something to do with the imgsrc getting lost when embedding in 49 // the canvas. this appears to be a problem with just about 50 // anything i've seen 51 52 53 context.drawImage(image, 0, 0); 54 var canvasdata = canvas.toDataURL("image/png", context); 55 56 var a = window.document.createElement("a"); 57 a.download = filename; 58 a.href = canvasdata; 59 document.body.appendChild(a); 60 a.click(); 61 document.body.removeChild(a); 62 63 canvasdata = null; 64 65 66 }; 67 68 69 70 // this is adapted (barely) from svg-crowbar 71 // https://github.com/NYTimes/svg-crowbar/blob/gh-pages/svg-crowbar-2.js#L211-L250 72 function applyStylesheets(svgEl) { 73 74 // use an empty svg to compute the browser applied stylesheets 75 var emptySvg = window.document.createElementNS("http://www.w3.org/2000/svg", 'svg'); 76 window.document.body.appendChild(emptySvg); 77 var emptySvgDeclarationComputed = getComputedStyle(emptySvg); 78 emptySvg.parentNode.removeChild(emptySvg); 79 80 // traverse the element tree and explicitly set all stylesheet values 81 // on an element. this is ripped from svg-crowbar 82 var allElements = traverse(svgEl); 83 var i = allElements.length; 84 while (i--){ 85 explicitlySetStyle(allElements[i], emptySvgDeclarationComputed); 86 } 87 } 88 89 90 function explicitlySetStyle (element, emptySvgDeclarationComputed) { 91 var cSSStyleDeclarationComputed = getComputedStyle(element); 92 var i, len, key, value; 93 var computedStyleStr = ""; 94 for (i=0, len=cSSStyleDeclarationComputed.length; i<len; i++) { 95 key=cSSStyleDeclarationComputed[i]; 96 value=cSSStyleDeclarationComputed.getPropertyValue(key); 97 if (value!==emptySvgDeclarationComputed.getPropertyValue(key)) { 98 computedStyleStr+=key+":"+value+";"; 99 } 100 } 101 element.setAttribute('style', computedStyleStr); 102 } 103 104 105 // traverse an svg and append all of the elements to the tree array. This 106 // ignores some elements that can appear in <svg> elements but whose 107 // children's styles should not be tweaked 108 function traverse(obj){ 109 var tree = []; 110 var ignoreElements = { 111 'script': undefined,
112 'defs': undefined, 113 }; 114 tree.push(obj); 115 visit(obj); 116 function visit(node) { 117 if (node && node.hasChildNodes() && !(node.nodeName.toLowerCase() in ignoreElements)) { 118 var child = node.firstChild; 119 while (child) { 120 if (child.nodeType === 1) { 121 tree.push(child); 122 visit(child); 123 } 124 child = child.nextSibling; 125 } 126 } 127 } 128 return tree; 129 } 130 131 132}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.