SVG入门案例

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


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值