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");
        }
时间: 2024-11-09 00:47:12

SVG入门案例的相关文章

Hibernate介绍和入门案例

一身转战三千里,一剑曾当百万师 如果你在之前没有学过SSH三大框架,那么你之前肯定是通过JDBC来对数据库进行操作.现在,你完全可以把跟数据库交互的操作直接交给Hibernate. Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库表建立映射关系,是一个全自动的 orm框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDBC

一起学习Hibernate: Hibernate01 —— Hibernate的概述与入门案例

一 Hibernate的介绍 1 让我们从JDBC与替代它的框架Hibernate进行一下对比. 1.1 JDBC的缺点 1) 代码结构繁琐.每次书写sql语句操作数据库都得需要很多步; 2) 是面向过程的编程,而非面向对象的: 3) 没有做到数据缓存.这会导致程序与数据库的交互的次数很多: 4) 因为事务是自动开启的,所以存在安全隐患. 1.2 JDBC的优点 1) 因为是底层的数据库操作,所以执行效率很高: 2) sql语句可以自己编写,可以进行优化从而选择效率最高的那些. 1.3 Hibe

PHPUnit 入门案例

了解PHPUnit 本案例是关于创建三角形的一个单元测试入门案例,在netbeans环境中完成,关于在此环境中搭建phpunit这里不再描述,可以参考以下资料完成搭建工作: http://www.cnblogs.com/x3d/p/phpunit-in-netbeans8.html https://phpunit.de/manual/current/zh_cn/installation.html https://github.com/sebastianbergmann/phpunit-skele

_00017 Kafka的体系结构介绍以及Kafka入门案例(初级案例+Java API的使用)

博文作者:妳那伊抹微笑 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前,妳却感觉不到我的存在 技术方向:Flume+Kafka+Storm+Redis/Hbase+Hadoop+Hive+Mahout+Spark ... 云计算技术 转载声明:可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作! qq交流群:214293307  (期待与你一起学习,共同进步) # Kfaka的体系结构 # 学习前言 Kafka的整个学习过程就是自己看官网的文档,出

MyBatis学习(一)简介及入门案例

1.什么是MyBatis? MyBatis是一个支持普通SQL查询,存储过程,和高级映射的优秀持久层框架.MyBatis去掉了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解进行配置和原始映射,以将接口和Java的POJO映射成数据库中的记录. MyBatis作为持久层框架,主要思想是将程序中大量的SQL语句剥离出来,配置在配置文件中,以实现SQL的灵活配置.这样的好处是将SQL语句和程序代码分离,可以在不修改代码的前提下,直接在配置文件中修

Servlet简要介绍及入门案例。

什么是Servlet呢? Servlet 试运行在服务器端的一个小的java程序,接收和相应从客户端发送的请求. 那么Servlet的作用是什么呢? 处理客户端的请求,并且对请求作出相应. 下面是Servlet的简单入门案例: //编写一个类实现Servlet接口 public  class ServletTest1  implements   Servlet{ public  void  service(ServletRequest request , ServletResponse  res

Freemarker入门案例

Freemarker入门案例 首先需要到freemarker官方下载freemarker的jar包,导入到项目中,如:freemarker-2.3.19.jar 1.先建个freemarker的工具类,FreemarkerUtil.java package com.ljq.fm; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; impor

spring 入门案例

spring开发步骤: spring jar包介绍: 在3.0以下的版本,源码有spring中相关的所有包(包括spring核心包和依赖包) 在3.0以上版本,源码中只有spring的核心包 没有依赖包 依赖包需要自己下载 1)源码,jar包:spring-framwork-3.2.5.RELEASE commons-logging-1.1.3.jar           日志 spring-beans-3.2.5.RELEASE.jar       bean节点 spring-context-

【一】MyBatis入门案例

1. MyBatis的简介 MyBatis 是支持普通 SQL 查询,存储过程和高级映射的优秀持久层框架.MyBatis 消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索.MyBatis 使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的 POJOs(Plan Old Java Objects,普通的 Java 对象)映射成数据库中的记录. 2. 入门案例 (1). 新建一个 Java 工程,其目录结构如下: (2). 依次介绍目录结构下的文件 (a). MyB