我正在使用SVG & JS在Web應用程序上工作。事情進展順利,但我對數據處理有些困惑。通過JavaScript訪問SVG數據
用戶創建的對象數據動態地附加到SVG根目錄。 Where &這個SVG數據如何存儲,&我該如何訪問它?我想閱讀它的原因是我想將這個SVG數據轉換成HTML5畫布(使用Google的canvg),最後將其轉換爲一個PNG圖像存儲在我們的數據庫中供參考。
任何指導將不勝感激。
我正在使用SVG & JS在Web應用程序上工作。事情進展順利,但我對數據處理有些困惑。通過JavaScript訪問SVG數據
用戶創建的對象數據動態地附加到SVG根目錄。 Where &這個SVG數據如何存儲,&我該如何訪問它?我想閱讀它的原因是我想將這個SVG數據轉換成HTML5畫布(使用Google的canvg),最後將其轉換爲一個PNG圖像存儲在我們的數據庫中供參考。
任何指導將不勝感激。
當Web瀏覽器加載SVG文件時,它(粗略地)分析字節流併爲SVG文件在內存中創建DOM結構。正是在腳本動態創建並向文檔添加新元素時修改了這種內存中表示。
您可以在這裏看到的這是一個非常簡單的例子:
http://phrogz.net/svg/svg_in_xhtml5.xhtml
的SVG文件加載在後臺的臉轉了一圈,然後JavaScript的動態創建的眼睛和鼻子,並追加他們爲子女SVG元素。
有三種方法,我知道的,你可以訪問這些信息,並把它變成一個畫布:
您可以步行元素自己的DOM,併發出畫布背景繪製命令:
var svg = document.getElementsByTagName('svg')[0];
var kids = svg.childNodes;
for (var i=0,len=kids.length;i<len;++i){
var kid = kids[i];
if (kid.nodeType!=1) continue; // skip anything that isn't an element
switch(kid.nodeName){
case 'circle':
// ...
break;
case 'path':
// ...
break;
// ...
}
}
請參閱SVG DOM reference以獲取有關可用屬性和方法的更多信息,或者僅使用DOM 2 Core方法來提取屬性。爲了簡單起見,您可能需要使用後者。
例如,既可以通過var cx = kid.cx.baseVal.value;
訪問當前(非SMIL動畫)使用SVG DOM的圓的cx
也可以更簡單地做var cx = kid.getAttribute('cx');
。
這將是簡單的,其中SVG和Canvas也有類似的命令(例如rect
或line
),工作一點點,他們不完全匹配(如circle
與arcTo
,polyline
一系列lineTo
命令) ,併爲path
元素及其many drawing commands做了大量工作。
每this answer和this paper,使用XMLSerializer
接口,以獲得SVG回來爲標記,使用直接作爲img
的來源,然後drawImage
是在畫布上。用我上面的例子:
var svg_xml = (new XMLSerializer).serializeToString(svg);
console.log(svg_xml);
// "<svg xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="full" viewBox="-350 -250 700 500">
// <circle r="200" class="face" fill="red"/>
// <path fill="none" class="face" transform="translate(-396,-230)" d="M487.41,282.411c-15.07,36.137-50.735,61.537-92.333,61.537 c-41.421,0-76.961-25.185-92.142-61.076"/>
// <circle cx="-60" cy="-50" r="20" fill="#000"/>
// <circle cx="60" cy="-50" r="20" fill="#000"/>
// </svg>"
var ctx = myCanvas.getContext('2d');
var img = new Image;
img.onload = function(){ ctx.drawImage(img,0,0); };
img.src = "data:image/svg+xml;base64,"+btoa(svg_xml);
如果你有SVG的XHTML(在我的例子),序列化不會捕捉到SVG塊外定義的樣式(如在我的例子),所以他們不會應用在圖像中。
注意,每this question/answer(礦),則必須之前設置onload
屬性如果你想IE9的兼容性,設置src
到數據URL。
不幸的是,由於什麼可能會或可能不會a bug,繪製一個數據URL圖像畫布造成的起源,清潔標誌被設置爲false
,這意味着你將無法調用toDataURL()
上畫布,並讓你的PNG回來。所以...
我想爲您的客戶端修改的SVG-> Canvas-> PNG-on-server的特定需求,您需要使用上面的第一步序列化svg_xml
,然後將該原始源傳遞給canvg。
或者,你可能會考慮每個序列化上面的SVG和提交直接到你的服務器,做server-side SVG-to-PNG conversion。
在@Phrogz答覆中提到WebKit的錯誤似乎已固定在新的版本,所以我發現不需要人工分析一個解決方案是
// from http://bl.ocks.org/biovisualize/1209499
// via https://groups.google.com/forum/?fromgroups=#!topic/d3-js/RnORDkLeS-Q
var xml = d3.select("svg")
.attr("title", "test2")
.attr("version", 1.1)
.attr("xmlns", "http://www.w3.org/2000/svg")
.node().parentNode.innerHTML;
// from http://webcache.googleusercontent.com/search?q=cache:http://phpepe.com/2012/07/export-raphael-graphic-to-image.html
// via http://stackoverflow.com/questions/4216927/problem-saving-as-png-a-svg-generated-by-raphael-js-in-a-canvas
var canvas = document.getElementById("myCanvas")
canvg(canvas, svgfix(xml));
document.location.href = canvas.toDataURL();
需要 https://code.google.com/p/svgfix/和https://code.google.com/p/canvg/和使用d3.js獲得svg源代碼,這應該是可行的,沒有d3.js(但這需要添加所需的元數據,這可能會導致缺少問題)。
這很奇妙的解釋。非常感謝Phrogz。 – Kayote 2011-03-07 14:03:36
精彩的回答!你還可以指出爲什麼類似* var svg = document.getElementById('svg')*將無法工作...... – 2012-10-30 09:20:49
@KeyBrdBasher這將工作只是找到,假設你有'