javascript全栈开发实践-web-7

184 阅读2分钟

我们在重构代码之后,重新添加新的功能:添加一个圆形/椭圆的工具。 第一步,增加一个新的按钮:

      <button id='ellipse' onclick="handleDrawEllipse()">ellipse</button>

按钮点击事件响应代码:

    function handleDrawEllipse(event) {
      tool = new EllipseTool(ctx, 2, 'green');
    }

第二部,实现EllipseTool。类似于矩形,也是用鼠标拖出一个矩形区域,然后在这个矩形区域内,画出一个椭圆/圆形。因此,我们让EllipseTool直接继承RectTool:

    class EllipseTool extends RectTool {
      //
      handleMouseMove(x, y) {
        if (this._tempImageData) {
          ctx.putImageData(this._tempImageData, 0, 0);
        }
        //
        this._bottomRight = {x, y};
        //
        const pt1 = this._topLeft;
        const pt2 = this._bottomRight;
        const left = Math.min(pt1.x, pt2.x);
        const top = Math.min(pt1.y, pt2.y);
        const right = Math.max(pt1.x, pt2.x);
        const bottom = Math.max(pt1.y, pt2.y);
        //
        const centerX = (left + right) / 2;
        const centerY = (top + bottom) / 2;
        const radiusX = centerX - left;
        const radiusY = centerY - top;
        ctx.beginPath();
        ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, Math.PI * 2);
        ctx.stroke();
      }
      //
      handleMouseUp() {
        return new EllipseData(this._topLeft, this._bottomRight, this.lineWidth, this.strokeStyle);
      }
    }

我们只是重写了handleMouseMove和handleMouseUp。主要就是覆盖显示部分和返回的数据类型。EllipseData也很简单:

    class EllipseData extends RectData {
      //
      draw(ctx) {
        //
        ctx.beginPath();
        ctx.lineWidth = this._lineWidth;
        ctx.strokeStyle = this._strokeStyle;
        //
        const pt1 = this._topLeft;
        const pt2 = this._bottomRight;
        const left = Math.min(pt1.x, pt2.x);
        const top = Math.min(pt1.y, pt2.y);
        const right = Math.max(pt1.x, pt2.x);
        const bottom = Math.max(pt1.y, pt2.y);
        //
        const centerX = (left + right) / 2;
        const centerY = (top + bottom) / 2;
        const radiusX = centerX - left;
        const radiusY = centerY - top;
        //
        ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, Math.PI * 2);
        ctx.stroke();
        //
      } 

同样,我们让EllipseData继承RectData,然后重写draw方法。当然你也可以让EllipseData直接继承自ActionData。并不会有太大的区别。 这样我们就实现了圆形/椭圆的绘制工具。和重构之前,我们添加矩形工具完全不同,我们没有修改任何已经存在的代码,而是仅仅添加了新的代码,就实现了椭圆工具的添加。 同样,你也可以继续实现更多的工具,例如直线,正多边形,五角星等等。 不过,仍然有可以改进的地方。首先,我们的js代码和html混在一起,不符合目前主流的方式(html和js分离)。即使我们把js拿出来当独放在一个文件内,让然不便与维护。因为所有的功能都混在一个文件内。 接下来,我们将会利用webpack来解决这个问题。让我们开发js就像c++/java那样,把代码分成不同的模块,然后模块之间可以进行引用,最后形成一个工程。