zoukankan      html  css  js  c++  java
  • 5. javascript OOP编程:封装、继承从零起步实现基于Html5的WEB设计器Jquery插件(含源码)

    面向对象编程三要素:封装、继承、多态,在这节中将结合设计器的组件设计来阐述javascript如何实现。

    1.封装:在设计器中的组件是很适合来说明封装的概念,组件是可以拖放到设计器画布上的元素,他可以有不同的形状,不同的背景,但通过抽象和提炼后具备以下共性

    • 都可以拖放到画布上
    • 都可以被选中和反选
    • 都有大小(宽、高)和位置,背景填充色,边框线颜色,文字颜色
    • 都可以被拖动
    • 都可以有文字标签
    • 一个组件可能包含多个子的元素组成。
    • 组件可以有背景图片
    • 组件可以调整大小
    • 组件间可以有连线,
    • 组件可以有不同种状态
    • 组件可以重绘

    因此我们抽象出一个类Component作为基类,定义三个继承组件Circle,Retangle,Ellipse

        function Component() {
        }
        Component.prototype.init = function (options) {
            if (options == undefined)
                options = {};
            this.properties = $.extend(options, Component.DEFAULTS);
            this.group = new paper.Group();
            var me = this;
            var drag = false;
            this.group.onClick = function (event) {
                me.group.children[0].selected = !me.group.children[0].selected;
            }
            this.group.onMouseDown = function (event) {
                drag = (event.event.button == 0);
            }
            this.group.onMouseUp = function () {
                drag = false;
                document.body.style.cursor = 'default';
            }
            this.group.onMouseDrag = function (event) {
                if (drag) {
                    this.translate(event.delta.x, event.delta.y);
                    document.body.style.cursor = 'move';
                }
            }
            return this;
        }
        Component.prototype.select = function () {
            this.group.children[0].selected = true;
        }
        Component.prototype.unselect = function () {
            this.group.children[0].selected = false;
        }
        Component.DEFAULTS = $.extend({}, {
             50,
            height: 50,
            x: 0,
            y: 0,
            id: "",
            typeName:"Component",
            backgroundColor:"white",
            backgroundImage:'',
            fontColor:'black',
            borderColor:'black',
            lineWeight:1,
            title: '',
            status: 1,
            runMode: 1,
            capacity:1
        });

    基类包括默认属性DEFAULTS,初始化方法init,选中select和取消选中unselect方法。

    javascript的继承是通过原型扩展来实现的,如下三个继承类的实现:

        function Circle() { }
        Circle.prototype = $.extend({}, Component.prototype);
        Circle.prototype = $.extend(Circle.prototype, {
            render: function (options) {
                this.properties = $.extend(this.properties, options);
                var circle = new paper.Path.Circle({
                    center: [this.properties.x, this.properties.y],
                    radius: 25,
                    fillColor: this.properties.backgroundColor
                });
                this.group.addChild(circle);
                return this;
            }
        });
    
        function Retangle() { }
        Retangle.prototype = $.extend({}, Component.prototype);
        Retangle.prototype = $.extend(Retangle.prototype, {
            render: function (options) {
                this.properties = $.extend(this.properties, options);
                var rect = new paper.Path.Rectangle({
                    point: [this.properties.x, this.properties.y],
                    size: [this.properties.width, this.properties.height],
                    radius: 5,
                    strokeWidth: 1,
                    strokeColor: this.properties.borderColor,
                    fillColor: this.properties.backgroundColor,
                    opacity: this.properties.opacity
                });
                this.group.addChild(rect);
                return this;
            }
        });
    
        function Ellipse() { }
        Ellipse.prototype = $.extend({}, Component.prototype);
        Ellipse.prototype = $.extend(Ellipse.prototype, {
            render: function (options) {
                this.properties = $.extend(this.properties, options);
                var ellipse = new paper.Path.Ellipse(
                    {
                        point: [this.properties.x, this.properties.y],
                        size: [this.properties.width, this.properties.height],
                        fillColor: this.properties.fillColor,
                    opacity: this.properties.opacity
                });
                this.group.addChild(ellipse);
                return this;
            }
        });

     注意看上图,

    Ellipse.prototype = $.extend({}, Component.prototype); 将基类原型方法扩展过来,
    Ellipse.prototype = $.extend(Ellipse.prototype, { 重写render方法,如果基类有定义render,在实例化调用时会调用重写的方法。
            render: function (options) {}

    我们再看拖拉生成实例的代码onDrop
            this.$element.on("drop", function (event) {
                event.preventDefault();
                debugger;
                var data = null;
                if (event.dataTransfer == undefined && event.originalEvent != undefined)
                    data = event.originalEvent.dataTransfer.getData("text");
                else if (event.dataTransfer != undefined)
                    data = event.dataTransfer.getData("text");
                var drag = false;
                switch (data) {
                    case "圆":
                        debugger;
                        var circle = new Circle().init().render({ x: event.originalEvent.offsetX, y: event.originalEvent.offsetY });
                        break;
                    case "矩形":
                        var rect = new Retangle().init().render({ x: event.originalEvent.offsetX, y: event.originalEvent.offsetY,  200, height: 100, opacity: 0.5 });
                        break;
                    case "椭圆":
                        var path = new Ellipse().init().render({ x: event.originalEvent.offsetX, y: event.originalEvent.offsetY,  120, height: 60, fillColor: 'green' });
                        break;
                }
            });

    注意对比上一节的示例代码,此处在生成实例时代码有简化,

    以var circle = new Circle().init().render({ x: event.originalEvent.offsetX, y: event.originalEvent.offsetY });为例,此处new Circle()
    会调用function Circle()的构造函数,init()在Circle中并没有定义,但通过原型继承了过来,所以是调用Component.init()方法,注意方法内部return this,实际
    返回的是Circle对象,接着.render是调用的Circle重写了的render方法。

    此处不再需要在每一个组件实例化后调用onClick,onMouseDown,onMouseUp,OnMouseDrag了,因为在基类初始化时已经定义了。只是需要理解this.group的概念,因为一个组件可能由多个图形或文字组成,划成一个Group当作一个整体。

    本节介绍就到这里,paperjs提供了许多的形状,事件,大家可以从paperjs.org官网了解更多,站在巨人的肩膀总比独自从造轮子来得要快。

    本节源代码下载:sample1.3

    直接运行查看

    (本文为原创,在引用代码和文字时请注明出处)

     
  • 相关阅读:
    P3932 浮游大陆的68号岛
    P4595 [COCI2011-2012#5] POPLOCAVANJE
    CF455E Function
    【转载】乱堆的东西
    BZOJ1034 [ZJOI2008]泡泡堂BNB[贪心]
    CSP2019退役记
    BZOJ5206 [Jsoi2017]原力[根号分治]
    luogu3651 展翅翱翔之时 (はばたきのとき)[基环树+贪心]
    BZOJ1040 [ZJOI2008]骑士[基环树DP]
    BZOJ3037 创世纪[基环树DP]
  • 原文地址:https://www.cnblogs.com/coolalam/p/9604409.html
Copyright © 2011-2022 走看看