自动选择SVG和VML的WEB页面
2006-10-23 10:03
363 查看
自动选择SVG和VML的WEB页面
问题
在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("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("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.createElementNS(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.appendChild(elem);
}
else
{
//alert("vml");
var elem = document.createElement("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);
}
//VML事件处理
function vmlClick()
{
var choiceId = event.srcElement.name;
selectChoice(choiceId);
}
因此在VML/SVG混合编程时,采用MODEL-VIEW-CONTROL方式是比较好的一种模式。
附:SVG和VML元素对应表(不全)
名称 | SVG | VML | 描述 |
矩形 | rect | rect | |
圆角矩形 | | roundrect | SVG中通过rect属性实现 |
直线 | line | line | |
圆 | circle | oval | |
椭圆 | ellipse | oval | |
折线 | polyline | polyline | |
多边形 | polygon | shape | |
曲线 | | arc | SVG中可以使用circle或path实现 |
路径 | path | path | |
文本 | text | textbox | |
文本段 | tpan | | |
路径文本 | textPath | textPath | |
| | | |
标题 | title | | |
描述 | desc | | |
| | | |
组 | group | group | |
预定义图形 | defs | vmlframe | |
| | | |
滤镜 | filter | | |
线性渐变 | linearGradient | | |
圆形渐变 | radialGradient | | |
图案 | pattern | | |
箭头 | marker | | 在stroke的属性StartArrow和EndArrow实现 |
剪裁 | clippath | | |
遮盖 | mask | | |
链接 | a | | |
| | | |
重用 | use | vmlframe | |
图形 | symbol | shape | |
光栅图像 | image | image | |
完整代码
HTML
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<title>VML-SVG-DEMO</title>
<STYLE>...
v:* {...}{ BEHAVIOR: url(#default#VML) }
</STYLE>
<script src="objects.js" language="JavaScript" type="text/javascript"></script>
<script src="initial.js" language="JavaScript" type="text/javascript"></script>
</head>
<body onload="init()"></body>
</html>
SVG
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 200" onload="OnLoadEvent(evt)">
<g id="Canvas"></g>
<script type="text/ecmascript">...
<![CDATA[
function OnLoadEvent(evt)
...{
window.parent.svgLoadFlag = true;
}
]]>
</script>
</svg>
初始化脚本
//useSVG = true; //you can also change this by hand
function renderObjects()
...{
if(useSVG)
...{
//Wait svg load event
if ( svgLoadFlag == false )
...{
setTimeout("renderObjects()",100);
return;
}
}
//alert(svgLoadFlag);
var bubble1 = new Bubble("b1", 100, 100, 30, "purple", "green");
bubble1.draw();
var bubble2 = new Bubble("b2", 30, 20, 20, "red", "yellow");
bubble2.draw();
}
function init()
...{
// Write svg embed object or vml group into html body
//
//<embed width='500' height='500' name='svgCanvas' src='canvas.svg' wmode='transparent' type='image/svg+xml' />
//<v:group id='vmlCanvas' style='WIDTH:500px;HEIGHT:500px;' coordsize = '200,200'/>;
if(useSVG)
...{
var elem = document.createElement("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("v:group");
elem.id = "vmlCanvas";
elem.style.width = 500 + "px";
elem.style.height = 500 + "px";
elem.coordsize = "200,200";
document.body.insertBefore(elem,null);
}
//Create graphic object and draw
renderObjects();
}
对象脚本
var useSVG = true;
var svgLoadFlag = false;
if (navigator.appName == "Microsoft Internet Explorer")
useSVG = false;
if (navigator.userAgent.search("Opera")>=0)
useSVG = true;
//alert(useSVG);
var svgns = "http://www.w3.org/2000/svg";
var xlinkNS = "http://www.w3.org/1999/xlink";
function GetSvgDocument()
...{
return(document.embeds[0].getSVGDocument());
}
function GetSvgCanvas()
...{
return(document.embeds[0].getSVGDocument().getElementById("Canvas"));
}
///
/// Bubble class
///
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.createElementNS(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.appendChild(elem);
}
else
...{
//alert("vml");
var elem = document.createElement("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;
}
///
/// Bubble class finish
///
相关文章推荐
- 自动选择SVG和VML的WEB页面
- 自动选择SVG和VML的WEB页面
- 自动选择SVG和VML的WEB页面
- 自动选择SVG和VML的WEB页面
- web国际化,使用accept-language+cookie自动选择语言跳转页面!
- Web图形开发,选择SVG还是VML
- 自动把纯文本转换成Web页面的php代码
- web底部页面自动加载
- 基于SVG的web页面图形绘制API介绍
- 解决VS2010打开Web页面时经常由于内存较低而导致VS2010自动关闭的问题
- 在 Asp.Net Web 应用程序中长时间装载页面时显示进度条 选择自 chenweionline 的 Blog
- 在WEB页面中根据分辨率自动调整内容宽度,以适应表格宽度
- 去掉移动web页面自动探测电话号码
- iOS WKwebview自动实现缩放网页适应屏幕和侧滑返回上个页面
- 在Web页面中控制其元素的选择状态
- web表单页面自动校验
- JavaWeb 将数据库查询结果展现到页面radio,根据页面用户选择查询数据库表结果
- webpack-dev-server自动更新页面
- 实现Web页面中级联菜单的设计/实现动态加载列表框/实现自动刷新页面/实现Web页面的局部动态更新/实现自动完成功能
- asp.net出错或404错误(找不到页面)自动跳转 webconfig配置方法