JavaScript原型继承和html画布 [英] JavaScript prototype inheritance and html canvas

查看:85
本文介绍了JavaScript原型继承和html画布的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名Ruby开发人员,他最终决定认真学习JavaScript。所以我购买了一些书籍,我开始潜入,但当我试图理解原型继承时,我很快陷入困境......

I'm a Ruby developer who finally decided to learn JavaScript seriously. So I purchased some books and I started to dive in, but I got stuck quickly when I tried to understand prototypal inheritance...

本书的一个例子是下列。
给定一个Shape,其原型有一个draw方法,以及两个子形状:一个Triangle和一个Rectangle,它继承自Shape;

One of the examples of the book is the following. Given a Shape which prototype has a draw method, and two child shapes: a Triangle and a Rectangle which prototype inherit from Shape;


  • 当我在Triangle和Rectangle实例上调用draw函数时,该方法将正确绘制它们。

  • 当我添加第二个方法来显示他们的名字时,每个实例都会正确记录它。

在我添加第三种填充形状的方法之前,一切都是完全可以理解的......只有最后一种方法才能填满。无论我打电话给哪一个。为什么?画布中有什么特别之处吗?

Everything was understandable perfectly until I added a third method to fill the shapes... And only the last one get filled. no matter which one I call. Why? Is there something special in canvas?

以下是练习的代码:

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

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

Shape.prototype = {
  constructor: Shape,
  init: function() {
    if (this.context === undefined) {
      Shape.prototype.context = document.getElementById('canvas').getContext('2d');
    };
    if (this.name === undefined) {
      Shape.prototype.name = 'generic shape'
    }
  },
  draw: function() {
    var i, ctx = this.context;
    ctx.strokeStyle = 'rgb(0,0,255)';
    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();
  },
  fill: function(color) {
    var ctx = this.context;
    ctx.fillStyle = color;
    ctx.fill();
  },
  say_name: function() {
    console.log('Hello my name is ' + this.name)
  }
};

function Triangle(a, b, c) {
  this.points = [a, b, c];
  this.name = 'Triangle'
  this.context = document.getElementById('canvas').getContext('2d');
}

function Rectangle(side_a, side_b) {
  var p = new Point(200, 200);
  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.name = 'Rectangle'
  this.context = document.getElementById('canvas').getContext('2d');
}

(function() {
  var s = new Shape();
  Triangle.prototype = s;
  Rectangle.prototype = s;
})();

function testTriangle() {
  var p1 = new Point(100, 100);
  var p2 = new Point(300, 100);
  var p3 = new Point(200, 0);
  return new Triangle(p1, p2, p3);
}

function testRectangle() {
  return new Rectangle(100, 100);
}

function make_me_crazy() {
  var t = testTriangle();
  var r = testRectangle();
  t.draw();
  r.draw();
  t.say_name();
  r.say_name();
  t.fill('red');
}
make_me_crazy();

<canvas height='600' width='800' id='canvas' />

谢谢!

更多详情:


  • 为什么函数 say_name 完全正常工作我希望说:'我是一个三角'或'我是一个矩形'而且从来没有'我是一个通用的形状',但是 fill 函数填充矩形,尽管我在三角形实例上调用它?当人们正确回答翻转两个绘制函数调用时,我会更好地指定以下内容。问题不在于形状的颜色,而在于 context 指针。为什么只填充最后一个形状?如果我在调用 fill 之前添加更多形状,则只会填充最后一个。这意味着我在做画布时做错了。我认为它是我绘制形状的地方,但它看起来更像是最后一个活跃的形状

  • 如何修复该代码以使其正常工作填充我想要的形状我想要?我的意思是。如果我想要一个接收特定形状实例并填充它的函数怎么办?

  • 有没有办法访问包含在画布中的绘图?

  • Why the function say_name is working exactly I expect saying: 'I am a triangle' or 'I am a rectangle' and never 'I am a generic shape', but the fill function fills the rectangle despite I'm calling it on a triangle instance? As people rightly answered to flip the two draw functions calls, I would specify better the following. The problem is not about the color of a shape, but the context pointer. why only the last shape is filled? If I add more shapes before calling fill only the last one get filled. This means I'm doing something wrong referring to the canvas. I supposed it was "the place where I draw shapes" but it seems more like "the last active shape"
  • How can I fix that code to make it working correctly filling the shape I want whenever I want? I mean. what if I want to have a function which receive an instance of a particular shape and fills it?
  • Is there any way to access a the draws contained into a canvas?

推荐答案

问题的核心是上下文 - 你的形状共享画布的上下文,因此在对象之间来回翻转并不是直截了当的。相反,将您的操作顺序视为一次处理单个形状,并在完成前者时仅转移到下一个形状。

The core of the problem is the context - your shapes are sharing the single context of the canvas, and therefore it is not straight-forward to flip back and forth between objects. Instead, think of your order-of-operations as handling a single shape at a time and only moving on to the next one when you are done with the former.

注意 make_me_crazy 函数中的调用顺序:

Note the order of calls in the make_me_crazy function:

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

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

  Shape.prototype = {
    constructor: Shape,
    init: function(){
      if (this.context === undefined) {
        Shape.prototype.context = document.getElementById('canvas').getContext('2d');
      };
      if(this.name === undefined){
        Shape.prototype.name = 'generic shape'
      }
    },
    draw: function(){
      var i, ctx = this.context;
      ctx.strokeStyle = 'rgb(0,0,255)';
      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();
    },
    fill: function(color){
      var ctx = this.context;
      ctx.fillStyle = color;
      ctx.fill();
    },
    say_name: function(){console.log('Hello my name is '+ this.name)}
  };

  function Triangle(a,b,c){
    this.points = [a, b, c];
    this.name = 'Triangle'
    this.context = document.getElementById('canvas').getContext('2d');
  }

  function Rectangle(side_a, side_b){
    var p = new Point(200, 200);
    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.name = 'Rectangle'
    this.context = document.getElementById('canvas').getContext('2d');
  }

  (function(){
    var s = new Shape();
    Triangle.prototype = s;
    Rectangle.prototype = s;
  })();

  function testTriangle(){
    var p1 = new Point(100, 100);
    var p2 = new Point(300, 100);
    var p3 = new Point(200, 0);
    return new Triangle(p1, p2, p3);
  }

  function testRectangle(){
    return new Rectangle(100, 100);
  }

  function make_me_crazy(){
    var t = testTriangle();
    t.say_name();
    t.draw();
    t.fill('red');
    
    var r = testRectangle();
    r.draw();
    r.say_name();
  }
  make_me_crazy();

<canvas height='600' width='800' id='canvas'></canvas>

这篇关于JavaScript原型继承和html画布的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆