是的,有:将svg附加到文档中,并将所有包含的图像编码为dataURIs。
我正在编写一个脚本来执行此 *** 作,还编写了一些其他内容,例如包括外部样式表以及toDataURL失败的其他修复方法(例如,通过
xlink:hrefattribute或引用的外部元素
<funciri>)。
这是我编写的用于解析图像内容的函数:
function parseImages(){ var xlinkNS = "http://www.w3.org/1999/xlink"; var total, enpred; // convert an external bitmap image to a dataURL var toDataURL = function (image) { var img = new Image(); // CORS workaround, this won't work in IE<11 // If you are sure you don't need it, remove the next line and the double onerror handler // First try with crossorigin set, it should fire an error if not needed img.crossOrigin = 'Anonymous'; img.onload = function () { // we should now be able to draw it without tainting the canvas var canvas = document.createElement('canvas'); canvas.width = this.width; canvas.height = this.height; // draw the loaded image canvas.getContext('2d').drawImage(this, 0, 0); // set our <image>'s href attribute to the dataURL of our canvas image.setAttributeNS(xlinkNS, 'href', canvas.toDataURL()); // that was the last one if (++enpred === total) exportDoc(); }; // No CORS set in the response img.onerror = function () { // save the src var oldSrc = this.src; // there is an other problem this.onerror = function () { console.warn('failed to load an image at : ', this.src); if (--total === enpred && enpred > 0) exportDoc(); }; // remove the crossorigin attribute this.removeAttribute('crossorigin'); // retry this.src = ''; this.src = oldSrc; }; // load our external image into our img img.src = image.getAttributeNS(xlinkNS, 'href'); }; // get an external svg doc to data String var parseFromUrl = function(url, element){ var xhr = new XMLHttpRequest(); xhr.onload = function(){ if(this.status === 200){ var response = this.responseText || this.response; var dataUrl = 'data:image/svg+xml; charset=utf8, ' + enpreURIComponent(response); element.setAttributeNS(xlinkNS, 'href', dataUrl); if(++enpred === total) exportDoc(); } // request failed with xhr, try as an <img> else{ toDataURL(element); } }; xhr.onerror = function(){toDataURL(element);}; xhr.open('GET', url); xhr.send(); }; var images = svg.querySelectorAll('image'); total = images.length; enpred = 0; // loop through all our <images> elements for (var i = 0; i < images.length; i++) { var href = images[i].getAttributeNS(xlinkNS, 'href'); // check if the image is external if (href.indexOf('data:image') < 0){ // if it points to another svg element if(href.indexOf('.svg') > 0){ parseFromUrl(href, images[i]); } else // a pixel image toDataURL(images[i]); } // else increment our counter else if (++enpred === total) exportDoc(); } // if there were no <image> element if (total === 0) exportDoc();}
此处svgDoc称为
svg, 该
exportDoc()函数可以编写为:
var exportDoc = function() { // check if our svgNode has width and height properties set to absolute values // otherwise, canvas won't be able to draw it var bbox = svg.getBoundingClientRect(); if (svg.width.baseval.unitType !== 1) svg.setAttribute('width', bbox.width); if (svg.height.baseval.unitType !== 1) svg.setAttribute('height', bbox.height); // serialize our node var svgData = (new XMLSerializer()).serializeToString(svg); // remember to enpre special chars var svgURL = 'data:image/svg+xml; charset=utf8, ' + enpreURIComponent(svgData); var svgImg = new Image(); svgImg.onload = function () { var canvas = document.createElement('canvas'); // IE11 doesn't set a width on svg images... canvas.width = this.width || bbox.width; canvas.height = this.height || bbox.height; canvas.getContext('2d').drawImage(svgImg, 0, 0, canvas.width, canvas.height); doSomethingWith(canvas) }; svgImg.src = svgURL;};
但是再一次,您必须首先将svg附加到文档中(通过xhr或到
<iframe>或
<object>元素中),并且必须确保所有资源都 符合CORS要求(或来自同一域)才能获得这些资源呈现。
var svg = document.querySelector('svg');var doSomethingWith = function(canvas) { document.body.appendChild(canvas)};function parseImages() { var xlinkNS = "http://www.w3.org/1999/xlink"; var total, enpred; // convert an external bitmap image to a dataURL var toDataURL = function(image) { var img = new Image(); // CORS workaround, this won't work in IE<11 // If you are sure you don't need it, remove the next line and the double onerror handler // First try with crossorigin set, it should fire an error if not needed img.crossOrigin = 'anonymous'; img.onload = function() { // we should now be able to draw it without tainting the canvas var canvas = document.createElement('canvas'); canvas.width = this.width; canvas.height = this.height; // draw the loaded image canvas.getContext('2d').drawImage(this, 0, 0); // set our <image>'s href attribute to the dataURL of our canvas image.setAttributeNS(xlinkNS, 'href', canvas.toDataURL()); // that was the last one if (++enpred === total) exportDoc(); }; // No CORS set in the response img.onerror = function() { // save the src var oldSrc = this.src; // there is an other problem this.onerror = function() { console.warn('failed to load an image at : ', this.src); if (--total === enpred && enpred > 0) exportDoc(); }; // remove the crossorigin attribute this.removeAttribute('crossorigin'); // retry this.src = ''; this.src = oldSrc; }; // load our external image into our img var href = image.getAttributeNS(xlinkNS, 'href'); // really weird bug that appeared since this answer was first posted // we need to force a no-cached request for the crossOrigin be applied img.src = href + (href.indexOf('?') > -1 ? + '&1': '?1'); }; // get an external svg doc to data String var parseFromUrl = function(url, element) { var xhr = new XMLHttpRequest(); xhr.onload = function() { if (this.status === 200) { var response = this.responseText || this.response; var dataUrl = 'data:image/svg+xml; charset=utf8, ' + enpreURIComponent(response); element.setAttributeNS(xlinkNS, 'href', dataUrl); if (++enpred === total) exportDoc(); } // request failed with xhr, try as an <img> else { toDataURL(element); } }; xhr.onerror = function() { toDataURL(element); }; xhr.open('GET', url); xhr.send(); }; var images = svg.querySelectorAll('image'); total = images.length; enpred = 0; // loop through all our <images> elements for (var i = 0; i < images.length; i++) { var href = images[i].getAttributeNS(xlinkNS, 'href'); // check if the image is external if (href.indexOf('data:image') < 0) { // if it points to another svg element if (href.indexOf('.svg') > 0) { parseFromUrl(href, images[i]); } else // a pixel image toDataURL(images[i]); } // else increment our counter else if (++enpred === total) exportDoc(); } // if there were no <image> element if (total === 0) exportDoc();}var exportDoc = function() { // check if our svgNode has width and height properties set to absolute values // otherwise, canvas won't be able to draw it var bbox = svg.getBoundingClientRect(); if (svg.width.baseval.unitType !== 1) svg.setAttribute('width', bbox.width); if (svg.height.baseval.unitType !== 1) svg.setAttribute('height', bbox.height); // serialize our node var svgData = (new XMLSerializer()).serializeToString(svg); // remember to enpre special chars var svgURL = 'data:image/svg+xml; charset=utf8, ' + enpreURIComponent(svgData); var svgImg = new Image(); svgImg.onload = function() { var canvas = document.createElement('canvas'); // IE11 doesn't set a width on svg images... canvas.width = this.width || bbox.width; canvas.height = this.height || bbox.height; canvas.getContext('2d').drawImage(svgImg, 0, 0, canvas.width, canvas.height); doSomethingWith(canvas) }; svgImg.src = svgURL;};window.onload = parseImages;canvas { border: 1px solid green !important;}<svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1"> <defs> <pattern id="Pattern" x="0" y="0" width=".25" height=".25"> <image xlink:href="https://dl.dropboxusercontent.com/s/1alt1303g9zpemd/UFBxY.png" width="100" height="100"/> </pattern> </defs> <rect fill="url(#Pattern)" x="0" y="0" width="200" height="200"/></svg>
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)