今天我来讲一下关于使用SVG画图的一些基本知识,并完成一个简单的DEMO演示。关于SVG的基础知识,这里暂时不做阐述,因为网上关于svg的知识不算少,这里推荐大家去w3c school看就可以,另外慕课网也有很多svg的视频,目前我对svg的了解其实也只是皮毛,这里通过一个简单的DEMO演示讲述SVG能帮我们做些什么,以及看一下关于svg的基本用法等。
svg主要通过两种方式呈现在浏览器里,一种是内嵌在html中,一种是独立的svg文件,两者都可以用浏览器打开看,这里我们演示第一种,将svg嵌套在html中,因为我们还要利用javascript写一些脚本来控制svg。
我们通过看截图看一下咱们这个DEMO要演示哪些东西(参考了慕课网SVG教程)
其实今天我讲的这些东西多半是从慕课网那里得到的,所以大家如果想仔细的看还是建议去慕课网,我这里只是简单的总结了一下。在这个页面中,我们将左侧的工具来放在了一个DIV里,右面就是我们的SVG的画布。我们通过左侧的工具栏可以创建矩形,圆形等图形,然后通过图形变化和移动改变图形的一些样式。其中几个比较实用的像旋转,缩放等。另外我还讲了一些弧度的做法,当然可能不太好。
第一步,我们需要搞个工程,建议用webstorm工具,引入jquery,因为之后我们可能需要用到一些操作dom的方法,用jquery比较方便。接下来我们开始进入正题,我们需要创建SVG画图,代码如下:
var svg = createSVG(); gobVars.svg = svg; initG(); <!--创建svg画布函数--> function createSVG(){ var svg= document.createElementNS(namespace,'svg'); svg.setAttribute('width','100%'); svg.setAttribute('height','100%'); $('#canvas').append(svg); svg.setAttribute("onmouseup","selectAreaRemove(evt)"); return svg; }
通过createSVG方法来创建我们的svg画布,通过createElementNS方法。创建出来的SVG其实就是一个DMO节点,给他设置相关属性,并嵌套在canvas这个DIV中。另外我们给这个SVG设置了一个onmouseup的事件,当鼠标抬起时触发selectAreaRemove方法,这个方法的作用我们一会再说。
在svg中,我们基本都会使用这个方法来创建SVG以及他的图形。
创建完成后,当我们点击矩形、圆形、椭圆、直线的时候,能够帮助我们创建对应的图形,这些图形是我们在做svg画图时经常用到的,所以这里我们案例体现了一下,我们看下代码:
//创建图形 function createShape(name){ /** * 根据按钮传递的名字创建对应的图形元素 设置相关属性值,其中: * transform 关于图形旋转 位移 缩放等图形变化的参数 * class 样式 这里我们只是用来标记没有实际样式 * @type {HTMLElement} */ var shape = document.createElementNS(namespace,name); shape.setAttributeNS(null,"transform", transFormDefault); shape.setAttributeNS(null,"class","shape_class"); /** * 调用select方法,设置它的基本参数 包括坐标等 * 然后将本图形复制给selected对象 意味着当前图形被选中 */ select(shape); /** * 最后将这个图形append到SVG父元素下 */ svg.appendChild(shape); }
<pre name="code" class="javascript"><!--图形被选中的行为--> function select(shape){ var attrs = shapeDefaultInfo[shape.tagName]; var attr,name,value; shapeForm.html(""); for(var key in attrs){ if(attrs.hasOwnProperty(key)){ name = key; value = shape.getAttribute(name) || attrs[name]; shape.setAttribute(name,value); createShapeHandler(shape,name,value); } } for(var name in defaultAttrs){ if(defaultAttrs.hasOwnProperty(name)){ value = shape.getAttribute(name) || defaultAttrs[name]; shape.setAttribute(name,value); } } selected = shape; updateShapeHandle(); }
在select方法中,我们循环了两个集合,集合如下:
var transFormDefault = "translate(0,0) rotate(0) scale(1)"; var shapeDefaultInfo = { rect:{x:10,y:10,width:200,height:100,rx:0,ry:0}, circle:{cx:200,cy:200,r:50}, ellipse:{cx:200,cy:200,rx:80,ry:30}, line:{x1:10,y1:10,x2:100,y2:100} } var defaultAttrs={ fill:'#ffffff', stroke:'#000000' }
如此,这样我们的图形就能显示在SVG里了,通过浏览器我们看一下源代码,当我们添加一个矩形到SVG中时,源代码是这样的:
我们发现svg中出现了一个rect的节点,结点中有transform属性(位移,旋转,大小) class属性 x代表坐标x y代表坐标y width代码长度 height代表宽度 rx ry 属性可使矩形产生圆角。其他的图形就不截图了。
这样我们第一个功能完成,现在我们要做就是通过滑动左侧的旋转,和缩放来实现图形的旋转和缩放功能。首先我们看一下工具栏怎么定义的:
<p> <label style="display: inline-block">x轴平移</label> <input id="translateX" type="range" min="-400" max="400" value="0"/> <label style="display: inline-block">y轴平移</label> <input id="translateY" type="range" min="-400" max="400" value="0"/> <label style="display: inline-block">旋转</label> <input id="rotate" type="range" min="-180" max="180" value="0"/> <label style="display: inline-block">缩放</label> <input id="scale" type="range" min="-1" max="2" step="0.1" value="0"/> </p>
工具栏就是html提供的input 只不过它的type是range 可以设置最大最小值默认值,我们通过监听这个组件来获取要旋转或者缩放的数值,然后通过一些方法来改变图形的变化,我们监控tranForm,一旦他发生了变化,我们则调用:
transForm.change(function(e){ if(e.target.tagName.toLowerCase() == 'input'){ if(selected){ var t ={}; t.tx = translateX.value; t.ty = translateY.value; t.rotate = rotate.value; t.scale = scale.value; selected.setAttribute('fill',fill.value); selected.setAttribute('stroke',stroke.value); selected.setAttribute('transform',encodeTransform(t)); } } })
其中关于旋转,缩放,位移的核心操作是:
selected.setAttribute('transform',encodeTransform(t));
我们通过encodeTransform方法获取当前的变化的值,进行了一些包装,这个包装就是将参数进行格式化(封装成svg能读懂的格式,具体代码如下):
function encodeTransform(t){ var s_tr = 'translate('+t.tx+','+t.ty+')'; var s_rotate = 'rotate('+t.rotate+')'; var s_scale = 'scale('+t.scale+')'; return [s_tr,s_rotate,s_scale].join(' '); }
其中,如果我们想让图形发生位移,则修改他的translate属性的值,如果我们想让它发生旋转就修改rotate的值,如果我们想让他发生缩放就修改scale的值。当然这些比较容易实现的。
这样我们的工具栏的功能也介绍完了,最后说一下弧度。实现弧度的方式有很多,我这里讲的是我实现的一种比较简单的方式,首先初始化5个圆形在SVG中,这5个圆被包含在一个组(g)里。我通过修改g的transform就可以操作g组下的所有图形。
function initG(){ var g1 = document.createElementNS(namespace,"g"); g1.setAttributeNS(null,"transform", transFormGDefault); g1.setAttributeNS(null,"class","circle_g"); var rrr = 25; var cx = 0; var cy = 0; var seatArray = []; //通过遍历 创建5个圆形 依次排列 并放入一个临时集合中 for(var i=0;i<5;i++){ var c = document.createElementNS(namespace,"circle"); c.setAttributeNS(null,"cx",cx); c.setAttributeNS(null,"cy",cy); c.setAttributeNS(null,"r",10); c.setAttributeNS(null,"class","circle_class"); c.setAttributeNS(null,"fill","#ffffff"); c.setAttributeNS(null,"stroke","#000000"); cx = cx + rrr; seatArray.push(c); } seatArray.sort(function(obj1,obj2){ return obj1.cx.baseVal.value - obj2.cx.baseVal.value; }); //定义一个弧度 var hudu = parseInt(10); //获取这一排的中间点X (5个座位 中间第3个座位) var rx = (seatArray[0].cx.baseVal.value + (seatArray[4].cx.baseVal.value - seatArray[0].cx.baseVal.value))/2;//圆心坐标 //Y坐标+要发生的弧度值 如果弧度为正数就是往下弧 反之向上弧 var ry = seatArray[3].cy.baseVal.value+hudu; //遍历5个座位 for (var j = 0; j < 5; j++) { //第1个和第5个不做操作 if(j == 0 || j == 4){ g1.appendChild(seatArray[j]); continue; }else{ //中间个 修改它的y坐标 两侧的也修改 但y坐标少一点 这里就是随便写了下 if(j < 2){ seatArray[j].setAttributeNS(null,"cy",(2-j) * hudu); }else if(j > 2){ seatArray[j].setAttributeNS(null,"cy",(j-2) * hudu); }else{ seatArray[j].setAttributeNS(null,"cy",j * hudu); } g1.appendChild(seatArray[j]); } } svg.appendChild(g1); }
产生的效果如下:
ok 这样就都讲完了 哎 讲的不太好 大家凑合看 之后再慢慢补充吧!!!
补充 :配合鼠标完成鼠标拖拽移动功能,代码如下:
/** * 鼠标按下事件 */ $(svg).mousedown(function (evt) { var target = evt.target; var className = target.getAttribute("class"); console.log("className:"+className); if(className == "circle_class"){ target= target.parentNode; className = "circle_g" } if(className == "shape_class" || className == "circle_g"){ gobVars.currentX= (evt.clientX); gobVars.currentY= (evt.clientY); gobVars.selectedObject = target; svg.setAttribute("onmousemove", "moveElement(evt)"); } }) /** * * @param evt */ function moveElement(evt,target) { var x = (evt.clientX - gobVars.currentX); var y = (evt.clientY - gobVars.currentY); var transformStr = gobVars.selectedObject.getAttribute("transform"); var transobj = decodeTransform(transformStr); transobj.tx += x; transobj.ty += y; gobVars.selectedObject.setAttribute("transform", encodeTransform(transobj)); gobVars.currentX = evt.clientX; gobVars.currentY = evt.clientY; } /** * 鼠标放下 * @param evt */ function selectAreaRemove(evt){ svg.removeAttribute("onmousemove"); }