StartGate——我的2D Canvas绘图框架

要说为什么做这个东西,主要是懒得看英文去学其他成熟框架(后来才发现自己写也得看英文)和锻炼自己的js编程能力.

要说为什么把这个东西发在博文上,主要是最近开学了所以没时间继续写,干脆写一点算一点,有点成就感总比没有的好吧

然后要说的就是这个东西是个未完品,目前只能绘制 矩形,图片,自定义(就是让你自己写原始代码) ,还有个抽象的Container用来模拟图层.

接下来要做的就是增加绘制功能和事件响应,以及优化代码(重复内容好多好多).

下面的内容就是StartGate框架:

/*
 * StartGate
 * 上次更新:2011.09.17
 */

//事件常量
Event={
    //鼠标事件
    Mouse:{
        Click:"onclick",
        DoubleClick:"dblclick",
        Down:"mousedown",
        Up:"mouseup",
        Move:"mousemove",
        Out:"mouseout",
        Over:"mouseover",
        Wheel:"mousewheel"
    },

    //键盘事件
    Key:{
        Press:"onkeypress",
        Down:"onkeydown",
        Up:"onkeyup"
    }

};

//事件处理器
//THINK & TODO
/*
EventObjcet=function(canvas){
    return {

        "canvas":canvas,

        bindEvent:function(event){
            canvas.attachEvent(event,this.event);
        }

    };
};
*/

//渲染对象
RenderObject={

    //自定义绘图对象
    Custom:function(){
        return {

            //属性:
            visible:true,

            //设置是否可见
            setVisible:function(bool){
                this.visible=bool;
            },

            //获取visible
            getVisible:function(){
                return this.visible;
            },

            //默认渲染函数
        renderingFunction:function(ctx){},

            //设置渲染函数
            setRenderingFunction:function(func){
                this.renderingFunction=func;
        return 0;
            },

            //渲染动作
            rendering:function(ctx){
        if(this.visible){
            this.renderingFunction(ctx);
        }
        return 0;
            }

        }
    },

    //容器对象
    Container:function(){
        return {

            //属性:
        visible:true,

            //渲染对象列表
            objectList:[],

            //批量增加对象
            addList:function(){
                for(var i=0;i<arguments.length;i++){
                    this.objectList.push(arguments[i]);
                }
                return 0;
            },

            //列表尾部添加
            append:function(object){
                return this.objectList.push(object);
            },

            //列表尾部去除
            pop:function(){
                return this.objectList.pop();
            },

            //返回列表长度
            len:function(){
                return this.objectList.length;
            },

        //设置是否可见
        setVisible:function(bool){
        this.visible=bool;
        },

        //获取visible
        getVisible:function(){
        return this.visible;
        },

            //渲染动作
            rendering:function(ctx){
        if(this.visible){
                    for(renderObject in this.objectList){
                        this.objectList[renderObject].rendering(ctx);
                    }
        }
        return 0;
            }

        };
    },

    //图像对象
    Img:function(){

    return {
        //属性
        img:0,
        x:0,
        y:0,
        slice:{"x":0,"y":0,"width":0,"height":0},
        width:0,
        height:0,
        visible:true,

        //设置是否可见
        setVisible:function(bool){
        this.visible=bool;
        },

        //获取visible
        getVisible:function(){
        return this.visible;
        },

        //获取坐标
        getPoint:function(){
        return {x:this.x,y:this.y};
        },

        //设置坐标
        setPoint:function(x,y){
        this.x=x;
        this.y=y;
        return 0;
        },

        //设置图片路径
        setSrc:function(url){
        this.img=new Image();
        this.img.src=url;
        this.width=this.img.width;
        this.height=this.img.height;
        return 0;
        },

        //获取图片路径
        getSrc:function(){
        return this.img.src;
        },

        //设置大小
        setSize:function(width,height){
        this.width=width;
        this.height=height;
        return 0;
        },

        //获取大小
        getSize:function(){
        return {width:this.width,height:this.height};
        },

        //设置切片
        setSlice:function(x,y,width,height){
        this.slice={"x":x,"y":y,"width":width,"height":height};
        this.width=width;
        this.height=height;
        return 0;
        },

        //设置切片(根据矩形坐标)
        setSlice2:function(x1,y1,x2,y2){
        var width=x2-x1;
        var height=y2-y1;
        this.slice={"x":x1,"y":y1,"width":width,"height":height};
        this.width=width;
        this.height=height;
        },

        //获取切片
        getSlice:function(){
        return this.slice;
        },

        //绘图
        draw:function(ctx){
        ctx.save();
        ctx.drawImage(this.img,this.x,this.y);
        ctx.restore();
        return 0;
        },

        //绘图(缩放)
        drawScaled:function(ctx){
        ctx.save();
        ctx.drawImage(this.img,this.x,this.y,this.width,this.height);
        ctx.restore();
        },

        //绘图(切片)
        drawSlice:function(ctx){
        ctx.save();
        ctx.drawImage(this.img,
                  this.slice.x,this.slice.y,
                  this.slice.width,this.slice.height,
                  this.x,this.y,
                  this.width,this.height);
        ctx.restore();
        },

        //默认渲染函数
        renderingFunction:function(ctx){this.draw(ctx)},

            //设置渲染函数
            setRenderingFunction:function(func){
                this.renderingFunction=func;
        return 0;
            },

            //渲染动作
            rendering:function(ctx){
        if(this.visible){
            this.renderingFunction(ctx);
        }
        return 0;
            }

    };
    },

    //矩形对象
    Rect:function(){
        return {

            //属性
            x:0,
            y:0,
            width:0,
            height:0,
            fillColor:"",
            strokeColor:"",
        visible:true,

        //设置是否可见
        setVisible:function(bool){
        this.visible=bool;
        },

        //获取visible
        getVisible:function(){
        return this.visible;
        },

            //获得坐标
            getPoint:function(){
                return {
                    x1:this.x,
                    y1:this.y,
                    x2:this.x+this.width,
                    y2:this.y+this.height
                    };
            },

            //设置坐标
            setPoint:function(x1,y1,x2,y2){
                this.x=x1;
                this.y=y1;
                this.width=x2-x1;
                this.height=y2-y1;
                return 0;
            },

            //设置填充颜色
            setFillColor:function(color){
                this.fillColor=color;
        return 0;
            },

            //设置边框颜色
            setStrokeColor:function(color){
                this.strokeColor=color;
        return 0;
            },

            //填充
            fill:function(ctx){
                ctx.save();
                ctx.fillStyle=this.fillColor;
                ctx.fillRect(this.x,this.y,this.width,this.height);
                ctx.restore();
        return 0;
            },

            //绘制边框
            stroke:function(ctx){
                ctx.save();
                ctx.strokeStyle=this.strokeColor;
                ctx.strokeRect(this.x,this.y,this.width,this.height);
                ctx.restore();
        return 0;
            },

        //默认渲染函数
            renderingFunction:function(ctx){this.fill(ctx)},

            //设置渲染函数
            setRenderingFunction:function(func){
                this.renderingFunction=func;
        return 0;
            },

            //渲染动作
            rendering:function(ctx){
        if(this.visible){
            this.renderingFunction(ctx);
        }
        return 0;
            }

        };

    }

}

//颜色生成
Color={

    //RGB颜色
    rgb:function(r,g,b){
    return "rgb("+r+","+g+","+b+")";
    },

    //RGBA颜色
    rgba:function(r,g,b,a){
    return "rgba("+r+","+g+","+b+","+a+")";
    },

    //十六进制颜色
    hex:function(hexcolor){
    return "#"+hexcolor;
    }

};

//渲染器
Renderer=function(){
    return{
        //渲染对象列表
        objectList:[],

        //列表尾部添加
        append:function(object){
        return this.objectList.push(object);
        },

        //列表尾部去除
    pop:function(){
        return this.objectList.pop();
    },

    //返回列表长度
    len:function(){
        return this.objectList.length;
    },

        //渲染
        rendering:function(ctx){
            for(renderObject in this.objectList){
                this.objectList[renderObject].rendering(ctx);
            }
        return 0;
        }

    };
};

//画板操作
CanvasObject={

    //获取Canvas
    getById:function(id){
    return document.getElementById(id);
    },

    getByName:function(name){
    return document.getElementsByName(name);
    },

    getByTagName:function(tagName){
    return document.getElementsByTagName(tagName);
    },

    //获取Context
    getCtx:function(canvas){
    return canvas.getContext("2d");
    },

    //设置大小
    setSize:function(canvas,width,height){
    canvas.width=width;
    canvas.height=height;
    return 0;
    }

};
//循环执行函数
loop=function(){
    return{
    action:function(){},
    parameters:[],
    self:this,

    //设置this指向
    setSelf:function(self){
        this.self=self;
        return 0;
    },

    //设置函数参数
    setParameters:function(parameters){
        this.parameters=parameters;
        return 0;
    },

    //设置函数
    setAction:function(func){
        this.action=func;
        return 0;
    },

    //执行函数
    run:function(){
        this.action.apply(this.self,this.parameters);
        return 0;
    }
    }
}

//上下文对象
ContextObject=function(context){
    return {
    ctx:context,

    //绑定context对象
    bind:function(context){
        this.ctx=context;
        return 0;
    },

    //矩形区域清除,context.clearRect的封装
    clear:function(x1,y1,x2,y2){
        this.ctx.clearRect(x1,y1,x2-x1,y2-y1);
        return 0;
    },

    //设置全局透明度
    setAlpha:function(alpha){
        this.ctx.globaAlpha=alpha;
        return 0;
    },

    //获取全局透明度
    getAlpha:function(){
        return this.ctx.globaAlpha;
    },

    //获取Context对象
    getCtx:function(){
        return this.ctx;
    }

    }
}

以及测试用的DEMO.js:

//每秒帧数
var fps=60;
fps=Math.round(1000/fps)

window.onload=function(){
    //获取Canvas对象
    var canvas=CanvasObject.getById("canvas");
    //获取Context对象
    var ctx=CanvasObject.getCtx(canvas);
    //获取Context扩展
    var ctxp=ContextObject(ctx);

    //创建自定义对象
    var obj1=RenderObject.Custom();
    //画HTML5的Logo
    obj1.setRenderingFunction(function(context){
        context.save();

        // back shine
        var a,b,a1,b1,r=300,q=0;
        var a0=150,b0=200,r0=80;

        for(var i=0;i<32;i++){
                context.beginPath();
                context.fillStyle = "#f2f2f2";
                a=a0+r0*Math.cos(i*Math.PI/16);
                b=b0+r0*Math.sin(i*Math.PI/16);
                context.moveTo(a,b);
                context.arc(a,b,r,q-0.12,q+0.12,false);
                q+=Math.PI/16;
                context.closePath();
                context.fill();
        }

        // TEXT
        context.beginPath();
        context.strokeStyle="#000";
        context.lineWidth=15;
        context.moveTo(60,20);        // H

        context.lineTo(60,65);
        context.moveTo(90,20);
        context.lineTo(90,65);
        context.moveTo(60,42.5);
        context.lineTo(90,42.5);
        context.moveTo(105,27.5);    // T
        context.lineTo(150,27.5);
        context.moveTo(127.5,35);
        context.lineTo(127.5,65);
        context.moveTo(165,65);        // M
        context.lineTo(165,20);
        context.moveTo(167,25);
        context.lineTo(182.5,45);
        context.lineJoin="miter";
        context.lineTo(198,25);
        context.moveTo(200,20);
        context.lineTo(200,65);
        context.moveTo(222.5,20);    // L
        context.lineTo(222.5,57.5);
        context.lineTo(247.74,57.5);
        context.stroke();

        // Logo
        context.beginPath();
        context.fillStyle = "#e34c26";
        context.moveTo(30,85);
        context.lineTo(269.68,85);
        context.lineTo(245.31,327.46);
        context.lineTo(149.84,355);
        context.lineTo(52.57,327.46);
        context.lineTo(30,85);
        context.fill();
        context.beginPath();
        context.fillStyle = "#f06529";
        context.moveTo(149.84,105);
        context.lineTo(247.74,105);
        context.lineTo(226.74,312.77);
        context.lineTo(149.84,335);
        context.lineTo(149.84,105);
        context.fill();
        context.beginPath();
        context.fillStyle = "#ebebeb";
        context.moveTo(150,135);
        context.lineTo(74.84,135);
        context.lineTo(83.55,225);
        context.lineTo(150,225);
        context.lineTo(150,195);
        context.lineTo(110.65,195);
        context.lineTo(107.83,165);
        context.lineTo(150,165);
        context.lineTo(150,135);
        context.moveTo(85,240);
        context.lineTo(88.73,287.8);
        context.lineTo(150,305);
        context.lineTo(150,275);
        context.lineTo(116.59,266.76);
        context.lineTo(115,240);
        context.lineTo(85,240);
        context.fill();
        context.beginPath();
        context.fillStyle = "#ffffff";
        context.moveTo(149.84,135);
        context.lineTo(149.84,165);
        context.lineTo(221.85,165);
        context.lineTo(224.84,135);
        context.lineTo(149.84,135);
        context.moveTo(149.84,195);
        context.lineTo(149.84,225);
        context.lineTo(186.13,225);
        context.lineTo(181.29,266.76);
        context.lineTo(149.84,275);
        context.lineTo(149.84,305);
        context.lineTo(209.15,287.8);
        context.lineTo(219.03,195);
        context.lineTo(149.84,195);
        context.fill();

        context.restore();
    });

    //创建图像
    var img1=RenderObject.Img();
    img1.setSrc("logo.png");
    img1.setPoint(200,200);
    img1.setSlice2(0,0,55,50);
    //img1.setSize(100,100);
    img1.setRenderingFunction(img1.drawSlice);
    //img1.setRenderingFunction(img1.draw);
    //alert(img1.getSrc());
    //alert(img1.img);

    //创建矩形
    var rect1=RenderObject.Rect();
    rect1.setPoint(100,100,500,500);
    rect1.setFillColor(Color.rgb(0,122,122));
    //rect1.setRenderingFunction(rect1.fill);
    //rect1.setVisible(false);

    //创建背景
    var background=RenderObject.Rect();
    background.setPoint(0,0,canvas.width,canvas.height);
    background.setFillColor(Color.rgb(0,0,0));
    //background.setRenderingFunction(background.fill);

    //创建渲染器
    var renderer=Renderer();
    /*
    renderer.append(background);
    renderer.append(rect1);
    renderer.append(img1);
    */
    var container1=RenderObject.Container();
    /*
    container1.append(background);
    container1.append(rect1);
    container1.append(img1);
    */
    //批量添加
    container1.addList(background,obj1,rect1,img1);
    renderer.append(container1);

    //创建循环体
    var mainLoop=loop();
    mainLoop.setAction(renderer.rendering);
    mainLoop.setSelf(renderer);
    mainLoop.setParameters([ctx]);
    //mainLoop.run();

    //开始运行
    var a=1;
    setInterval(
        function(){
            if(rect1.width<=400){
                a=1;
            }else if(rect1.width>=500){
                a=-1;
            }
            rect1.width+=a;
            rect1.x+=a;
            img1.y+=a;
            img1.x+=a;
            mainLoop.run();
        },
        fps
    );
};

还有测试用的html页面:

<!DOCTYPE HTML>
<html>
<head>
    <title>DEMO</title>
    <link rel="stylesheet" href="style.css"/>
    <script src="../StartGate.2DEngine.js"></script>
    <script src="DEMO.js"></script>
</head>
<body>
    <canvas id="canvas" width="800px" height="600px">
        Your browser does not support the canvas element.
    </canvas>
</body>
</html>

以及样式表:

body{
    text-align:center;
    background:black;
}

#canvas{
    border:1px solid white;
    background:rgba(100,100,100,0.5);
}

点击这里查看DEMO

差不多就是这样…在Google Code上新建了一个start-gate的开源项目,不过由于网络问题和git玩得不熟,还没把源放上去.