简体   繁体   English

SVG 到 Canvas 的转换:生成的图像为空

[英]SVG to Canvas conversion: generated image is empty

I am trying to convert SVG string to PNG.我正在尝试将 SVG 字符串转换为 PNG。 But no luck with different approaches suggested.但是建议不同的方法没有运气。

Firstly, I tried creating an Object URL for SVG and using as source.首先,我尝试为 SVG 创建一个对象 URL 并用作源。 Second, directly giving svg source with type data:image/xml;utf-8 .其次,直接给出类型为data:image/xml;utf-8 svg 源。 And then converting SVG to base64 and using as source.然后将 SVG 转换为 base64 并用作源。

But none of them seem to work.但它们似乎都不起作用。

 var xmlSerializer = new XMLSerializer(); var svgString = xmlSerializer.serializeToString(window.container); var canvas = document.createElement("canvas"); var bounds = { width: 1040, height: 487 }; canvas.width = bounds.width; canvas.height = bounds.height; var context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); var DOMURL = self.URL || self.webkitURL || self; var ns = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; var svg = new Blob([ns + svgString], { type: 'image/svg+xml;charset=utf-8' }); var svg64 = btoa(ns + svgString); var b64Start = 'data:image/svg+xml;base64,'; // prepend a "header" var image64 = b64Start + svg64; var url = DOMURL.createObjectURL(svg); var image = new Image(); image.addEventListener('load', function() { context.drawImage(image, 0, 0, canvas.width, canvas.height); var png = canvas.toDataURL("image/png"); document.body.appendChild(image); DOMURL.revokeObjectURL(png); }); debugger; image.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(ns + svgString))));
 <svg xmlns="http://www.w3.org/2000/svg" style="position:absolute;left:0;top:0;-ms-transform:scale(1, -1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1)" id="container" viewBox="-2135.523613963039 -1000 4271.047227926078 2000" width="1040" height="487" xmlns:xlink="http://www.w3.org/1999/xlink"> <g type="Text" clip-path="url(#91f940b6-79d2-4a12-9189-96a95ae1662e)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e"> <rect fill="#67dfff" fill-opacity="0.5" stroke-opacity="1" font-size="49.28131416837823" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.49486652977413, 298.5694462268994) rotate(0) scale(1, -1)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" x="-246.4065708418891" y="-73.09379812628339" height="146.18759625256678" width="492.8131416837782" style="pointer-events: visible;" /> <text alignment-baseline="middle" style="pointer-events:none" fill="#ff9700" fill-opacity="1" stroke="#ff9700" stroke-opacity="1" font-size="49.28131416837823" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.49486652977413, 298.5694462268994) rotate(0) scale(1, -1)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e"> <tspan x="-234.08624229979478" y="-9.028089707391686">Test</tspan> <tspan x="-234.08624229979478" y="55.037618711500016">123</tspan> </text> <clipPath id="91f940b6-79d2-4a12-9189-96a95ae1662e"> <rect guid="91f940b6-79d2-4a12-9189-96a95ae1662e" fill="#67dfff" fill-opacity="0.5" stroke-opacity="1" font-size="49.28131416837823" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.49486652977413, 298.5694462268994) rotate(0) scale(1, -1)" x="-246.4065708418891" y="-73.09379812628339" height="146.18759625256678" width="492.8131416837782" /> </clipPath> </g> <g type="Pencil" guid="28d84559-a8c9-4077-89ac-aa8971ea5e39"> <path fill="none" stroke="#ff284f" stroke-opacity="1" stroke-width="20.53388090349108" transform="translate(-974.6748593308843, 246.95419530848943) rotate(0)" guid="28d84559-a8c9-4077-89ac-aa8971ea5e39" d="M-227.24163622010826 -324.2984800449713 L-217.11158830771967 -312.25193658159003 L-206.3166337755987 -298.28889756721634 L-194.38742677452285 -282.31810130894576 L-188.36415504283207 -274.46959571916705 L-175.22247126459854 -257.2211357602348 L-162.08078748636433 -239.9726758013026 L-146.06436038164145 -219.028117279742 L-130.0479332769188 -198.08355875818143 L-112.38879569991661 -173.4429016739925 L-94.72965812291488 -148.8022445898036 L-75.42781007363317 -122.10819941526562 L-56.12596202435191 -95.41415424072764 L-36.824113975070645 -67.0773985939104 L-17.522265925789156 -38.740642947093136 L2.190259741561931 -9.582532064136274 L21.90278540891302 19.57557881882059 L39.561922985914975 47.912334465637855 L57.22106056291716 76.24909011245512 L72.82681004956987 101.30042481471384 L88.43255953622304 126.35175951697255 L102.39559855059667 149.3497061288822 L116.35863756497054 172.3476527407919 L127.03625563478579 190.41746793586367 L137.71387370460081 208.48728313093557 L147.1594589202066 225.32506547179804 L156.60504413581236 242.16284781266046 L163.99724126106912 255.30453159089456 L171.38943838632565 268.44621536912865 L177.1389250393031 278.7131558208741 L182.88841169228056 288.9800962726194 L186.99518787297882 296.37229339787626 L191.10196405367708 303.7644905231329 L195.2087402343751 310.3353324122498 L199.31551641507326 316.9061743013668 L200.95822688735245 319.37024000978573 L202.60093735963176 321.8343057182046 L203.83297021384112 323.06633857241405 L205.0650030680506 324.2983714266234 L205.47568068612054 324.29837142662365 L205.88635830419037 324.29837142662365 L206.29703592226008 324.29837142662365 L206.7077135403299 324.29837142662365 L206.7077135403299 323.47701619048377 L206.7077135403299 322.6556609543442 L207.11839115839973 321.01295048206504 L207.52906877646956 319.37024000978573 L207.93974639453938 317.3168519194367 L208.3504240126091 315.2634638290876 L209.17177924874875 311.15668764838944 L209.9931344848884 307.0499114676912 L211.22516733909777 301.30042481471384 L212.45720019330724 295.5509381617365 L213.68923304751672 288.9800962726194 L214.9212659017261 282.4092543835023 L216.15329875593545 274.6063796401758 L217.38533161014493 266.80350489684935 L219.02804208242412 256.94724206317386 L220.6707525547033 247.09097922949826 L221.9027854089128 237.64539401389254 L223.13481826312238 228.19980879828677 L223.95617349926192 217.93286834654134 L224.77752873540157 207.66592789479597 L225.5988839715411 195.7562769707714 L226.42023920768077 183.84662604674674 L226.8309168257507 171.5262975046523 L227.24159444382053 159.2059689625578 L227.24159444382053 146.88564042046335 L227.24159444382053 134.56531187836885 L227.24159444382053 121.83430571820458 L227.24159444382053 109.1032995580403 L227.24159444382053 96.78297101594592 L227.24159444382053 84.46264247385142 L227.24159444382053 74.19570202210605 L227.24159444382053 63.92876157036068 L227.24159444382053 54.07249873668508 L227.24159444382053 44.216235903009476 L227.24159444382053 34.35997306933399 L227.24159444382053 24.503710235658446 L227.24159444382053 15.879480256192323 L227.24159444382053 7.255250276726173 L227.24159444382053 -0.13694684853052763 L227.24159444382053 -7.5291439737872 L227.24159444382053 -14.510663480974046 L227.24159444382053 -21.492182988160835 L227.24159444382053 -26.83099202306846 L227.24159444382053 -32.16980105797606 L227.24159444382053 -35.04454438446476 L227.24159444382053 -37.91928771095348 L227.24159444382053 -39.97267580130256 L227.24159444382053 -42.02606389165166 L227.24159444382053 -43.25809674586108 L227.24159444382053 -44.49012960007056 L227.24159444382053 -45.311484836210184 L227.24159444382053 -46.132840072349836 L227.24159444382053 -46.95419530848943 L227.24159444382053 -47.775550544629056 L227.24159444382065 -48.802244589803564 L227.24159444382065 -49.144475938195086 L227.24159444382065 -49.82893863497813 L227.24159444382065 -51.882326725327204 " style="pointer-events: visible;" /> </g> </svg>

First I optimized your SVG code using this online tool - it's better if you always optimize your SVG code - and with help from this example I modified your javascript code:首先,我使用这个在线工具优化了你的 SVG 代码——如果你总是优化你的 SVG 代码会更好——在这个例子的帮助下,我修改了你的 javascript 代码:

jsFiddle 1 - [ doesn't work in IE10, IE11 and Safari ] jsFiddle 1 - [在 IE10、IE11 和 Safari 中不起作用]

code:代码:

 var xmlSerializer = new XMLSerializer(); var svgString = xmlSerializer.serializeToString(window.container); var canvas = document.createElement("canvas"); var bounds = { width: 1040, height: 487 }; canvas.width = bounds.width; canvas.height = bounds.height; var ctx = canvas.getContext("2d"); var DOMURL = self.URL || self.webkitURL || self; var img = new Image(); var svg = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" }); var url = DOMURL.createObjectURL(svg); img.onload = function() { ctx.drawImage(img, 0, 0); var png = canvas.toDataURL("image/png"); var mg = document.createElement("img"); mg.setAttribute("src", png); document.body.appendChild(mg); DOMURL.revokeObjectURL(png); }; img.setAttribute("src", url);
 <h3>The SVG:</h3> <svg xmlns="http://www.w3.org/2000/svg" id="container" viewBox="-2135.5 -1000 4271 2000" width="1040" height="487"> <g type="Text" style="position:absolute; left:0; top:0; -ms-transform:scale(1, -1);-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-o-transform:scale(1, -1); transform:scale(1, -1)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" clip-path="url(#91f940b6-79d2-4a12-9189-96a95ae1662e)"> <rect fill="#67dfff" fill-opacity="0.5" stroke-opacity="1" font-size="49.3" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.5, 298.6) rotate(0) scale(1, -1)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" x="-246.4" y="-73.1" height="146.2" width="492.8" style="pointer-events: visible;" /> <text alignment-baseline="middle" font-size="49.3" text-decoration="none" font-family="Helvetica Neue" transform="translate(-57.5 298.6)rotate(0)scale(1 -1)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" style="fill:#ff9700;font-style:none;font-weight:none;pointer-events:none;stroke:#ff9700"> <tspan x="-234.1" y="-9"> Test</tspan> <tspan x="-234.1" y="55"> 123</tspan> </text> <clipPath id="91f940b6-79d2-4a12-9189-96a95ae1662e"> <rect guid="91f940b6-79d2-4a12-9189-96a95ae1662e" fill="#67dfff" fill-opacity="0.5" stroke-opacity="1" font-size="49.3" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.5, 298.6) rotate(0) scale(1, -1)" x="-246.4" y="-73.1" height="146.2" width="492.8" /> </clipPath> </g> <g type="Pencil" guid="28d84559-a8c9-4077-89ac-aa8971ea5e39"> <path guid="28d84559-a8c9-4077-89ac-aa8971ea5e39" d="M-1201.9-77.3L-1191.8-65.3 -1181-51.3 -1169.1-35.4 -1163-27.5 -1149.9-10.3 -1136.8 7 -1120.7 27.9 -1104.7 48.9 -1087.1 73.5 -1069.4 98.2 -1050.1 124.8 -1030.8 151.5 -1011.5 179.9 -992.2 208.2 -972.5 237.4 -952.8 266.5 -935.1 294.9 -917.5 323.2 -901.8 348.3 -886.2 373.3 -872.3 396.3 -858.3 419.3 -847.6 437.4 -837 455.4 -827.5 472.3 -818.1 489.1 -810.7 502.3 -803.3 515.4 -797.5 525.7 -791.8 535.9 -787.7 543.3 -783.6 550.7 -779.5 557.3 -775.4 563.9 -773.7 566.3 -772.1 568.8 -770.8 570 -769.6 571.3 -769.2 571.3 -768.8 571.3 -768.4 571.3 -768 571.3 -768 570.4 -768 569.6 -767.6 568 -767.1 566.3 -766.7 564.3 -766.3 562.2 -765.5 558.1 -764.7 554 -763.4 548.3 -762.2 542.5 -761 535.9 -759.8 529.4 -758.5 521.6 -757.3 513.8 -755.6 503.9 -754 494 -752.8 484.6 -751.5 475.2 -750.7 464.9 -749.9 454.6 -749.1 442.7 -748.3 430.8 -747.8 418.5 -747.4 406.2 -747.4 393.8 -747.4 381.5 -747.4 368.8 -747.4 356.1 -747.4 343.7 -747.4 331.4 -747.4 321.1 -747.4 310.9 -747.4 301 -747.4 291.2 -747.4 281.3 -747.4 271.5 -747.4 262.8 -747.4 254.2 -747.4 246.8 -747.4 239.4 -747.4 232.4 -747.4 225.5 -747.4 220.1 -747.4 214.8 -747.4 211.9 -747.4 209 -747.4 207 -747.4 204.9 -747.4 203.7 -747.4 202.5 -747.4 201.6 -747.4 200.8 -747.4 200 -747.4 199.2 -747.4 198.2 -747.4 197.8 -747.4 197.1 -747.4 195.1" style="fill:none;pointer-events:visible;stroke-width:20;stroke:#ff284f" /> </g> </svg> <hr> <h3>The image:</h3>


EDIT: to get it working in IE11 ( before, I only tested with chrome and FF ), the base64 encoded image needs to be injected into the src attribute of the created/appended image.编辑:为了让它在 IE11 中工作(之前,我只用 chrome 和 FF 进行了测试),需要将 base64 编码的图像注入到创建/附加图像的src属性中。

Also since we're following this approach we need to get rid of the transform: scale(1, -1) otherwise the "blueish" rectangle would look flipped vertically in IE, now it is like below:此外,由于我们遵循这种方法,我们需要摆脱transform: scale(1, -1)否则“蓝色”矩形在 IE 中看起来会垂直翻转,现在如下所示:

jsFiddle 2 - [ tested in Chrome, Fireforx, IE10+, but I have no idea about Safari (1) ] jsFiddle 2 - [在 Chrome、Fireforx、IE10+ 中测试,但我不知道 Safari (1) ]

code:代码:

 var xmlSerializer = new XMLSerializer(); var svgString = xmlSerializer.serializeToString(window.container); var canvas = document.createElement("canvas"); var bounds = { width: 1040, height: 487 }; canvas.width = bounds.width; canvas.height = bounds.height; var context = canvas.getContext('2d'); context.clearRect(0, 0, canvas.width, canvas.height); var DOMURL = self.URL || self.webkitURL || self; var ns = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'; var svg = new Blob([ns + svgString], { type: 'image/svg+xml;charset=utf-8' }); var svg64 = btoa(ns + svgString); var b64Start = 'data:image/svg+xml;base64,'; // prepend a "header" var image64 = b64Start + svg64; var url = DOMURL.createObjectURL(svg); var image = new Image(); image.addEventListener('load', function() { var mg = document.createElement("img"); // inject the base64 encoded image into the image source mg.setAttribute("src", image64); document.body.appendChild(mg); }); image.setAttribute("src", url);
 <h3>The SVG:</h3> <svg xmlns="http://www.w3.org/2000/svg" id="container" viewBox="-2135.5 -1000 4271 2000" width="1040" height="487"> <g type="Text" style="" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" clip-path="url(#91f940b6-79d2-4a12-9189-96a95ae1662e)"> <rect fill="#67dfff" fill-opacity="0.5" stroke-opacity="1" font-size="49.3" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.5, 298.6) rotate(0) scale(1, -1)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" x="-246.4" y="-73.1" height="146.2" width="492.8" style="pointer-events: visible;" /> <text alignment-baseline="middle" font-size="49.3" text-decoration="none" font-family="Helvetica Neue" transform="translate(-57.5 298.6) rotate(0)" guid="91f940b6-79d2-4a12-9189-96a95ae1662e" style="fill:#ff9700;font-style:none;font-weight:none;pointer-events:none;stroke:#ff9700"> <tspan x="-234.1" y="-9"> Test</tspan> <tspan x="-234.1" y="55"> 123</tspan> </text> <clipPath id="91f940b6-79d2-4a12-9189-96a95ae1662e"> <rect guid="91f940b6-79d2-4a12-9189-96a95ae1662e" fill="#67dfff" fill-opacity="0.5" stroke-opacity="1" font-size="49.3" text-decoration="none" font-style="none" font-weight="none" font-family="Helvetica Neue" transform="translate(-57.5, 298.6) rotate(0) scale(1, -1)" x="-246.4" y="-73.1" height="146.2" width="492.8" /> </clipPath> </g> <g type="Pencil" guid="28d84559-a8c9-4077-89ac-aa8971ea5e39"> <path guid="28d84559-a8c9-4077-89ac-aa8971ea5e39" d="M-1201.9-77.3L-1191.8-65.3 -1181-51.3 -1169.1-35.4 -1163-27.5 -1149.9-10.3 -1136.8 7 -1120.7 27.9 -1104.7 48.9 -1087.1 73.5 -1069.4 98.2 -1050.1 124.8 -1030.8 151.5 -1011.5 179.9 -992.2 208.2 -972.5 237.4 -952.8 266.5 -935.1 294.9 -917.5 323.2 -901.8 348.3 -886.2 373.3 -872.3 396.3 -858.3 419.3 -847.6 437.4 -837 455.4 -827.5 472.3 -818.1 489.1 -810.7 502.3 -803.3 515.4 -797.5 525.7 -791.8 535.9 -787.7 543.3 -783.6 550.7 -779.5 557.3 -775.4 563.9 -773.7 566.3 -772.1 568.8 -770.8 570 -769.6 571.3 -769.2 571.3 -768.8 571.3 -768.4 571.3 -768 571.3 -768 570.4 -768 569.6 -767.6 568 -767.1 566.3 -766.7 564.3 -766.3 562.2 -765.5 558.1 -764.7 554 -763.4 548.3 -762.2 542.5 -761 535.9 -759.8 529.4 -758.5 521.6 -757.3 513.8 -755.6 503.9 -754 494 -752.8 484.6 -751.5 475.2 -750.7 464.9 -749.9 454.6 -749.1 442.7 -748.3 430.8 -747.8 418.5 -747.4 406.2 -747.4 393.8 -747.4 381.5 -747.4 368.8 -747.4 356.1 -747.4 343.7 -747.4 331.4 -747.4 321.1 -747.4 310.9 -747.4 301 -747.4 291.2 -747.4 281.3 -747.4 271.5 -747.4 262.8 -747.4 254.2 -747.4 246.8 -747.4 239.4 -747.4 232.4 -747.4 225.5 -747.4 220.1 -747.4 214.8 -747.4 211.9 -747.4 209 -747.4 207 -747.4 204.9 -747.4 203.7 -747.4 202.5 -747.4 201.6 -747.4 200.8 -747.4 200 -747.4 199.2 -747.4 198.2 -747.4 197.8 -747.4 197.1 -747.4 195.1" style="fill:none;pointer-events:visible;stroke-width:20;stroke:#ff284f" /> </g> </svg> <hr><h3>The image:</h3>


Notes:笔记:

1 - OP did this image.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgString); 1 - OP 做了这个image.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgString); image.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgString); to get it working in Safari as well as other browsers.让它在 Safari 和其他浏览器中工作。

Final code here:最终代码在这里:

 var svgElement = document.querySelector('.design-review-container'); var asImage = function(svgString) { var drawImage = function(ctx, img, x, y, width, height, deg, flip) { //save current context before applying transformations ctx.save(); //convert degrees to radians if (flip) { var rad = deg * Math.PI / 180; } else { var rad = 2 * Math.PI - deg * Math.PI / 180; } //set the origin to the center of the image ctx.translate(x + width / 2, y + height / 2); //rotate the canvas around the origin ctx.rotate(rad); if (flip) { //flip the canvas ctx.scale(-1, 1); } //draw the image ctx.drawImage(img, -width / 2, -height / 2, width, height); //restore the canvas ctx.restore(); } var canvas = document.createElement("canvas"); var bounds = { width: parseInt(svgElement.getAttribute('width')), height: parseInt(svgElement.getAttribute('height')) }; var ht = bounds.height; var wd = bounds.width; canvas.setAttribute('width', wd); canvas.setAttribute('height', ht); var context = canvas.getContext('2d'); context.imageSmoothingEnabled = false; return new Promise(function(resolve, reject) { var image = new Image(); document.body.appendChild(image); image.onload = function() { drawImage(context, image, 0, 0, wd, ht, 180, true); resolve(canvas.toDataURL('image/png')); }; image.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgString); }); }; var xmlSerializer = new XMLSerializer(); var svgString = xmlSerializer.serializeToString(svgElement); asImage(svgString).then(function(src) { svgElement.parentNode.removeChild(svgElement); var image = new Image(); document.body.appendChild(image); image.src = src; });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM