問題
在WEB上使用二維圖形編程的人員如今面臨者一個兩難的選擇,是使用SVG,仍是VML?兩者的功能 類似,能夠知足大多數WEB二維圖形應用的需求,但目前的狀況是:VML只能在IE中使用,SVG被firefox,opera等瀏覽器的最新版本支持, 而且是W3C制定的開放標準,但目前IE不內置支持SVG,只能經過ADOBE的SVG插件顯示。
對於有特定用戶的應用,可能選擇哪種技術均可以,軟件提供方能夠要求用戶安裝和配置 所需的環境。但對於面向INTERNET用戶的應用,例如網上地圖等,這個問題就比較明顯了。IE無疑是最普遍使用的瀏覽器,並且大多數用戶在不瞭解網站 內容的狀況下,不會選擇下載並安裝一個4M多的SVG插件。而在技術上,SVG無疑前景更光明,並且被其它瀏覽器支持,能夠被非WINDOWS平臺用戶使 用。
思路
可否經過用戶瀏覽器的類型,自動在
SVG和VML之間切換,以在瀏覽器上顯示一樣(或基本類似)的圖形?(下面提到的SVG都是SVG1.1標準)
解決方法
1, 根據用戶瀏覽器狀況,設置顯示標誌
//設置使用SVG顯示標誌,缺省爲使用
var useSVG = true;
//若是爲IE則使用VML
if (navigator.appName == "Microsoft Internet Explorer")
useSVG = false;
//若是爲其它瀏覽器,則使用SVG,這裏用Opera
if (navigator.userAgent.search("Opera")>=0)
useSVG = true;
2, 在HTML初始化時,加載SVG或VML對象
if(useSVG)
{
var elem = document_createElement_x_x_x("embed");
elem.id = "svgCanvas";
elem.width = 500;
elem.height = 500;
elem.name = "svgCanvas";
elem.src = "canvas.svg";
elem.wmode = "transparent";
elem.type = "image/svg+xml";
document.body.insertBefore(elem,null);
}
else
{
var elem = document_createElement_x_x_x("v:group");
elem.id = "vmlCanvas";
elem.style.width = 500 + "px";
elem.style.height = 500 + "px";
elem.coordsize = "200,200";
document.body.insertBefore(elem,null);
}
以後,咱們就能夠分別在SVG或VML畫布上進行操做了。固然最好是定義一個與顯示無關的圖形對象。
3, 圖形對象,此處爲一個簡單的圓
function Bubble(id, cx, cy, r, stroke, fill)
{
this.id = id;
this.cx = cx;
this.cy = cy;
this.r = r;
this.stroke = stroke;
this.fill = fill;
this.draw = draw;
this.move = move;
}
其顯示和移動實現爲:
function draw()
{
if(useSVG)
{
//alert("svg");
var svgDocument = GetSvgDocument();
if(svgDocument == null)
return;
var elem = svgdocument_createElement_x_x_xNS(svgns, "circle" );
elem.setAttributeNS(null, "id", this.id);
elem.setAttributeNS(null, "cx", this.cx);
elem.setAttributeNS(null, "cy", this.cy);
elem.setAttributeNS(null, "r", this.r);
elem.setAttributeNS(null,"stroke",this.stroke);
elem.setAttributeNS(null,"fill",this.fill);
var svgCanvas = GetSvgCanvas();
if(svgCanvas == null)
return;
svgCanvas.a(elem);
}
else
{
//alert("vml");
var elem = document_createElement_x_x_x("v:oval");
with (elem.style)
{
position="absolute";
top=this.cy - this.r;
left=this.cx - this.r;
width=parseInt(this.r*2);
height=parseInt(this.r*2);
}
elem.coordorigin = "0,0";
elem.strokecolor=this.stroke;
elem.FillColor = this.fill;
vmlCanvas.insertBefore(elem,null);
}
}
function move(x, y)
{
this.cx = x;
this.cy = y;
}
4, 使用
var bubble1 = new Bubble("b1", 100, 100, 30, "purple", "green");
bubble1.draw();
var bubble2 = new Bubble("b2", 30, 20, 20, "red", "yellow");
bubble2.draw();
VML顯示:
SVG顯示
5,注意事項:
l 經過上面的圖能夠看出,儘管比較類似,但仍是有所不一樣,例如圓的邊線因爲使用的是缺省屬性,SVG和VML使用的筆畫粗細是不一樣。所以要顯示徹底相同的圖形要付出很大的工做量。
l 儘管
SVG和VML在大多數狀況下能夠互相替換,但仍是有一些對方不支持的特性和屬性。例如SVG中的動畫(animate)等,這些要在VML-SVG混合時儘可能避免使用,實在不行就只能使用腳本模擬實現了。
l SVG爲獨立的嵌入對象,所以要使用embedded列表取得,而VML能夠直接使用HTML的文檔對象。在SVG動態嵌入時,要判斷加載狀況,在加載完成後才能夠操做。
在SVG中加載事件中通知HTML
function OnLoadEvent(evt)
{
window.parent.svgLoadFlag = true;
}
在HTML初始化時,等待SVG加載完成標誌
if(useSVG)
{
//Wait svg load event
if ( svgLoadFlag == false )
{
setTimeout("renderObjects()",100);
return;
}
}
l 若是使用交互事件,例如鼠標操做等,SVG和VML的事件對象結構是不一樣的,傳遞方式也不相同,應分別處理,不過通常在獲得事件對象的屬性,例如座標位置,產生事件對象ID後,就可使用相同的處理函數了。例如:
//SVG的事件處理
function svgClick(evt)
{
var choiceId = evt.target.getAttributeNS(null,"id");
selectChoice(choiceId);
}
function vmlClick()
{
var choiceId = event.srcElement.name;
selectChoice(choiceId);
}