绘画板 02——抽象并实现图形绘制功能

github地址: https://github.com/wangyuheng/painter

DEMO地址: http://painter.crick.wang/

针对上个版本的基础代码进行抽象和封装

将所有的图形绘制工具,都“继承”一个DrawTool工具类,在此工具类中绑定、解绑事件,代码如下

(function() {
    var defaultListener = {
        mousedown: function() {
            console.log('mousedown you should implement this function!');
        },
        mousemove: function() {
            console.log('mousemove you should implement this function!');
        },
        mouseup: function() {
            console.log('mouseup   you should implement this function!');
        }
    };
    var DrawTool = {
        init: function(svgDoc, listeners) {
            var l = $.extend({}, defaultListener, listeners);
            svgDoc.on('mousedown', l.mousedown);
            svgDoc.on('mousemove', l.mousemove);
            svgDoc.on('mouseup', l.mouseup);
        },
        stop: function(svgDoc, listeners) {
            var l = $.extend({}, defaultListener, listeners);
            svgDoc.off('mousemove', l.mousemove);
            svgDoc.off('mousedown', l.mousedown);
            svgDoc.off('mouseup', l.mouseup);
        }
    };


    this.DrawTool = DrawTool;
})();

所有js独立代码都采用闭包形式,避免的参数污染。 拆分后的目录结构如下

painter-2-0

还是以矩形为例,Rect在构造函数中继承使用了DrawTool的init方法,并重写stop方法,暴露出去。

var Rect = function(parentEle) {
    parent = parentEle;
    svgDoc = parent.doc();
    DrawTool.init(svgDoc, listener);
    this.stop = function () {
        DrawTool.stop(svgDoc, listener);
    };
};

this.DrawTool.Rect = Rect;

通过在Rect类内部定义mousedown、mousemove、mouseup事件方法,调用svgjs提供的绘制方法,实现图形的绘制工作。完整代码如下:

(function() {

    var parent = null;
    var drawing = false;
    var element = null;
    var startPoint = null;

    function mousedown(event) {
        console.log('rect mousedown');
        drawing = true;
        startPoint = svgDoc.transformPoint(event);
        element = parent.rect(0, 0).style("fill-opacity", '0.0').stroke({
            width: '2',
            color: '#000000'
        });
    }

    function mousemove(event) {
        console.log('rect mousemove');
        if (drawing) {
            var svgPoint = svgDoc.transformPoint(event);
            var x = svgPoint.x;
            var y = svgPoint.y;

            var newWidth = x - startPoint.x;
            var newHeight = y - startPoint.y;
            var startX = startPoint.x;
            var startY = startPoint.y;
            if (newWidth < 0) {
                startX += newWidth;
            }

            if (newHeight < 0) {
                startY += newHeight;
            }
            newWidth = Math.abs(newWidth);
            newHeight = Math.abs(newHeight);
            element.x(startX).y(startY).width(newWidth).height(newHeight);
        }
    };

    function mouseup(event) {
        console.log('rect mouseup ' + element);
        drawing = false;
    }

    var listener = {
        mousedown: mousedown,
        mousemove: mousemove,
        mouseup: mouseup,
    };


    var Rect = function(parentEle) {
        parent = parentEle;
        svgDoc = parent.doc();
        DrawTool.init(svgDoc, listener);
        this.stop = function () {
            DrawTool.stop(svgDoc, listener);
        };
    };

    this.DrawTool.Rect = Rect;

})();

有一个特殊的类为折线polyline工具类,此图形为连续绘制,需要记录上一个element,并且在stop方法中清空之前的element,并且监听鼠标右键点击事件,结束图形绘制。
阻止鼠标右键方法为

function mousedown(event) {
    if (event.button == 2) {
        document.oncontextmenu=function(){return false;}
        drawing=false;
        points  = [];
        element = null;
        return;
    }
    if (!drawing) {
        drawing = true;
        var currPoint = svgDoc.transformPoint(event);
        points.push([currPoint.x, currPoint.y]);
    }
}

至此,已完成图形的基本绘制功能