构建Canvas矢量图形渲染器(四)—— 各种矢量元素(线、面、五角星)

    这次随笔接着上次的内容继续,为我们的geometry类添加更多的矢量元素。

 (目录上线了,大家如果对这个系列了解不是很多请看目录!)

    其实,通过设计好的架构我们很容易通过geometry基类扩展新几何类型。

    本次随笔内容不是很多,先上demo。

 

1.增加各种几何对象。

1.几何类型:线(Line)

    线也是一继承自Geometry的类。简单的来说,线其实就是一点数组的集合。

//CLASS:几何对象线类。
function Line(points) {
    Geometry.apply(this, arguments);
    this.points = points;
}

Line.prototype = new Geometry();

Line.prototype.geoType = "Line";

    简单不?一个线的几何类型就这么4、5行代码就搞定了~

2.几何类型:面(LinerRing)

    面也可以称作是一条封闭的线,这么我们的面继承自线,并对线做了一些修改。

//CLASS:几何对象封闭线类
function LinerRing(points) {
    Line.apply(this, arguments);
    if(points) {
        this.points = points;
        var len = this.points.length;
        if(this.points[0].x != this.points[len-1].x || this.points[0].y != this.points[len-1].y) {
            this.points.push(this.points[0].clone());
        }
    }
}

LinerRing.prototype = new Line();

LinerRing.prototype.geoType = "LinerRing";

    是不是也很easy,判断线的首尾是否相连(最后一个点的x,y值是否和第一个点相等)。如果不相等则克隆第一个点,并添加到数组最后。

3.扩展几何类型:五角星(Star)

//CLASS:几何图形五角星
function Star(center, r) {
    //中心点
    this.center = center;
    //五角星的长半径
    this.r = r;
    var points = this.getPoints(center, r);
    LinerRing.call(this, points);
}

Star.prototype = new LinerRing();

Star.prototype.getPoints = function(center, r) {
    var point, points = [];
    var angle = 0;
    var degree = Math.PI / 180;
    for(var i = 0; i < 10; i++) {
        var radius = (i % 2 == 0)? r : r/2;
        point = new Point(center.x + Math.sin(angle * degree) * radius, center.y + Math.cos(angle * degree) * radius);    
        points.push(point);
        angle+=36;
    }
    return points;
}

Star.prototype.geoType = "LinerRing";

    五角星的具体画法这里就不详细阐述了,简单说下就是定义一个长半径r,其短半径这里设为r/2。和画圆的方法一样,交替使用长半径和短半径绘制其顶点,这样就画出来五角星的各个顶点了。其实五角星也就是LinerRing,所以这里他也继承自LinerRing。

    说完这几个基本类型,下面我们就再说说如何在渲染器中解析这几种几何类型。

2.渲染器端解析几何类型

    1.增加渲染的种类

//每一个矢量元素的绘制,这里我们在以后会添加更多的矢量图形。
Canvas.prototype.draw = function(geometry, style, id){
    if(geometry.geoType == "Point"){
        this.drawPoint(geometry, style, id);
    }
    if(geometry.geoType == "Circle") {
        this.drawCircle(geometry, style, id);
    }
    if(geometry.geoType == "Line") {
        this.drawLine(geometry, style, id);
    }
    if(geometry.geoType == "LinerRing") {
        this.drawLinerRing(geometry, style, id);
    }
    //{todo} 我们在这里判断各种矢量要素的绘制。        
}

    2.绘制线

Canvas.prototype.drawLine = function(geometry, style, id) {
    this.setCanvasStyle("stroke", style);
    this.rendererPath(geometry, {fill: false, stroke: true}, id);
    this.setCanvasStyle("reset");
}

    由于线只需要调用stroke方法,则我们这里只为其设置stroke的样式。

    rendererPath这个方法一会儿和绘制面一起说。

    3.绘制面

Canvas.prototype.drawLinerRing = function(geometry, style, id) {
    if(style.stroke) {
        this.setCanvasStyle("stroke", style);
        this.rendererPath(geometry, {fill: false, stroke: true}, id);
    }
    if(style.fill) {
        this.setCanvasStyle("fill", style);
        this.rendererPath(geometry, {fill: true, stroke: true}, id);
    }
    this.setCanvasStyle("reset");
}

    绘制面的时候我们会根据style的设定是否需要stroke、fill来调用不同的设置样式的方式,并调用rendererPath方法。

   3.rendererPath

Canvas.prototype.rendererPath = function(geometry, rendererType, id) {
    var points = geometry.points;
    var len = points.length;
    var context = this.context;
    context.beginPath();
    var start = this.getLocalXY(points[0]);
    var x = start.x;
    var y = start.y;
    if (!isNaN(x) && !isNaN(y)) {
        context.moveTo(x, y);
        for (var i=1; i<len; ++i) {
            var pt = this.getLocalXY(points[i]);
            context.lineTo(pt.x, pt.y);
        }
        if (rendererType.fill) {
            context.fill();
        } 
        if (rendererType.stroke) {
            context.stroke();
        } 
    }
}

    其实不管是线还是面,都是对一段path进行渲染的。无非区别在于一个不需要填充、一个需要。

    那么我们在调用这个函数的时候传入rendererType来区分是否需要填充。

    本节的内容就到这里。到目前为止一个矢量渲染器的大体结构就已经完成。后面要做的就是将绘制点、绘制面、绘制线段添加为鼠标点击支持的形式,通过扩展geometry可以得到更多的几何图形。

    尝试一下:大家下载源码后,可以扩展geometry类型为其添加一个矩形图形类。

    下次随笔预告:1.将添加图片的支持。

                        2.初步性能优化。

    本次随笔的所有源码+demo,请点击下载



posted @ 2012-04-22 10:28  豆豆狗  阅读(3134)  评论(1编辑  收藏  举报