我们在重构代码之后,重新添加新的功能:添加一个圆形/椭圆的工具。 第一步,增加一个新的按钮:
<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那样,把代码分成不同的模块,然后模块之间可以进行引用,最后形成一个工程。