问题
在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_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_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_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_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);
}