自动选择SVG和VML的WEB页面

自动选择SVGVMLWEB页面
问题
       在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);
       }
      
//VML事件处理
       function vmlClick()
       {
var choiceId = event.srcElement.name;
              selectChoice(choiceId);
}
因此在VML/SVG混合编程时,采用MODEL-VIEW-CONTROL方式是比较好的一种模式。
posted on 2012-04-19 10:46  yujizais  阅读(414)  评论(0编辑  收藏  举报