今天我来讲一下关于使用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");
}