簡體   English   中英

SVG到圖像的導出性能問題(使用canvg / XMLSerializer / getComputedStyle)

[英]SVG to Image export performance issues (using canvg / XMLSerializer / getComputedStyle)

我正在使用canvg將圖表的svg轉換為圖像。 我們的問題是,默認情況下,並非所有CSS屬性都應用於圖像,因此最終在循環中使用了getComputedStyle。

如果我們一次要導出10個甚至20個圖表,那么在性能方面這是一團糟。

 var labels = ['2018-10-01', '2018-10-02', '2018-10-03', '2018-10-04', '2018-10-05', '2018-10-06', '2018-10-07', '2018-10-08', '2018-10-09', '2018-10-10', '2018-10-11', '2018-10-12', '2018-10-13', '2018-10-14', '2018-10-15', '2018-10-16', '2018-10-17', '2018-10-18', '2018-10-19', '2018-10-20', '2018-10-21', '2018-10-22', '2018-10-23', '2018-10-24', '2018-10-25', '2018-10-26', '2018-10-27', '2018-10-28', '2018-10-29', '2018-10-30', '2018-10-31', '2018-11-01', '2018-11-02', '2018-11-03', '2018-11-04', '2018-11-05', '2018-11-06', '2018-11-07', '2018-11-08', '2018-11-09', '2018-11-10', '2018-11-11', '2018-11-12', '2018-11-13', '2018-11-14', '2018-11-15', '2018-11-16', '2018-11-17', '2018-11-18', '2018-11-19', '2018-11-20', '2018-11-21', '2018-11-22', '2018-11-23', '2018-11-24', '2018-11-25', '2018-11-26', '2018-11-27', '2018-11-28', '2018-11-29', '2018-11-30', '2018-12-01', '2018-12-02', '2018-12-03', '2018-12-04', '2018-12-05', '2018-12-06', '2018-12-07', '2018-12-08', '2018-12-09', '2018-12-10', '2018-12-11', '2018-12-12', '2018-12-13', '2018-12-14', '2018-12-15', '2018-12-16', '2018-12-17', '2018-12-18', '2018-12-19', '2018-12-20', '2018-12-21', '2018-12-22', '2018-12-23', '2018-12-24', '2018-12-25', '2018-12-26', '2018-12-27', '2018-12-28', '2018-12-29', '2018-12-30', '2018-12-31', '2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04', '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08', '2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12', '2019-01-13', '2019-01-14', '2019-01-15', '2019-01-16', '2019-01-17', '2019-01-18', '2019-01-19', '2019-01-20', '2019-01-21', '2019-01-22', '2019-01-23', '2019-01-24', '2019-01-25', '2019-01-26', '2019-01-27', '2019-01-28', '2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01', '2019-02-02', '2019-02-03', '2019-02-04', '2019-02-05', '2019-02-06', '2019-02-07', '2019-02-08', '2019-02-09', '2019-02-10', '2019-02-11', '2019-02-12', '2019-02-13', '2019-02-14', '2019-02-15', '2019-02-16', '2019-02-17', '2019-02-18', '2019-02-19', '2019-02-20', '2019-02-21', '2019-02-22', '2019-02-23', '2019-02-24', '2019-02-25', '2019-02-26', '2019-02-27', '2019-02-28']; var columns = ['data101', 'data2', 'data347']; var data = [ [0, 0, 2, 2, 1, 2, 7, 3, 1, 7, 5, 5, 5, 5, 6, 6, 11, 7, 2, 7, 16, 7, 3, 5, 10, 9, 11, 7, 3, 7, 7, 10, 10, 9, 18, 10, 20, 13, 9, 19, 16, 13, 20, 18, 14, 15, 18, 20, 19, 11, 13, 13, 12, 16, 11, 12, 21, 20, 23, 19, 19, 23, 23, 24, 23, 25, 21, 23, 20, 22, 21, 23, 24, 25, 27, 29, 28, 25, 24, 17, 20, 24, 22, 27, 21, 27, 19, 26, 31, 27, 28, 27, 21, 20, 27, 22, 22, 19, 17, 21, 23, 19, 22, 20, 21, 25, 15, 19, 20, 19, 21, 28, 17, 20, 14, 18, 17, 20, 27, 21, 18, 18, 20, 16, 27, 16, 16, 9, 18, 8, 19, 13, 8, 16, 15, 16, 9, 15, 10, 13, 10, 11, 10, 13, 12, 7, 14, 16, 13, 14, 8], [0, 0, 338, 1201, 1268, 1371, 1286, 1148, 446, 288, 228, 253, 193, 201, 283, 393, 436, 379, 421, 444, 444, 417, 513, 353, 364, 399, 238, 191, 305, 337, 365, 349, 365, 244, 101, 39, 55, 72, 151, 98, 31, 127, 114, 92, 104, 196, 307, 245, 84, 168, 41, 38, 292, 488, 536, 569, 495, 448, 408, 358, 344, 380, 328, 334, 332, 330, 345, 312, 369, 377, 356, 301, 226, 273, 237, 116, 178, 133, 114, 138, 95, 143, 74, 74, 83, 47, 75, 101, 96, 59, 46, 128, 70, 57, 93, 80, 94, 93, 63, 86, 81, 63, 70, 102, 91, 67, 69, 68, 88, 76, 79, 70, 119, 88, 74, 94, 76, 54, 82, 90, 75, 130, 67, 78, 106, 91, 81, 27, 77, 21, 104, 83, 55, 60, 62, 304, 393, 191, 292, 77, 76, 55, 125, 89, 99, 127, 60, 75, 99, 120, 56], [0, 0, 0, 1419, 7454, 12638, 10944, 7652, 4272, 11219, 9071, 7207, 7929, 8373, 9566, 6310, 7406, 9286, 8415, 7659, 6457, 3380, 10902, 10952, 10508, 7219, 4625, 4484, 4396, 5178, 5991, 7927, 14132, 14307, 5094, 10011, 6257, 9184, 18574, 12597, 11415, 7118, 9991, 10225, 14337, 4417, 12701, 17833, 23553, 10037, 4833, 5894, 19421, 14735, 12597, 8730, 5888, 11836, 13143, 17219, 10492, 10528, 8649, 11868, 10502, 6758, 7672, 8479, 11142, 22330, 26595, 4423, 17434, 8709, 9657, 7823, 9135, 19765, 18016, 16010, 8419, 7300, 8877, 9611, 9050, 8680, 8211, 6635, 3069, 10739, 6288, 6761, 7807, 16243, 20415, 23051, 19727, 8721, 6445, 8585, 13688, 14728, 17113, 16255, 3898, 4622, 3869, 3774, 4190, 3461, 4824, 4608, 4613, 3677, 3648, 3575, 3556, 4036, 3732, 2517, 4676, 4129, 3250, 4142, 3987, 4396, 3362, 2964, 1849, 2609, 2851, 3003, 3583, 3473, 3190, 2658, 4363, 3959, 4588, 3771, 4315, 3178, 3354, 3159, 2695, 4114, 4292, 3322, 1218, 3526, 3717] ]; var colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B']; var padding = 5; //prepare chart data var columnData = []; var chartDataColumns = []; var chartData = []; chartData.push([columns[0]].concat(data[0])); chartDataColumns = [ ['x'].concat(labels) ].concat(chartData); var chart1 = c3.generate({ bindto: d3.select('#chart1'), data: { x: 'x', columns: [['x'].concat(labels)].concat(chartData), type: 'line', onmouseover: function(d) { chart1.focus(d.id); chart2.focus(d.id); }, onmouseout: function() { chart1.revert(); chart2.revert(); } }, legend: { position: 'right', show: true, item: { onclick: function(id) { if (chart1) chart1.toggle(id); if (chart2) chart2.toogle(id); }, onmouseover: function(id) { if (chart1) chart1.focus(id); if (chart2) chart2.focus(id); }, onmouseout: function(id) { if (chart1) chart1.revert(); if (chart2) chart2.revert(); } } }, tooltip: { show: true, format: { value: function(value) { return d3.format(",.0f")(value); } } }, zoom: { enabled: true }, axis: { x: { type: 'timeseries', tick: { rotate: 90, format: '%Y-%m-%d' } }, y: { label: 'sample-data', tick: { format: d3.format(",") } } }, color: { pattern: colors } }); var chart2 = c3.generate({ bindto: d3.select('#chart2'), data: { columns: [[columns[0]].concat(data[0])], type: 'pie', onmouseover: function(id) { if (chart1) chart1.focus(id); if (chart2) chart2.focus(id); }, onmouseout: function(id) { if (chart1) chart1.revert(); if (chart2) chart2.revert(); } }, legend: { position: 'right', show: true, item: { onclick: function(id) { if (chart1) chart1.toggle(id); if (chart2) chart2.toogle(id); }, onmouseover: function(id) { if (chart1) chart1.focus(id); if (chart2) chart2.focus(id); }, onmouseout: function(id) { if (chart1) chart1.revert(); if (chart2) chart2.revert(); } } }, color: { pattern: colors }, }); for (var i = 1; i < columns.length; i++) { setTimeout(function(column) { chart1.load({ columns: [ [columns[column]].concat(data[column]) ] }); chart2.load({ columns: [[columns[column]].concat(data[column])] }); }, (i * 5000 / columns.length), i); } document.getElementById("exportButton").onclick = function() { exportChartToImage(); }; function exportChartToImage() { var createImagePromise = new Promise(function(resolve, reject) { var images = []; d3.selectAll('svg').each(function() { if (this.parentNode) { images.push(getSvgImage(this.parentNode, true)); } }); if (images.length > 0) resolve(images); else reject(images); }); createImagePromise.then(function(images) { images.forEach(function(img, n) { img.toBlob(function(blob) { saveAs(blob, "image_" + (n + 1) + ".png"); }); }); }) .catch(function(error) { throw error; }); }; /** * Converts a SVG-Chart to a canvas and returns it. */ function getSvgImage(svgContainer, png) { var svgEl = d3.select(svgContainer).select('svg').node(); var svgCopyEl = svgEl.cloneNode(true); if (!svgCopyEl) return; //remove elements not for printing lensObject = d3.selectAll(".hidden-print").remove().exit(); //add temp document objects var emptySvgEl = d3.select(document.createElementNS("http://www.w3.org/2000/svg", "svg")).attr("id", "emptysvg") .attr("version", 1.1) .attr("height", 2) .node(); var canvasComputed = d3.select(document.createElement("canvas")).attr("id", "canvasComputed").node(); var container = d3.select(document.createElement("div")).attr("style", "display: none;") .attr("class", "c3").node(); svgContainer.append(container); container.append(svgCopyEl); container.append(emptySvgEl); container.append(canvasComputed); //apply all CSS styles to SVG exportStyles(svgCopyEl, emptySvgEl); // transform SVG to canvas using external canvg canvg(canvasComputed, new XMLSerializer().serializeToString(svgCopyEl)); //remove temp document objects canvasComputed.remove(); emptySvgEl.remove(); svgCopyEl.remove(); container.remove(); return canvasComputed; } function exportStyles(svg, emptySvg) { var tree = []; var emptySvgDeclarationComputed = getComputedStyle(emptySvg); //d3.select(svg).selectAll().each(function() { $(svg).find("*").each(function() { explicitlySetStyle(this, emptySvgDeclarationComputed); }); } function traverse(obj, tree) { tree.push(obj); if (obj.hasChildNodes()) { var child = obj.firstChild; while (child) { if (child.nodeType === 1 && child.nodeName != 'SCRIPT') { traverse(child, tree); } child = child.nextSibling; } } return tree; } function explicitlySetStyle(element, emptySvgDeclarationComputed) { var cSSStyleDeclarationComputed = getComputedStyle(element); var i, len, key, value; var computedStyleStr = ""; for (i = 0, len = cSSStyleDeclarationComputed.length; i < len; i++) { key = cSSStyleDeclarationComputed[i]; value = cSSStyleDeclarationComputed.getPropertyValue(key); if (value !== emptySvgDeclarationComputed.getPropertyValue(key)) { if (key == 'visibility' && value == 'hidden') { computedStyleStr += 'display: none;'; } else { computedStyleStr += key + ":" + value + ";"; } } } element.setAttribute('style', computedStyleStr); } 
 <link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.12/c3.min.css" rel="stylesheet" /> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.12/c3.min.js"></script> <!-- Required to convert named colors to RGB --> <script src="https://cdnjs.cloudflare.com/ajax/libs/canvg/1.4/rgbcolor.min.js"></script> <!-- Optional if you want blur --> <script src="https://cdnjs.cloudflare.com/ajax/libs/stackblur-canvas/1.4.1/stackblur.min.js"></script> <!-- Main canvg code --> <script src="https://cdnjs.cloudflare.com/ajax/libs/canvg/1.5/canvg.js"></script> <script src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div id="chart1" class "c3"> </div> <div id="chart2" class="c3"> </div> <button type="button" id="exportButton"> export to SVG </button> 

=> http://jsfiddle.net/gothmogg/jLt3yq75/

該示例演示了如何將CSS樣式應用於SVG。 如果我們使用不帶getComputedStyle的普通canvg,則c3圖表的x和y軸看起來就像是一團糟。

您知道獲取有效圖像的更快方法嗎? 有沒有辦法過濾CSS樣式? 也許只使用“ c3”樣式?

我設法避免了使用getComputedStyle來解決將C3 SVG圖表導出到PNG的性能問題。

瀏覽C3中的問題,我發現了問題#313

https://github.com/c3js/c3/issues/313

對於其他人, http: //www.nihilogic.dk/labs/canvas2image/也可能是一個不錯的地方,但我在https://gist.github.com/aendrew/1ad2eed6afa29e30d52e#file-exportchart-js找到了解決方案-L29

我已經將代碼從使用angular更改為d3,現在可以使用了(對我來說)。

希望這可以幫助其他有同樣問題的人。

這里是工作代碼。 請注意:css樣式僅被檢查和內聯一次。

 var labels = ['2018-10-01', '2018-10-02', '2018-10-03', '2018-10-04', '2018-10-05', '2018-10-06', '2018-10-07', '2018-10-08', '2018-10-09', '2018-10-10', '2018-10-11', '2018-10-12', '2018-10-13', '2018-10-14', '2018-10-15', '2018-10-16', '2018-10-17', '2018-10-18', '2018-10-19', '2018-10-20', '2018-10-21', '2018-10-22', '2018-10-23', '2018-10-24', '2018-10-25', '2018-10-26', '2018-10-27', '2018-10-28', '2018-10-29', '2018-10-30', '2018-10-31', '2018-11-01', '2018-11-02', '2018-11-03', '2018-11-04', '2018-11-05', '2018-11-06', '2018-11-07', '2018-11-08', '2018-11-09', '2018-11-10', '2018-11-11', '2018-11-12', '2018-11-13', '2018-11-14', '2018-11-15', '2018-11-16', '2018-11-17', '2018-11-18', '2018-11-19', '2018-11-20', '2018-11-21', '2018-11-22', '2018-11-23', '2018-11-24', '2018-11-25', '2018-11-26', '2018-11-27', '2018-11-28', '2018-11-29', '2018-11-30', '2018-12-01', '2018-12-02', '2018-12-03', '2018-12-04', '2018-12-05', '2018-12-06', '2018-12-07', '2018-12-08', '2018-12-09', '2018-12-10', '2018-12-11', '2018-12-12', '2018-12-13', '2018-12-14', '2018-12-15', '2018-12-16', '2018-12-17', '2018-12-18', '2018-12-19', '2018-12-20', '2018-12-21', '2018-12-22', '2018-12-23', '2018-12-24', '2018-12-25', '2018-12-26', '2018-12-27', '2018-12-28', '2018-12-29', '2018-12-30', '2018-12-31', '2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04', '2019-01-05', '2019-01-06', '2019-01-07', '2019-01-08', '2019-01-09', '2019-01-10', '2019-01-11', '2019-01-12', '2019-01-13', '2019-01-14', '2019-01-15', '2019-01-16', '2019-01-17', '2019-01-18', '2019-01-19', '2019-01-20', '2019-01-21', '2019-01-22', '2019-01-23', '2019-01-24', '2019-01-25', '2019-01-26', '2019-01-27', '2019-01-28', '2019-01-29', '2019-01-30', '2019-01-31', '2019-02-01', '2019-02-02', '2019-02-03', '2019-02-04', '2019-02-05', '2019-02-06', '2019-02-07', '2019-02-08', '2019-02-09', '2019-02-10', '2019-02-11', '2019-02-12', '2019-02-13', '2019-02-14', '2019-02-15', '2019-02-16', '2019-02-17', '2019-02-18', '2019-02-19', '2019-02-20', '2019-02-21', '2019-02-22', '2019-02-23', '2019-02-24', '2019-02-25', '2019-02-26', '2019-02-27', '2019-02-28']; var columns = ['data101', 'data2', 'data347']; var data = [ [0, 0, 2, 2, 1, 2, 7, 3, 1, 7, 5, 5, 5, 5, 6, 6, 11, 7, 2, 7, 16, 7, 3, 5, 10, 9, 11, 7, 3, 7, 7, 10, 10, 9, 18, 10, 20, 13, 9, 19, 16, 13, 20, 18, 14, 15, 18, 20, 19, 11, 13, 13, 12, 16, 11, 12, 21, 20, 23, 19, 19, 23, 23, 24, 23, 25, 21, 23, 20, 22, 21, 23, 24, 25, 27, 29, 28, 25, 24, 17, 20, 24, 22, 27, 21, 27, 19, 26, 31, 27, 28, 27, 21, 20, 27, 22, 22, 19, 17, 21, 23, 19, 22, 20, 21, 25, 15, 19, 20, 19, 21, 28, 17, 20, 14, 18, 17, 20, 27, 21, 18, 18, 20, 16, 27, 16, 16, 9, 18, 8, 19, 13, 8, 16, 15, 16, 9, 15, 10, 13, 10, 11, 10, 13, 12, 7, 14, 16, 13, 14, 8], [0, 0, 338, 1201, 1268, 1371, 1286, 1148, 446, 288, 228, 253, 193, 201, 283, 393, 436, 379, 421, 444, 444, 417, 513, 353, 364, 399, 238, 191, 305, 337, 365, 349, 365, 244, 101, 39, 55, 72, 151, 98, 31, 127, 114, 92, 104, 196, 307, 245, 84, 168, 41, 38, 292, 488, 536, 569, 495, 448, 408, 358, 344, 380, 328, 334, 332, 330, 345, 312, 369, 377, 356, 301, 226, 273, 237, 116, 178, 133, 114, 138, 95, 143, 74, 74, 83, 47, 75, 101, 96, 59, 46, 128, 70, 57, 93, 80, 94, 93, 63, 86, 81, 63, 70, 102, 91, 67, 69, 68, 88, 76, 79, 70, 119, 88, 74, 94, 76, 54, 82, 90, 75, 130, 67, 78, 106, 91, 81, 27, 77, 21, 104, 83, 55, 60, 62, 304, 393, 191, 292, 77, 76, 55, 125, 89, 99, 127, 60, 75, 99, 120, 56], [0, 0, 0, 1419, 7454, 12638, 10944, 7652, 4272, 11219, 9071, 7207, 7929, 8373, 9566, 6310, 7406, 9286, 8415, 7659, 6457, 3380, 10902, 10952, 10508, 7219, 4625, 4484, 4396, 5178, 5991, 7927, 14132, 14307, 5094, 10011, 6257, 9184, 18574, 12597, 11415, 7118, 9991, 10225, 14337, 4417, 12701, 17833, 23553, 10037, 4833, 5894, 19421, 14735, 12597, 8730, 5888, 11836, 13143, 17219, 10492, 10528, 8649, 11868, 10502, 6758, 7672, 8479, 11142, 22330, 26595, 4423, 17434, 8709, 9657, 7823, 9135, 19765, 18016, 16010, 8419, 7300, 8877, 9611, 9050, 8680, 8211, 6635, 3069, 10739, 6288, 6761, 7807, 16243, 20415, 23051, 19727, 8721, 6445, 8585, 13688, 14728, 17113, 16255, 3898, 4622, 3869, 3774, 4190, 3461, 4824, 4608, 4613, 3677, 3648, 3575, 3556, 4036, 3732, 2517, 4676, 4129, 3250, 4142, 3987, 4396, 3362, 2964, 1849, 2609, 2851, 3003, 3583, 3473, 3190, 2658, 4363, 3959, 4588, 3771, 4315, 3178, 3354, 3159, 2695, 4114, 4292, 3322, 1218, 3526, 3717] ]; var colors = ['#0065A3', '#767670', '#D73648', '#7FB2CE', '#00345B']; var padding = 5; //prepare chart data var columnData = []; var chartDataColumns = []; var chartData = []; var C3Styles = null; chartData.push([columns[0]].concat(data[0])); chartDataColumns = [ ['x'].concat(labels) ].concat(chartData); var chart1 = c3.generate({ bindto: d3.select('#chart1'), data: { x: 'x', columns: [ ['x'].concat(labels) ].concat(chartData), type: 'line', onmouseover: function(d) { chart1.focus(d.id); chart2.focus(d.id); }, onmouseout: function() { chart1.revert(); chart2.revert(); } }, legend: { position: 'right', show: true, item: { onclick: function(id) { if (chart1) chart1.toggle(id); if (chart2) chart2.toogle(id); }, onmouseover: function(id) { if (chart1) chart1.focus(id); if (chart2) chart2.focus(id); }, onmouseout: function(id) { if (chart1) chart1.revert(); if (chart2) chart2.revert(); } } }, tooltip: { show: true, format: { value: function(value) { return d3.format(",.0f")(value); } } }, zoom: { enabled: true }, axis: { x: { type: 'timeseries', tick: { rotate: 90, format: '%Y-%m-%d' } }, y: { label: 'sample-data', tick: { format: d3.format(",") } } }, color: { pattern: colors } }); var chart2 = c3.generate({ bindto: d3.select('#chart2'), data: { columns: [ [columns[0]].concat(data[0]) ], type: 'pie', onmouseover: function(id) { if (chart1) chart1.focus(id); if (chart2) chart2.focus(id); }, onmouseout: function(id) { if (chart1) chart1.revert(); if (chart2) chart2.revert(); } }, legend: { position: 'right', show: true, item: { onclick: function(id) { if (chart1) chart1.toggle(id); if (chart2) chart2.toogle(id); }, onmouseover: function(id) { if (chart1) chart1.focus(id); if (chart2) chart2.focus(id); }, onmouseout: function(id) { if (chart1) chart1.revert(); if (chart2) chart2.revert(); } } }, color: { pattern: colors }, }); for (var i = 1; i < columns.length; i++) { setTimeout(function(column) { chart1.load({ columns: [ [columns[column]].concat(data[column]) ] }); chart2.load({ columns: [ [columns[column]].concat(data[column]) ] }); }, (i * 5000 / columns.length), i); } document.getElementById("exportButton").onclick = function() { exportChartToImage(); }; function exportChartToImage() { var createImagePromise = new Promise(function(resolve, reject) { var images = []; d3.selectAll('svg').each(function() { if (this.parentNode) { images.push(getSvgImage(this.parentNode, true)); } }); if (images.length > 0) resolve(images); else reject(images); }); createImagePromise.then(function(images) { images.forEach(function(img, n) { img.toBlob(function(blob) { saveAs(blob, "image_" + (n + 1) + ".png"); }); }); }) .catch(function(error) { throw error; }); }; /** * Converts a SVG-Chart to a canvas and returns it. */ function getSvgImage(svgContainer, png) { var svgEl = d3.select(svgContainer).select('svg').node(); var svgCopyEl = svgEl.cloneNode(true); if (!svgCopyEl) return; //remove elements not for printing lensObject = d3.selectAll(".hidden-print").remove().exit(); //add temp document objects var canvasComputed = d3.select(document.createElement("canvas")).attr("id", "canvasComputed").node(); var container = d3.select(document.createElement("div")).attr("style", "display: none;") .attr("class", "c3").node(); svgContainer.append(container); container.append(svgCopyEl); container.append(canvasComputed); /* taken from https://gist.github.com/aendrew/1ad2eed6afa29e30d52e#file-exportchart-js and changed from, angular to D3 functions */ /* Take styles from CSS and put as inline SVG attributes so that Canvg can properly parse them. */ var chartStyle; if (!C3Styles) { // Get rules from c3.css var styleSheets = document.styleSheets; for (var i = 0; i <= styleSheets.length - 1; i++) { if (styleSheets[i].href && (styleSheets[i].href.indexOf('c3.min.css') !== -1 || styleSheets[i].href.indexOf('c3.css') !== -1)) { try { if (styleSheets[i].rules !== undefined) { chartStyle = styleSheets[i].rules; } else { chartStyle = styleSheets[i].cssRules; } break; } //Note that SecurityError exception is specific to Firefox. catch (e) { if (e.name == 'SecurityError') { console.log("SecurityError. Cant read: " + styleSheets[i].href); continue; } } } if (chartStyle !== null && chartStyle !== undefined) { C3Styles = {}; var selector; // Inline apply all the CSS rules as inline for (i = 0; i < chartStyle.length; i++) { if (chartStyle[i].type === 1) { selector = chartStyle[i].selectorText; var styleDec = chartStyle[i].style; for (var s = 0; s < styleDec.length; s++) { C3Styles[styleDec[s]] = styleDec[styleDec[s]]; } } } } } } if (C3Styles) d3.select(svgCopyEl).selectAll('.c3:not(.c3-chart):not(path)').style(C3Styles); // SVG doesn't use CSS visibility and opacity is an attribute, not a style property. Change hidden stuff to "display: none" d3.select(svgCopyEl).selectAll('*') .filter(function(d) { return d && d.style && (d.style('visibility') === 'hidden' || d.style('opacity') === '0'); }) .style('display', 'none'); //fix weird back fill d3.select(svgCopyEl).selectAll("path").attr("fill", "none"); //fix no axes d3.select(svgCopyEl).selectAll("path.domain").attr("stroke", "black"); //fix no tick d3.select(svgCopyEl).selectAll(".tick line").attr("stroke", "black"); // transform SVG to canvas using external canvg canvg(canvasComputed, new XMLSerializer().serializeToString(svgCopyEl)); //remove temp document objects canvasComputed.remove(); svgCopyEl.remove(); container.remove(); return canvasComputed; } 
 <link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.12/c3.min.css" rel="stylesheet" /> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.6.12/c3.min.js"></script> <!-- Required to convert named colors to RGB --> <script src="https://cdnjs.cloudflare.com/ajax/libs/canvg/1.4/rgbcolor.min.js"></script> <!-- Optional if you want blur --> <script src="https://cdnjs.cloudflare.com/ajax/libs/stackblur-canvas/1.4.1/stackblur.min.js"></script> <!-- Main canvg code --> <script src="https://cdnjs.cloudflare.com/ajax/libs/canvg/1.5/canvg.js"></script> <script src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.min.js"></script> <div id="chart1" class "c3"> </div> <div id="chart2" class="c3"> </div> <button type="button" id="exportButton"> export to SVG </button> 

不幸

document.styleSheets[i].rules

無法在此處的腳本中訪問。 雖然它在我的環境中有效。 知道為什么這在這里不起作用嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM