【Javascript继承案例学习:绘制图形】

Javascript继承案例学习:绘制图形

这是一个关于继承的应用示例。示例的任务是计算各种不同图形的面积和边界,然后将它们绘制出来。并且,要求在这过程中尽可能地实现代码重用。

分析

首先,我们要将所有对象的公共部分定义成一个构造器,即Shape。然后我们基于这个构造器分别构建我们的Triangle、Rectangle 和Square 构造器,它们将全部继承于Shape。

Shape 体系中的共有属性主要包括:

  • 一个能根据给定的point 绘制出图形的draw()方法。
  • 一个getParameter()方法。
  • 一个用于存储point 对象的数组属性。
  • 其他必须的属性与方法。

关于绘制部分,我们还将用到标签。还有两个辅助构造器不能不提—Point 和Line。其中,Point 用于定义图形,而Line 则用于计算给定两个点之间的距离。

实现

1 首先,我们要在空白的HTML 页面中添加一个canvas 标签;然后将JavaScript 代码放到script标签里:

<canvas height="600" width="800" id="canvas" />
<script>
// ... code goes here
</script>

2 构造器定义

function Point(x, y) {
 	this.x = x;
	this.y = y;
}

function Line(p1, p2) {
    this.p1 = p1;
    this.p2 = p2;
    this.length = Math.sqrt(
        Math.pow(p1.x - p2.x, 2) + 
        Math.pow(p1.y - p2.y, 2)
    );
}

function Shape() {
    this.points = [];
    this.lines = [];
    this.init();
}

3 定义Shape.Prototype 的方法。下面我们用对象标识法来定义所有的方法。

Shape.prototype = {
// 重置坐标
constructor: Shape,
// 初始化,如果有canvas对象,设置坐标的上下文
init: function() {
    if (this.context === undefined) {
	    var canvas = document.getElementById('canvas');
	    Shape.prototype.context = canvas.getContext('2d');
    }
},
// 通过坐标绘制图形
draw: function () {
	  var i, ctx = this.context;
	  ctx.strokeStyle = this.getColor();
	  ctx.beginPath();
	  ctx.moveTo(this.points[0].x, this.points[0].y);
	  for (i = 1; i<this.points.length; i++) {
	      ctx.lineTo(this.points[i].x, this.points[i].y);
	  }
	  ctx.closePath();
	  ctx.stroke();
},
// 生成随机的颜色
getColor: function () {
   var i, rgb = [];
   for (i = 0; i< 3; i++) {
       rgb[i] = Math.round(255 * Math.random());
   }
   return 'rgb(' + rgb.join(',') + ')';
},
// 通过坐标数组,创建线的实例,并添加到shape的lines属性中
getLines: function() {
    if (this.lines.length > 0) {
        return this.lines;
    }
    var i, lines = [];
    for (i = 0; i<this.points.length; i++) {
        lines[i] = new Line(this.points[i],
        this.points[i + 1] || this.points[0]);
    }
    this.lines = lines;
    return lines;
},
// 被子对象继承,实现
getArea: function () {},
// 计算所有线的周长
getPerimeter: function () {
    var i, perim = 0, lines = this.getLines();
    for (i = 0; i<lines.length; i++) {
        perim += lines[i].length;
    }
    return perim;
}
}
// 子对象构建器:三角形
function Triangle(a, b, c){
	this.points = [a, b, c];
	this.getArea = function(){
	    var p = this.getPerimeter();
	    s = p / 2;
	    return Math.sqrt(
	        s
	        * (s - this.lines[0].length)
	        * (s - this.lines[1].length)
	        * (s - this.lines[2].length));
	};
}
// 子对象构建器:矩形
function Rectangle(p, side_a, side_b){
	this.points = [
	    p,
	    new Point(p.x + side_a, p.y), // top right
	    new Point(p.x + side_a, p.y + side_b), // bottom right
	    new Point(p.x, p.y + side_b) // bottom left
	];
	this.getArea = function() {
	    return side_a * side_b;
	};
}
// 子对象构建器:正方形。由于Square 是Rectangle 的一种特例,所以对于它的实现,我们可以重用Rectangle,而其中最简单的莫过于构造器借用法了。
function Square(p, side){
	Rectangle.call(this, p, side, side);
}
// 处理构造器之间的继承关系: 原型链模式,在该模式中,我们需要新建一个父对象实体,然后直接将其设置为子对象的原型
(function () {
	var s = new Shape();
	Triangle.prototype = s;
	Rectangle.prototype = s;
	Square.prototype = s;
})();
// 测试
var p1 = new Point(100, 100);
var p2 = new Point(300, 100);
var p3 = new Point(200, 0);

var t = new Triangle(p1, p2, p3);
t.draw();
t.getPerimeter();
t.getArea();

var r = new Rectangle(new Point(200, 200), 50, 100);
r.draw();
r.getPerimeter();
r.getArea();

var s = new Square(new Point(130, 130), 50);
s.draw();
s.getPerimeter();
s.getArea();

new Square(p1, 200).draw();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

~卷心菜~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值