目标:了解vml和svg的兼容性写法
实现方式:代码和说明lizhi.js
由于时间仓促,类库写的很草率,纯粹一时性起玩乐之作,不过基本思路和兼容方式基本就是这样的,可能一些细节没太在意。
如果你真的想做一个svg和vml兼容类库可以参考代码思路,自己创作。如果有什么问题可以联系我,很乐意帮你解决。
/*
* 玩乐之作,思路经供参考。
* lizhi.0.1.js
* 作者:荔枝小站fanlizhi
*/
/*
*判断属性是否属于对象
*是返回true 不是返回 false
*/
function isEmptyObject(obj){
for(var name in obj){
return false;
}
return true;
}
/*
*基础全局对象F
*id canvas的外部div
*/
function F (id) {
return new F.prototype.init(id);
}
/*
* F.prototype 初始方法和属性
* F.prototype.init 返回 div dom 和 canvas 画板
* version 版本
* _NS svg xml命名空间
* _ISSVG 是否SVG
* _CNAME vml与元素关联的className
*/
F.fn = F.prototype = {
init : function(id){
this.c = document.getElementById(id);
this.r = this.initC();
return this;
},
version : '0.1',
_NS : 'http://www.w3.org/2000/svg',
_ISSVG : true,
_CNAME : 'fan'
}
/*
* F.prototype.initC
* 返回画板
*/
F.fn.initC = function(){
if(document.createElementNS){
var r = document.createElementNS(this._NS,'svg');
r.setAttribute('vesion','1.1');
r.setAttribute('xmlns',this._NS);
r.setAttribute('style','width:100%;height:100%;');
}else{
var head = document.getElementsByTagName("head")[0];
var style = document.createElement("style");
var r = document.createElement("div");
this._ISSVG = false;
document.namespaces.add("v", "urn:schemas-microsoft-com:vml");//添加命名空间
var cssStr = '.fan {behavior:url(#default#VML);} v\:*{behavior:url(#default#VML);}'; //添加元素和vml的关系
style.type = 'text/css';
style.styleSheet.cssText = cssStr;
head.appendChild(style);//添加到head里面
r.setAttribute('style','position:absolute;width:100%;height:100%;');
}
this.c.appendChild(r);
return r;
}
/*
* F.prototype.Line
* 返回line的element对象
*/
F.fn.Line = function(x1,y1,x2,y2){
return new E.prototype.initLine(this,x1,y1,x2,y2);
}
/*
* F.prototype.Path
* 返回Path的element对象
*/
F.fn.Path = function(path){
return new E.prototype.initPath(this,path);
}
/*
* F.prototype.Rect
* 返回Rect的element对象
*/
F.fn.Rect = function(x,y,width,height,corner){
return new E.fn.initRect(this,x,y,width,height,corner);
}
/*
* F.prototype.ellipse
* 返回Ellipse的element对象
*/
F.fn.Ellipse = function(cx,cy,rx,ry){
return new E.fn.initEllipse(this,cx,cy,rx,ry);
}
/*
* 将 F.prototype 属性,方法添加到 F.prototype.init.prototype 上
* 将 将F的全局方法属性给画布
*/
F.fn.init.prototype = F.fn;
/*
* ELement 对象
*/
function E(){}
/*
* E.prototype 放属于element的参数
* _VML, SVG 中的attr为统一样式名
*/
E.fn = E.prototype = {
_VML : {'attr':{'stroke-width':'strokeweight','stroke':'strokecolor','opacity':'opacity','dashstyle':'dashstyle','joinstyle':'joinstyle','fill':'fillcolor','src':'src'}},
_SVG : {'attr':{'stroke-width':'stroke-width','stroke':'stroke','opacity':'fill-opacity','dashstyle':'stroke-dasharray','joinstyle':'stroke-linecap','fill':'fill','src':'href'}}
}
E.fn.svgFormatDashstyle = function (val) {
var strokew = this.dom.getAttribute('stroke-width');
switch (val) {
case 'Dash':
return strokew*4+','+strokew*5;
break;
case 'Dot':
return strokew*1+','+strokew*4;
break;
default:
return 'none';
}
}
/*
* 初始化样式属性
*/
E.fn.initAttr = function(el,attrs){
var attrs = attrs || {};
if(!this.F._ISSVG){
var stroke = document.createElement("stroke");
stroke.className = this.F._CNAME;
el.appendChild(stroke);
var fill = document.createElement("fill");
fill.className = this.F._CNAME;
el.appendChild(fill);
fill.setAttribute('opacity','0');
}else{
el.setAttribute('stroke','#000');//默认
el.setAttribute('fill','none');//默认 兼容vml
}
if(el.nodeName === 'path'){
el.setAttribute('stroke','#000');//默认
el.setAttribute('fill','none');//默认 兼容vml
}
return el;
}
/*
* 调用path的时候初始化vml shape
*/
E.fn.initPath_VML = function(F){
var dom = document.createElement("shape");
dom.style.position = 'absolute';
dom.style.width = '1px';
dom.style.height= '1px';
dom.setAttribute('coordsize','1,1');
dom.className = F._CNAME;
return dom;
}
/*
* 调用path的时候初始化SVG path
*/
E.fn.initPath_SVG = function(F){
var dom = document.createElementNS(F._NS,"path");
return dom;
}
/*
* E.prototype.initLine 初始化 line对象
*/
E.fn.initLine = function(F,x1,y1,x2,y2){
if (F._ISSVG) {
var dom = document.createElementNS(F._NS,"line");
dom.setAttribute('x1',x1);
dom.setAttribute('y1',y1);
dom.setAttribute('x2',x2);
dom.setAttribute('y2',y2);
dom.setAttribute('stroke','#000');
}else{
var dom = this.initPath_VML(F);
var path = 'M'+x1+' '+y1+'L'+x2+' '+y2+'e';
dom.path = path;
}
this.F = F;
this.dom = dom;
dom = this.initAttr(dom);
F.r.appendChild(dom);
return this;
}
/*
* E.prototype.initPath 初始化 path对象
*/
E.fn.initPath = function(F,path){
path = path.toUpperCase();
if(F._ISSVG){
var dom = E.fn.initPath_SVG(F);
dom.setAttribute('d',path);
}else{
var dom = E.fn.initPath_VML(F);
var path = path.replace('Z','X');
dom.path = path;
}
this.F = F;
this.dom = dom;
dom = this.initAttr(dom);
F.r.appendChild(dom);
return this;
}
/*
* E.prototype.initRect 初始化 rect对象
* points:{x,y,width,height}
*/
E.fn.initRect = function(F,x,y,width,height,corner){
var IScorner = false;
if(corner != 0 && typeof corner ==='number'){
var shortL = width > height ? height : width;
if(corner >= shortL>>1){
corner = shortL>>1;
}
IScorner = true;
}
if(F._ISSVG){
var corner = corner || 0;
var dom = document.createElementNS(F._NS,"rect");
dom.setAttribute('x',x);
dom.setAttribute('y',y);
dom.setAttribute('width',width);
dom.setAttribute('height',height);
if (IScorner) {
dom.setAttribute('rx',corner);
dom.setAttribute('ry',corner);
}
}else{
var dom = this.initPath_VML(F);
var path ='';
if(x && y && typeof x === 'number' && typeof y === 'number' && width && height && typeof width === 'number' && typeof height === 'number'){
var xl = x + width,yl = y + height;
if(IScorner){
var x1 = x+corner,y1 = y+corner,x4 = xl-corner,y4 = yl-corner;
path += 'M'+x1+' '+y+'L'+x4+' '+y+'qx'+xl+' '+y1+'L'+xl+' '+y4+'qy'+x4+' '+yl+'L'+x1+' '+yl+'qx'+x+' '+y4+'L'+x+' '+y1+'qy'+x1+' '+y+' z';
}else{
path += 'M'+x+' '+y+' ';
path += 'L'+ xl +' '+ y;
path += 'L'+ xl +' '+ yl;
path += 'L'+ x +' '+ yl +'xe';
}
}
dom.path = path;
}
this.F = F;
this.dom = dom;
dom = this.initAttr(dom);
F.r.appendChild(dom);
return this;
}
/*
* E.prototype.initRect 初始化 rect对象
* points:{x,y,width,height}
*/
E.fn.initEllipse = function(F,cx,cy,rx,ry){
if(F._ISSVG){
var dom = document.createElementNS(F._NS,"ellipse");
dom.setAttribute('cx',cx);
dom.setAttribute('cy',cy);
dom.setAttribute('rx',rx);
dom.setAttribute('ry',ry);
}else{
var dom = this.initPath_VML(F);
var path ='ae'+cx+' '+cy+' '+rx+' '+ry+' 0 23592960X';
dom.path = path;
}
this.F = F;
this.dom = dom;
dom = this.initAttr(dom);
F.r.appendChild(dom);
return this;
}
E.fn.initLine.prototype = E.fn;
E.fn.initPath.prototype = E.fn;
E.fn.initRect.prototype = E.fn;
E.fn.initEllipse.prototype = E.fn;
我这还有一
个调用的例子,可以通过下面的方式测试一下:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script src="lizhi.js" type="text/javascript"></script>
<script type="text/javascript">
window.onload = function(){
var paper = F("dv");
var line = paper.Line(5,50,100,50);
var path = paper.Path('M5 100 C5 150 200 200 100 250');
var rect = paper.Rect(300,300,100,100,20);
var ellipse = paper.Ellipse(300,100,20,50);
var path1 = paper.Path('M100 100L200 100Z');
}
</script>
</head>
<body>
<div id="dv" style="width:800px;height:500px; background:#ceafec"></div>
</body>
</html>
下面是在我电脑上跑的样子:
新的博客迁移至: l-zhi.com
虽然代码不多300来行,但是我也花了不少时间研究svg 和vml。
转载请写明出处,你的支持才是我分享的动力。
如果时间精力允许的话我可能会加入img和text,以及样式的更改方法,当然还得希望公司别再老加班了
。