轻量级网页客户端矢量图形绘制技术总结(lightweight techniques for online drawing)...

提到在线绘图,目前最流行的技术应该属Flex了(可参见另一篇文章:15个强大的在线图片编辑器 ),另外Silverlight在此方面也很有潜力。相比之下,诸多轻量级的客户端矢量图形绘制技术却显得有点鲜为人知。谨以此文总结我一年以来收集的此方面的相关资料与心得,与大家分享!

在一些web客户端客户端开发中,轻量级客户端矢量图形绘制技术还能够起到重要的作用。

1. VML 矢量标记语言

维基百科对VML的解释如下:

VML(Vector Markup Language) is an application of Extensible Markup Language (XML) 1.0 which defines a format for the encoding of vector information together with additional markup to describe how that information may be displayed and edited.

例子:使用VML与鼠标绘图:

 

ContractedBlock.gif ExpandedBlockStart.gif online drawing
<SCRIPT LANGUAGE="JavaScript"> 
  
var x,y,a,b;  
  
function drawline(fromX,fromY,toX,toY){   
  
var strElement=   "<v:Line id='line_"+fromX+"_"+fromY+"_"+toX+"_"+toY+"' from='" + fromX + "," + fromY + "' to='" + toX + "," + toY + "' strokecolor='red'></v:Line>";   
  
var newPoint = document.createElement(strElement);   
  document.getElementById(
"map").appendChild(newPoint);     
  }
  
function draw(){
    
if(x==undefined&&b==undefined){x=window.event.x;y=window.event.y;return false;}
    a
=window.event.x;b=window.event.y;
    drawline(x,y,a,b)
    x
=a;y=b;
  }
  
function draws(){
  
if(x==undefined&&b==undefined){return false;}
  
if(x==window.event.x&&b==window.event.y){return false;}
  
if(document.getElementById("TempLine")){document.getElementById("TempLine").outerHTML=""}
  
var strElement=   "<v:Line id='TempLine' from='" + x + "," + y + "' to='" + window.event.x + "," + window.event.y + "' strokecolor='red'></v:Line>";   
  
var newPoint = document.createElement(strElement);   
  document.getElementById(
"map").appendChild(newPoint);     
  }
</SCRIPT>   
<html xmlns:v="urn:schemas-microsoft-com:vml">   
<HEAD>   
<META http-equiv="Content-Type" content="text/html;Charset=gb2312">   
<title>vml example</title>   
<STYLE>   
v\:*
{behavior:url(#default#VML);}/*define V as VML variable*/   
</STYLE>   
</HEAD>   
<BODY>
<table border="1" align="center">
  
<tr>
    
<td><div id="map" style="width:600px;height:500px;background-color:#cccccc;position:relative;" onmousedown="draw();" onmousemove="draws()"></div></td>
  
</tr>
</table>
</body>   
</html>

 

VML作为一种XML的扩展,还在数据处理上很有用途,这里还有个例子:

例子:VML+XML绘制树型图表(Create a Tree Graph by VML+XML)

code is pick from internet, connect me if you are the author, Thanks.

 

 

ContractedBlock.gif ExpandedBlockStart.gif data.xml
<?xml version="1.0" encoding="utf-8"?>
<Company>
  
<Manager>
    
<DepartMentA>
      
<StafferA1 />
      
<StafferA2 />
      
<StafferA3 />
    
</DepartMentA>

    
<DepartMentB>
      
<StafferB1 />
      
<StafferB2 />
      
<StafferB3 />
    
</DepartMentB>

    
<DepartMentC>
      
<StafferC1 />
      
<StafferC2 />
      
<StafferC3 />
    
</DepartMentC>
  
</Manager>
</Company>

 

ContractedBlock.gif ExpandedBlockStart.gif vml.htm
<html xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<META HTTP-EQUIV="MSThemeCompatible" CONTENT="Yes">
<style type="text/css">
    v\:*
{
        behavior
:url(#default#VML);
    
}
    
    v\:RoundRect
{
        text-align
:center;
        position
:relative;
    
}
    
    v\:TextBox
{
        vertical-align
:middle;
        font-size
:13px;
    
}
</style>
    
<script type="text/javascript">
function $(id){
    
return document.getElementById(id);    
}

function Point2D(x,y){
    
this.x = x;
    
this.y = y;    
}

function Xml2Vml(xmlFile){
    
this.XML = new ActiveXObject("MSXML2.DOMDocument.5.0");
    
this.XML.async=false;
    
this.XML.load(xmlFile);
    
this.SpanX = 10;
    
this.SpanY = 25;
    
this.ItemWidth = 100;
    
this.ItemHeight = 25;
    
this.VmlRoot = document.createElement('<v:group coordsize="1000,1000" id="vml" style="width:1000px;height:1000px;">');
}

Xml2Vml.prototype.RecursiveParse 
= function(rootNode,offset){
    
var allChild = rootNode.childNodes;
    
var xOffset = offset.x;
    
var yOffset = offset.y;
    
if(allChild.length==0){
        rootNode.setAttribute(
"LeftX",xOffset);
        rootNode.setAttribute(
"RightX",xOffset+this.ItemWidth);
        xOffset 
+= this.SpanX + this.ItemWidth;
    }
else{
        
for(var i=0;i<allChild.length;i++){
            
var w = this.RecursiveParse(allChild[i],new Point2D(xOffset,yOffset+2*this.SpanY+this.ItemHeight));
            xOffset 
+= this.SpanX + w;
        }
        rootNode.setAttribute(
"LeftX",(parseInt(allChild[0].getAttribute("LeftX")) + parseInt(allChild[0].getAttribute("RightX")))/2);
        rootNode.setAttribute("RightX",(parseInt(allChild[allChild.length-1].getAttribute("LeftX")) + parseInt(allChild[allChild.length-1].getAttribute("RightX")))/2);
    }
    rootNode.setAttribute(
"PosY",yOffset);
    
return xOffset-offset.x-this.SpanX;
}

Xml2Vml.prototype.ParseXml 
= function(){
    
this.RecursiveParse(this.XML.documentElement,new Point2D(0,0));    
}

Xml2Vml.prototype.RecursiveRender 
= function(xmlNode){
    
var allChild = xmlNode.childNodes;
    
var xl = xmlNode.getAttribute("LeftX");
    
var xr = xmlNode.getAttribute("RightX");
    
var x = (parseInt(xl)+parseInt(xr))/2;
    var y = xmlNode.getAttribute("PosY");
    
var str = xmlNode.tagName;

    
if(xmlNode!=this.XML.documentElement) this.VmlRoot.appendChild(document.createElement('<v:line from="'+x+','+y+'" to="'+x+','+(parseInt(y)+this.SpanY)+'" />'));
    y
=parseInt(y)+this.SpanY;
    
var RoundRect = document.createElement('<v:RoundRect style="width:'+this.ItemWidth+'px;height:'+this.ItemHeight+'px;left:'+(x-this.ItemWidth/2)+'px;top:'+y+'px" align="center">')
    RoundRect.appendChild(document.createElement('<v:shadow on="True" type="single" color="#b3b3b3" offset="5px,5px"/>'));
    
var TextBox = document.createElement('<v:TextBox />');
    TextBox.innerHTML 
= str;
    RoundRect.appendChild(TextBox);
    
this.VmlRoot.appendChild(RoundRect);
    
    
if(allChild.length>0){
        y 
+= this.ItemHeight+this.SpanY;
        
this.VmlRoot.appendChild(document.createElement('<v:line from="'+x+','+(y-this.SpanY)+'" to="'+x+','+y+'" />'));
        xl 
= (parseInt(allChild[0].getAttribute("LeftX")) + parseInt(allChild[0].getAttribute("RightX")))/2;
        xr = (parseInt(allChild[allChild.length-1].getAttribute("LeftX")) + parseInt(allChild[allChild.length-1].getAttribute("RightX")))/2;
        this.VmlRoot.appendChild(document.createElement('<v:line from="'+xl+','+y+'" to="'+xr+','+y+'" />'));
        
for(var i=0;i<allChild.length;i++this.RecursiveRender(allChild[i]);
    }
}

Xml2Vml.prototype.RenderVml 
= function(){
    
this.RecursiveRender(this.XML.documentElement);    
}

</script>
</head>

<body>

<center>
    
<div id="div" style="WIDTH: 1000px; HEIGHT: 1000px"></div>
</center>

<script type="text/javascript">
var Ins = new Xml2Vml("data.xml");
Ins.ParseXml();
Ins.RenderVml();
$(
"div").appendChild(Ins.VmlRoot);
</script>

</body>
</html>

 

VML的相关资料:

http://www.w3.org/TR/NOTE-VML
http://en.wikipedia.org/wiki/Vector_Markup_Language
http://www.vml.org/Wnew.html

VML的在线案例:

http://www.tool.la/VMLPalette/

注:VML只支持IE5 以上的IE浏览器,请参见:

http://www.causeway.co.uk/demos/vml/index.htm

To view these charts you will need a VML enabled browser; this means IE5 or above with the VML component installed. Please don't be too annoyed if this page looks a complete mess in Firefox or Opera - VML is a Microsoft-specific format and will never be supported by standards-aware browsers.

 

2. SVG可扩展矢量图形

W3C网站对SVG的介绍:

SVG(Scalable Vector Graphics ) is a language for describing two-dimensional graphics and graphical applications in XML. SVG 1.1 is a W3C Recommendation and forms the core of the current SVG developments. SVG Tiny 1.2 is the specification currently being developed as the core of the SVG 1.2 language (comments welcome). The SVG Mobile Profiles: SVG Basic and SVG Tiny are targeted to resource-limited devices and are part of the 3GPP platform for third generation mobile phones. SVG Print is a set of guidelines to produce final-form documents in XML suitable for archiving and printing. Read more about SVG.

严格的来说,SVG并不是一种轻量级的绘图方案,因为它需要安装Adobe的SVG Viewer插件(2.78M),但SVG同样也是基于XML的,其强大的功能可以轻松的制作出各种动态和静态图型:

大量SVG例子:

下转自中国w3c联盟

动态
普通效果
http://www.adobe.com/svg/dynamic/transformations2.html

无JS干预效果
http://www.adobe.com/svg/dynamic/declarative.html

JS干预效果
http://www.adobe.com/svg/dynamic/javascript.html

鼠标事件效果,注意可以在HTML元素中干预效果,甚至可以在各个不同的SVG间互相干预
http://www.adobe.com/svg/dynamic/mouseevents.html

键盘事件效果,鼠标点击SVG后敲击键盘,如果字体完全消失,需要再点击
http://www.adobe.com/svg/dynamic/keyboardevents.html

动态插入对象
http://www.adobe.com/svg/dynamic/insertion.html

语言支持演示,支持国际任何语言(拿了日本的语言,中国啊,自强!)
http://www.adobe.com/svg/dynamic/insertion.html

SVG优秀的压缩算法及与JPG、GIF的质量比较
http://www.adobe.com/svg/workflow/optimizing.html

浏览插件的自动安装
http://www.adobe.com/svg/workflow/autoinstall.html

SVG在GoLive、Office、FramwMaker中的使用
http://www.adobe.com/svg/workflow/workflow.html

--------------
静态
点击以显示不同区域
http://www.adobe.com/svg/basics/boundbox.html

动态改变SVG字体及文字内容(无中文字体)
http://www.adobe.com/svg/basics/text.html

动态改变CSS
http://www.adobe.com/svg/basics/css.html

填充
http://www.adobe.com/svg/basics/fills.html

加边
http://www.adobe.com/svg/basics/strokes.html

渐变
http://www.adobe.com/svg/basics/grads.html

滤镜特效1、2
http://www.adobe.com/svg/basics/filtereffects.html
http://www.adobe.com/svg/basics/filtereffects2.html


与传统位图(Jpeg、Gif、Png)的结合
http://www.adobe.com/svg/basics/jpgs.html

ICC标准的色彩支持
http://www.adobe.com/svg/basics/icc.html

选择可见元素的设置
http://www.adobe.com/svg/basics/printing.html

SVG参考资料:

http://www.w3.org/Graphics/SVG/

 

3. Canvans

Firefox官方网站对Canvans的介绍:

<canvas>是一个新的HTML元素,这个元素可以被Script语言(通常是JavaScript)用来绘制图形。例如可以用它来画图、合成图象、或做简单的(和不那么简单的)动画。右面的图象展示了一些<canvas>的应用示例,我们将会在此教程中看到他们的实现。

注意:Canvans是HTML5标准中的新技术,这意味着所有不支持HTML5的浏览器都不能支持Canvans,包括IE

并不是所有现代浏览器都支持<canvas>元素,所以你需要 Firefox 1.5或更新版本、或者其他基于Gecko的浏览器例如Opera 9、或者最近版本的Safari才能看到所有示例的动作。

例子:简单Canvans例子,来自FF社区

ContractedBlock.gif ExpandedBlockStart.gif 请使用FF或Safari观看
<html>
  
<head>
    
<title>A canvas fillRect, strokeRect and clearRect example</title>
    
<meta name="DC.creator" content="Kamiel Martinet, http://www.martinet.nl/">
    
<meta name="DC.publisher" content="Mozilla Developer Center, http://developer.mozilla.org">
    
<script type="text/javascript">
      
function drawShape(){
        
// get the canvas element using the DOM
        var canvas = document.getElementById('tutorial');

        
// Make sure we don't execute when canvas isn't supported
        if (canvas.getContext){

          
// use getContext to use the canvas for drawing
          var ctx = canvas.getContext('2d');

          
// Draw shapes
          ctx.fillRect(25,25,100,100);
          ctx.clearRect(
45,45,60,60);
          ctx.strokeRect(
50,50,50,50);

        } 
else {
          alert(
'You need Safari or Firefox 1.5+ to see this demo.');
        }
      }
    
</script>
    
<style type="text/css">
      body 
{ margin: 20px; font-family: arial,verdana,helvetica; background: #fff;}
      h1 
{ font-size: 140%; font-weight:normal; color: #036; border-bottom: 1px solid #ccc; }
      canvas 
{ border: 2px solid #000; float: left; margin-right: 20px; margin-bottom: 20px; }
      pre 
{ float:left; display:block; background: rgb(238,238,238); border: 1px dashed #666; padding: 15px 20px; margin: 0 0 10px 0; }
    
</style>
  
</head>

  
<body onload="drawShape();">
    
<h1>An example of fillRect, clearRect and strokeRect</h1>
    
<div>
      
<canvas id="tutorial" width="150" height="150"></canvas>
<pre>
function drawShape(){
  // get the canvas element using the DOM
  var canvas = document.getElementById('tutorial');

  // Make sure we don't execute when canvas isn't supported
  if (canvas.getContext){

    // use getContext to use the canvas for drawing
    var ctx = canvas.getContext('2d');

    // Draw shapes
    ctx.fillRect(25,25,100,100);
    ctx.clearRect(45,45,60,60);
    ctx.strokeRect(50,50,50,50);
  }
}
</pre>
    
</div>
  
</body>

</html>

 

Canvans不仅能够绘制2D、3D的矢量图形,还可以与JS交互来实现一些复杂的动画:

 

Canvans教程:

https://developer.mozilla.org/cn/Canvas_tutorial

Canvas示例集 Canvas articles and other resources

 

4. 推荐的第三方开源框架:

除了上述三种技术之外,一些开源的WEB绘图框架也做的很好,尤其是在浏览器兼容方面,在此向大家推荐下列两个:

http://www.c-point.com/javascript_vector_draw.htm

http://www.walterzorn.com/jsgraphics/jsgraphics_e.htm

 

文章写的仓促,其实这方面技术有很深,不足之处请多多补充

Thanks. 

转载于:https://www.cnblogs.com/blodfox777/archive/2009/02/11/1388021.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值