• 学习RaphaelJS矢量图形包--Learning Raphael JS Vector Graphics中文翻译(一)


          (原文地址:http://www.cnblogs.com/idealer3d/p/LearningRaphaelJSVectorGraphics.html

          前面3篇博文里面,我们讲解了一本叫做《Instant RaphaelJS Starter》的书,那本书里我们将RaphaelJS里面的基本内容都进行了比较详细的讲解。但是,坦白的说,那本书通俗易懂却太过浅显。现在我们下一本叫做《Learning Raphael JS Vector Graphics》的书,算是上一本的进阶。当然,它里面大部分篇幅也是基本内容。因为一本书不能去讲一个写复杂的业务问题,你所要做的也是学会基本内容然后自己去活用。我这里翻译此书的目的,第一是想加深对于RaphaelJS的理解,第二是本来也是要读这本书的,就顺带翻译了,或许还能给英语不拿手的同志们有点帮助,第三就是寻找一些突破的契机去解决我现在碰到的问题。好了,废话少说。新的一本书,大家可以去网上搜索一下,应该可以找到下载。

          和上本书一样,本书前面的几页是一些序言、版权声明等东西,这里我也略过不讲了。我们从目录页开始讲。如果你认真学习过前面3篇翻译上本书博文的内容,这本书的目录写出来的时候,你就应该能明白每个章节讲的是什么内容。

                             目录

    序言 --------------------------------------------------- 1

    第一章: Web图形---------------------------------------- 5

         在Web上绘制矢量图---------------------------------- 6

               矢量图形绘制包-----------------------------------7

         详述SVG-------------------------------------------- 8

               使用RaphaelJS包而不是直接使用SVG-------------- 9

         RaphaelJS的应用--------------------------------------9

         下载RaphaelJS-------------------------------------- 10

         创建RaphaelJS的Js项目------------------------------ 11

               项目的构建与优化 --------------------------------11

         小结-------------------------------------------------11

    第二章: RaphaelJS基本图形绘制 --------------------------13

          绘制环境------------------------------------------- 13

               画布坐标系-------------------------------------- 15

          绘制基本图形---------------------------------------- 16

          导入图片--------------------------------------------18

          Raphael元素属性------------------------------------ 18

               简单(基础)填充-------------------------------- 19

               图片填充---------------------------------------- 19

               应用笔画---------------------------------------- 20

               其它属性---------------------------------------- 21

                     超链接--------------------------------------21

                     透明度--------------------------------------22

                     矩形裁剪------------------------------------22

               渐变应用----------------------------------------23

                    线性渐变------------------------------------ 23

                    径向渐变------------------------------------ 25

               元素分组---------------------------------------- 27

         使用文本-------------------------------------------- 28

               引用常用字体------------------------------------ 29

         小结-------------------------------------------------30

    第三章: 绘制Path(路径)---------------------------- ----31

          Path绘制概念--------------------------------------- 32

          Path绘制命令--------------------------------------- 33

                "移动到"命令------------------------------------34

                "连接到"命令----------------------------------- 35

                "关闭路径"命令--------------------------------- 37

          绘制曲线------------------------------------------- 38

                二次贝塞尔曲线--------------------------------- 38

                三次贝塞尔曲线--------------------------------- 41

                绘制弧线--------------------------------------- 43

          Path中比较实用的方法------------------------------- 46

                Element.getTotalLength() ---------------------46

                Element.getPointAtLength(length) -------------47

                Element.getSubpath(from, to)----------------- 48

               Catmull-Rom弧线------------------------------- 49

           小结----------------------------------------------- 50

    第四章: 变形转换和事件处理------------------------------ 51

          基本图形变换和事件处理------------------------------52

                基本图形变换------------------------------------52

                      平移----------------------------------------53

                      旋转--------------------------------------- 53

                      缩放----------------------------------------55

                基本事件响应----------------------------------- 55

                      注册基本事件响应 ---------------------------55

                      注销基本事件响应----------------------------57

           使用矩阵------------------------------------------- 58

                 转换矩阵--------------------------------------- 58

                 使用转换矩阵----------------------------------- 58

           拖放功能------------------------------------------- 60

                 Element.drag() 方法 ---------------------------60

                 onstart事件----------------------------------- 60

                 onend事件------------------------------------ 60

                 onmove事件---------------------------------- 60

                       拖动的例子-------------------------------- 61

            丢下元素------------------------------------------ 62

                  边界框覆盖 -----------------------------------62

                  边界框中的边界框 -----------------------------63

            小结--------------------------------------------- 64

    第五章: 向量动画--------------------------------------- 65

               基本动画 ---------------------------------------66

          变换路径------------------------------------------ 67

          缓动类型 ------------------------------------------70

                内建的缓动算法规则 ----------------------------70

                使用三次贝塞尔公式的缓动 ----------------------71

           动画转换 ------------------------------------------72

           动画常用属性-------------------------------------- 73

                 常用属性 --------------------------------------73

                 随着一个长路径动画-----------------------------76

                      动画的暂停和重新开始-----------------------78

          小结------------------------------------------------79

    第六章: 使用已经存在的SVG文件--------------------------81

          Inkscape ------------------------------------------82

               下载Inkscape-----------------------------------82

               开始使用Inkscape-------------------------------82

           检查path------------------------------------------87

                 Inkscape的XML编辑器-------------------------87

                 从存在的SVG图片中提取path-------------------89

           SVG转换到raphael对象的工具-----------------------90

                 Ready Set Raphael ---------------------------90

                 其它转换工具 ----------------------------------91

           等值域图 ------------------------------------------92

                 创建等值域图 ----------------------------------92

                 开源SVG文件---------------------------------- 96

           小结-----------------------------------------------96

    第七章: 创建一个可视化社交媒体--------------------------97

          社交媒体应用--------------------------------------- 97

               开始--------------------------------------------98

               使用JQeury-------------------------------------99

               系统可用数据------------------------------------99

               绘制人型图表-----------------------------------100

               图表点击响应-----------------------------------101

               绘制一把钥匙-----------------------------------102

          随时间发布消息-------------------------------------103

                开始-------------------------------------------104

                推送的数据-------------------------------------104

    (第七章这里有些专业术语,我在没读到这里之前,暂时不能获得准确的意思,抱歉,翻译到这里的时候讲把这里补充一下。)

         我们从正文第一章开始讲。

    Web图形

         在当前浏览器的领域,图形的绘制是非常重要的。从图表到简单图片,从数学到视觉艺术,哪里都需要图形的绘制。所以浏览器对于这块功能的需求大增。所以以此衍生了很多相关技术。不止VML和SVG,HTML5 Canvas和WebGL.每个都有它们适用的领域,VML和SVG处理2D矢量图,HTML5Canvas的位图绘制以及WebGL的3D绘制渲染。

         本书讲述一个开源和轻量级的JS库,Raphael,它使用SVG和VML在浏览器中绘制矢量图形。 它提供了很多非常方便的用户绘制和变换矢量图的方法,在支持直接操作DOM的同时还支持导入位图以及文本的绘制。它就是SVG和VML的优秀合体。一位内它已经将底层封装完善,我们在使用时不需要去考虑SVG和VML的方面问题,只要集中精力搞好我们的Raphael就可以了。

         VML是微软设计并且在1998年提交给W3C,基于XML技术的在IE版本5+后绘制矢量图形。SVG使用W3C组织在2001自己推出的适量绘制图形技术。也是基于XML的文件组织,但是它适用于所有主流浏览器。IE在9以后的版本也开始支持SVG。

    矢量图形绘制包

    现在有很多比较成熟可用的矢量图形绘制JS包。除了RaphaelJS,还有两个非常流行的矢量图形绘制工具包,Paper.js和D3.js,每个都有它们各种优缺点。下面有一个简单的比较:

    包名称          IE6,7,8支持            开箱即用(个人理解是开源)   低层次包(意味着你可以操作的空间更大)

    Raphael           Yes                        Yes                                   Yes

    D3.js               No                         No                                     No

    Paper.js           No                         No                                     No

    Raphael是为一个支持VML的矢量图形绘制包,其余的包都支持SVG,但是由于是高级包,在使用虽然可能简单一些,但是你操作性大减。当我们可以直接对底层内容进行操作时,你会发现我们可以做的事情要远比其它的多,当然代价就是学习周期长,难度大(实话说,如果你只是做比较普通的功能,Raphael还是非常简单的,但是对于复杂的操作有些引擎操作需要自己去实现,还是有难度的)。

     SVG说明

    SVG是当今Web应用最广泛的矢量图形绘制技术。所有主流浏览器都提供了全方位的支持,甚至最新的手机浏览器都已经加入对SVG的支持。

    SVG是基于XML的,就是标签对格式的。比如我们要画从坐标(50,50)的点画一个黑色实心线段到点(10,10)可以用下面的代码:

    <path d="M50 50 L10 10" stroke-width="1" stroke="#000" />

    除了路径path之外,SVG还支持图形绘制、文本、填充、渐变、动画以及用户绑定的事件响应。你可以在http://raphaeljsvectorgraphics.com/the-graphical-web/raw-svg/网站上查看一些SVG的例子。

    Raphael基本XML语言,所以这本书看完后,你会非常熟悉一些SVG的语法,特别是和path有关的。

    使用Raphael而不要直接使用SVG

    撇开浏览器支持不说,有一个非常好的原因让我们使用Raphael而不是直接写原生态的SVG,因为它让矢量绘制简单更多。举个例子,我门要画一个矩形并且让它的宽度从50px动画变成100px。原生态的SVG代码:

    <rect x="10" y="10" width="50" height="30">

          <animate attributeType="XML"

                   attributeName="width"

                   to="100"

                   fill="freeze"

                   dur="1s" />

    </rect>

    我们在(10,10)坐标位置开始画一个宽50px,高30px的矩形也就是<rect>标签,然后需要在内部、嵌入一个<animate>标签,然后在animate标签里面,并且进行说明哪里要变、怎么变。还要有fill="freeze"来保持变换的形状,否则会被重置。这样看上去代码冗长而且不易操作。但是我们使用Raphael的话,只需要:

    var rect = paper.rect(10, 10, 50, 30);

    rect.animate({

          100

          }, 1000);

    我们的矩形创建和动画变动都更加简洁,而且如果你要变动的内容更多,那就对比更明显。另外Raphael可以很好与其它包整合,比如jQeury,这归功于Raphael声明一个全局的变量Raphael。

    Raphael的应用

    Raphael现在已经广泛应用在从地图制图Town Hall @ the White House event(http://askobama.twitter.com/)到网络小游戏比如Ebocs(http://www.dejapong.com/ebocs/).

    Raphael特别适用于制图方面,因为RaphaelJS库为我们提供了直接操作DOM元素的能力并且我们还可以随意缩放而不担心图片的失真。你可以在http://raphaeljs.com/australia.html 找到一些很好的例子。

    (接下来讲的内容是如何下载RaphaelJS并且搭建起来环境,我们在第一篇博文里面已经有说明大家可以去看那个,这里不再赘述。地址:http://www.cnblogs.com/idealer3d/p/Instant_RaphaelJS_Starter.html)。还有大家搭建项目的时候要规划好,特别是文件夹以及路径要管理规范。

    第二章 使用Raphael绘制基本图形

          Raphael提供了图形绘制的基本元素:形状、图片和文本。图形有预定义的矩形、圆形、椭圆以及组合图形等。图形和文本是可以填充的。变框的填充只能是单色但是可以修改。填充可以是线性也可以是渐变的。

          绘制环境

          要绘制图形,我们需要一个绘制的环境。我们需要创建一个空间供我们去绘制和储存。就像艺术家一样,我们需要一个画布。浏览器的视口,就是我们的画布。SVG标准把视口认为是绘制区域自己,我们一般认为浏览器区域就是视口了。我们利用Raphael去创建画布的代码如下:

         var paper= Raphael(50,100,500,300);

    它的效果如下:

     如上图所示,我们在视口的区域,离左上角x轴(横轴)50px,y轴(竖轴)100px的位置开始创建一个宽500,高300的矩形框,这就是我们的画布。也就是说,paper对象,就是我们的画布。我们更推荐,我们利用已经存在的dom元素来建立画布而不是直接利用视口。在这种情况下,我们的画布的位置就是相对DOM元素的位置来讲的:

    <div id="my-canvas"></div>

    我们可以根据如下代码来建立画布:

    var paper=Raphael("my-canvas",500,300);

    也就是我们根据一个DOM的id去建立画布。当然直接用Id也可以,获得DOM对象也可以:

    Raphael(document.getElementById("my-canvas"),500,300);

    画布坐标系

          我们可以根据下面的插图来理解画布的坐标系:

    看图我们可以发现,坐标系原点在画布的左上角。(0,0)开始,x轴为从左到右,y轴为从上到下。另外如果出现负值,则位置如下:

    这里是比较好理解的,但是需要注意的是,在负值的区域是不可见的:

    Hidden:隐藏;Visible:可见的。

    坐标系弄清楚以后,我们就可以开始绘制我们的图形了。

    绘制基本图形

          Raphael提供了矩形、圆形、椭圆的作为基本图形的预定义绘制方法。我们创建的画布对象可以调用这些方法。Rect矩形的绘制语法:

    Paper.rect(x,y,width,height,[r]);

    我们可以看到paper.rect共有5个参数,其中前4个为必须参数,第五个为可选参数。前两个,x,y 其实参照我们创建画布就可以理解,这里的x,y是在画布坐标系的(x,y)位置开始绘制,绘制一个宽度为第三个参数width、高度为第四个参数height的矩形。如果第5个参数设置并且大于0,则为圆角矩形。[r]以为圆角的半径。代码示例将在下面贴出。我们先讲解圆形和椭圆。圆形的绘制语法:

    Paper.circle(x,y,r);

    在(x,y)位置绘制一个半径为r的的圆。椭圆的语法:

    Paper.ellipse(x,y,x-radius,y-radius);

    在(x,y)位置绘制一个横向半径为x-radius,竖向半径y-radius的椭圆。代码如下:

    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Raphael Test</title>
        </head>
        <body>
            <div id="my-canvas" style="padding:0px;margin:0px;border:solid;">
            </div>
            <!--some html doms-->
            <!--some scripts-->
            <script type="text/javascript" src="../js/lib/raphael.js">
            </script>
            <script type="text/javascript">
                //在my-canvas节点上面创建画布
                var paper = Raphael("my-canvas", 500, 300);
                //在(20,20)位置创建一个宽100,高60的直角矩形
                var rect = paper.rect(20, 20, 100, 60);
                //在(140,20)位置创建一个宽100,高60,圆角半径10的圆角矩形
                var rectR = paper.rect(160, 20, 100, 60, 10);
                //在(50,150)位置绘制一个半径为40的圆形
                var cir = paper.circle(50, 150, 40);
                //在(150,150)绘制一个横向半径50,竖向半径35的椭圆
                var ellipse = paper.ellipse(150, 150, 50, 35);
                //位置提示
                var tip = paper.text(5, 20, "(10,20)");
                var tipR = paper.text(145, 20, "(160,20)");
                var tipC = paper.text(50, 150, "(100,50)");
                var tipE = paper.text(150, 150, "(100,140)");
            </script>
        </body>
    </html>

    效果图如下:

    如上图,我们在代码中有每个图形的详细解释,这里不多解释,大家可以阅读代码中的注释。这里再引用原书的椭圆图形加深理解:

     导入图片

           Raphael允许我们导入位图至画布中。语法如下:

    paper.image("a.png",50,50,200,200);

    意味着我们在(50,50)的位置导入一个图片,图片被缩放到长200,宽200.图片的路径和名字为:"a.png"。我们在上面的那段代码中加入:

    //导入图片
    var agirl=paper.image("../images/mm.jpg",300,100,200,300);

     效果如下:

    接下来我们继续介绍每个我们创建的元素自带的属性。

    元素属性

          我们绘制的图形都可以有填充、边框属性以及其它的很多属性。我们创建图形的时候,每个方法返回一个图形对象,而这些对象就可以去赋予我们想要的属性。这些对象都有一个attr()方法,里面参数为键值对(json),键为元素属性名称,值为属性取值。

    填充

         我们首先介绍填充属性。填充可以是基本填充或者图形填充。基本填充我们使用颜色去填充一个形状,颜色的格式可以是#rrggbb、简写#rgb、rgb(r,g,b)甚至是颜色的英文单词red、green等。我们在前面那段代码中添加如下代码测试:

      rect.attr({
         fill: "#000"
       });
      rectR.attr({
          fill:"rgb(0,0,0)"
        });
      cir.attr({
          fill: "green"
         });
      ellipse.attr({
          fill: "url(../images/mm.jpg)"
        });

     效果图如下:

    不过我们使用位图填充椭圆的时候,由于椭圆太小我们这里只有原位图的右上角被填充到了椭圆中。这里大家理解就好啦。

    处理笔画(边框)

          元素的笔画有很多属性,最常用的是颜色和宽度。属性的键名就是"stroke","stroke-width"。因此,我们把刚才代码中添加几行新的代码:

    var newcir = paper.circle(50, 250, 40);
                newcir.attr({
                    fill: "green",
                    stroke: "red",
                    'stroke-width': "10"
                });

    我们可以通过比叫两个圆的不同来看到stroke笔画设置的不同。这里需要知道的是,我们代码里面的笔画宽度是10,其实这个10有一半也就是5是在图形内部,而剩余的则是在图形的外面。也就是在你设置的笔画宽度的中间是图形的真是大小(准确的说,是你期望的图形大小)。其实,即便我们不设置笔画属性,我们所绘制的所有图形都有自带的笔画属性,他们的宽度是1px。如果你确实不想设置笔画属性,那么你需要显式地设置stroke-none。当然还有其它一些stroke属性这里没有提及,大家如果想了解可以到RaphaelJS的官方网站去查阅资料。

    其它属性

          herf

          元素上面添加一个链接,允许这个dom元素扮演一个超链接的角色。当点击这个图形时,它将打开一个新的链接。(为了演示方便,我们另起一份代码,刚才的代码内容已经比较繁杂)。代码:

     var paper = Raphael("my-canvas", 500, 400);
                var rect = paper.rect(30, 30, 140, 140);
                rect.attr({
                    fill: "green",
                    href: "http://www.baidu.com"
                });

    原书上讲,这里将创建一个表现为超链接的矩形。但是我实际测试中点击并没有作用,这里我还需要找找问题。我们暂时记下来,继续往下走。

          透明度

          元素透明度键名opacity,取值范围为0(完全不透明)到1(完全透明),也可以分别设置stroke-opacity和fill-opacity。我们前面说过,stroke是以中心来还,一半在外,一半在内。这里就会出现副作用,因为可以分别设置透明度而导致分开设置透明度会有一些限制。这里我们不再贴代码,原书的例子很好,我就直接贴出来了:

     矩形切割

           Raphael支持通过clip-rect属性来进行元素的矩形切割,它允许我们将图形切割出一部分下来。我们可以按照下面的代码来进行图形区域切割:

     var paper = Raphael("my-canvas", 500, 400);
                var circle = paper.circle(100, 100, 80);
                //原书是在attr里面直接加入了'clip-rect'属性,将圆的1/4切割下来,我们分开两步加入动画,以便理解。这里最终达到的效果与原书一致
                circle.attr({
                    fill: "pink",
                    'stroke-width': 0,
                });
                circle.animate({
                    'clip-rect': '20,20,80,80'
                }, 2000,'easeIn');

    大家将这段代码替换上面那大段代码的js部分就可以看到效果了。效果如下:

    2秒后:

    clip-rect属性的4个参数与矩形创建是一致的,x,y坐标开始宽、高定制的矩形。原书辅助解释的图:

    虚线圆就是我们创建的circle对象,粉红色的部分就是设置该属性后剩余的部分。

    渐变

         Raphael支持线性和梯度渐变去填充图形,要达到这个效果,而不是直接用一个颜色的字符串去设置fill属性。我们需要指定了下面这种字符串的格式去做到线性渐变:

                <angle>-<color>[-<color>[:<offset>]]*-<color>

    下面的语法就是达到径向渐变的效果:

          r[(<fx>,<fy>)]<color>[-<color>[:<offset>]]*-<color>

    好吧,我承认我也没看懂。我们来看例子帮助我这智五渣理解一下。

    线性渐变

          最基本的线性渐变的格式:

                <angle>-<color1>-<color2>

    比如:

           var rect=paper.rect(20,20,160,160);

           rect.attr({

                   'stroke-width':0,

                   fill:'0-#f00-#000'

                 })

    我们去实验一下:

                var paper = Raphael("my-canvas", 500, 400);
                var rect = paper.rect(50, 50, 100, 100);
                var rect1 = paper.rect(200, 50, 100, 100);
                var rect2 = paper.rect(350, 50, 100, 100);
                rect.attr({
                    'stroke-width': 0,
                    fill: '0-#f00-#000'
                });
                rect1.attr({
                    'stroke-width': 0,
                    fill: '90-#f00-#000'
                });
                rect2.attr({
                    'stroke-width': 0,
                    fill: '45-#f00-#000'
                })

     还是把这段复制到js部分就可以了,我们的运行效果图:

    3个矩形,我们分别按照0度角、90度角、45度角实现从红色到黑色的渐变。嘿嘿,似乎上面那段奇怪的代码也不怎么难嘛。

         注意,我们的角度计算是从x轴正方向沿逆时针方向来定义角度(--这句话其实就是说角度和我们脑子里的原始想法一致,不要去纠结其它)。

         线性渐变可以有任意个数的颜色和这些颜色组成线性渐变的点,定义为offsets 。也就是有了下面的语法结构:

               [-<color>[:<offset>]]*

    在这里,任何个数的-color:offset组合可以用来创建。比如,我们使用下面的string来看看:

          fill:"0-#00a9e0-#323490:20-#ea1688:40-#eb2e2e:60-#fde92d:80-#009e54"

    我们用上面那行字符串可以建立一个彩虹样式的矩形,每个颜色相比前一个颜色多占据20%。下面的字符串可以达到相同效果:

          "0-#00a9e0-#323490-#ea1688-#eb2e2e-#fde92d-#009e54"

    这里只要把字符串贴到上面我们js代码的fill属性就行了,就不再截图举例了。

    径向渐变

          径向渐变与线性渐变相似,但是径向渐变绘制的时候是放射式的,从一个点开始(默认图形的中心点),最基本的径向渐变的语法:

          r<color>-<color>

          比如,我们在代码里面加入:

        var paper = Raphael("my-canvas", 500, 400);
                var circle = paper.circle(150, 150, 100);
                circle.attr({
                    'stroke-width': 0,
                    fill: 'r#f00-000'
                })

    我们可以得到:

    我们得到一个从中心为红色渐变到边缘为黑色的圆形。根据我们上面线性渐变的描述,我们根据offsets属性去“分段”定义颜色渐变,我们试验一下径向渐变的offsets效果:

      circle.attr({
                    'stroke-width': 0,
                    fill: 'r#f00-000:80-#f00'
                })

    我们把上面的circle对象attr方法修改为上面的这句,效果如下:

     呶?看出来区别了吧。那么估计有童鞋要问了,我不想从中心点开始画啊,我想随意的点,记得前面语法出现的fx和fy吗,它们就是来做这个的。这里我就不详细举代码例子了,袁术的配图真是不错,一看就可以明白:

    我们发现我在r命令后面的括号里面添加好fx和fy的值,可以获得不同效果。fx和fy很容易能看出来取值范围为[0,1],其实就是中心点在图形的x和y最大值的比例位置。这里很容易理解,不多做解释了。

         最后,提一点,path对象是不能用径向渐变的。这是因为VML在这里有bug,所以这里的径向渐变只适用于基本图形。

  • 相关阅读:
    JSP课程设计:宿舍管理系统(附源码)
    【博客模板页】从此不再为写博客头疼 (ノ ̄▽ ̄)~(ノ ̄▽ ̄)~(ノ ̄▽ ̄)~
    个人自定义的快捷键
    碎知识点收藏栏 [逆序时间排版]
    JavaSE (46)
    《Java8实战》05
    Python04
    【BUG11】
    三、如何科学地做到:算法竞赛从入门到放弃/算法竞赛从了解入坑到快速放弃指南?
    二、如何科学地在面试时踩雷?
  • 原文地址:https://www.cnblogs.com/idealer3d/p/LearningRaphaelJSVectorGraphics.html
Copyright © 2020-2023  润新知