JavaScript 原型继承和 html canvas

2024-05-13

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

这本书的例子之一如下。 给定一个 Shape,其原型有一个绘制方法,以及两个子形状:一个 Triangle 和一个 Rectangle,其原型继承自 Shape;

  • 当我在三角形和矩形实例上调用绘制函数时,该方法将正确绘制它们。
  • 当我添加第二种方法来显示它们的名称时,每个实例都会正确记录它。

一切都是可以理解的,直到我添加了第三种方法来填充形状......并且只有最后一个被填充。不管我打电话给哪一个。为什么?画布上有什么特别的吗?

这是练习的代码:

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只有最后一个被填满。这意味着我在参考画布时做错了事情。我以为它是“我绘制形状的地方”,但它看起来更像是“最后一个活动形状”
  • 我怎样才能修复该代码以使其正确工作填充我想要的形状不管什么时候我要?我是说。如果我想要一个函数来接收特定形状的实例并填充它怎么办?
  • 有什么方法可以访问画布中包含的绘图吗?

问题的核心是上下文 - 你的形状正在共享single画布的上下文,因此在对象之间来回翻转并不简单。相反,请将您的操作顺序视为一次处理一个形状,只有在完成前一个形状后才继续处理下一个形状。

注意调用的顺序make_me_crazy功能:

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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript 原型继承和 html canvas 的相关文章

随机推荐

  • 无法再转换为 LayerDrawable(升级 v7 后)

    我正在使用支持库的最新版本 22 1 1 我曾经这样去 mRatingBar RatingBar getActivity findViewById R id rating LayerDrawable layer LayerDrawable
  • PHP 论坛软件可以轻松与现有网站集成吗? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有一个现有的 php 网站 已经设置了用户系统 注册 身份验证 丢失密码等 我决定添加一个留言板并将其与现有网站集成 在一个网站上注册应
  • 框架可以用什么代替?

    假设我有一个包含 50 个网页的网站 每个页面由 A Header 导航 左侧内容 右侧内容 Footer 不使用 Frames 服务器端编程 第三方工具和软件 构架 我需要将这 5 个部分的代码 HTML 标记 分别放入这 50 个页面中
  • 指向指针的指针与普通指针

    指针的作用是保存特定变量的地址 那么下面代码的内存结构应该是这样的 int a 5 int b a 内存地址 值一个 0x000002 5b 0x000010 0x000002 好的 那么假设现在我要保存指针 b的地址 那么我们一般定义一个
  • Python3 http.server:将日志保存到文件中

    我使用Python3 6编写了一个简单的HTTP服务器来重定向所有请求 我写的文件可以找到here https github com kmahyyg learn py3 blob master antiscanhttp py 我可以在 Ub
  • 防止脚本目录被添加到Python 3中的sys.path

    有没有办法阻止脚本的目录被添加到python3中的sys path 由于导入在 python 中是相对的 因此我遇到了导入冲突 我正在处理的一个遗留项目有一个名为logger py在与内置冲突的脚本的根目录中logger 我使用的自定义构建
  • 从SQLite列中获取所有数字字符串并进行总和计算

    我是 Android 和 SQLite 的新手 我在 SQLite 中有一个只有数字的 AMOUNT 列 我可以在 ListView 中显示它 但我无法找到任何我理解的方法来将它们全部添加并显示在 TextView 中 这是数据库助手 im
  • 修改sqlite3中的列类型

    我对 SQLite 3 还很陌生 现在我必须向现有的表中添加一列 我开始这样做 ALTER TABLE thetable ADD COLUMN category 当然 我忘记指定该列的类型 我想做的第一件事就是删除该列 然后重新添加它 然而
  • 如果列表中的某个字符位于该字符之前,请选择该字符

    我有这个正则表达式 a z s gmi 该正则表达式选择 从我的文字中 sme a eliezovce 2015 Spolo ne pre Eur pu Osl vili aj 940 但我只想选择 没有 如果列表中的某些字符 a z 之前
  • Spring MVC - 自动查找验证器

    假设我有一个像这样的示例实体类 public class Address 和相应的验证器 Component public AddressValidator implements Validator Override public bool
  • 如何在 postgreSQL 中从时间戳中减去/添加分钟

    我有以下场景 我有员工登记他们的上班 下班手续 但他们有10分钟的容忍度 我通过这种观点得到的最新条目 CREATE OR REPLACE VIEW employees late entries id created datetime en
  • Windows Azure 远程站点“Microsoft.ACE.OLEDB.12.0”提供程序未在本地计算机上注册[重复]

    这个问题在这里已经有答案了 以下代码在我的本地开发计算机上可以正常运行 但是当我部署它时 我收到以下错误消息Azure 远程网站 我已经查看了SO答案和谷歌搜索结果 但我仍然不清楚我必须在本地计算机上安装什么 这样当我将代码推送到Azure
  • 如何阻止 Django 中发生级联删除?

    我的 Django 应用程序中有三个模型类 class Folder models Model folder models ForeignKey Folder null True blank True related name folder
  • 您的手机中未安装应用程序

    我在模拟器中运行该应用程序 它成功运行 并且应用程序的图标显示在模拟器菜单中 但是当我尝试从模拟器菜单再次运行该应用程序时 它不允许我从中运行并显示 Toast 您的手机中未安装应用程序 在图像中 红色圆形是我的应用程序图标 如果您有您的M
  • “初始化 MCI 时出现问题”播放声音问题

    我正在尝试使用 Playsound 播放代码文件夹中的文件 但是每次运行代码时 它似乎都能够调用该文件 但我总是收到以下输出 playsound PlaysoundException Error 277 for command open p
  • 图像魔法叠加图像

    我有两个图像 一个是叠加图像 比如说具有透明度的图像 A 另一个是图像 B 我必须将叠加图像 A 放在图像 B 上 以便通过图像 A 的透明部分可以看到图像 B 的某些部分 我还必须根据一些参数移动图像B 我怎样才能用image magic
  • WebPack 源映射令人困惑(重复文件)

    我决定在我今天正在启动的一个新项目上尝试 WebPack 并且我从源映射中得到了非常奇怪的行为 我在文档中找不到任何相关信息 在浏览 StackOverflow 时也找不到其他人遇到此问题 我目前正在查看由以下公司制作的 HelloWorl
  • Scala 的代码覆盖率工具 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • FF 和 Webkit 中边框折叠的差异

    我有一个包含以下规则的表 table cellspacing 0 cellpadding 0 style width 100 并且单元格具有以下 CSS td padding 4px height 22px border 1px solid
  • JavaScript 原型继承和 html canvas

    我是一名 Ruby 开发人员 最终决定认真学习 JavaScript 所以我买了一些书 开始深入研究 但当我试图理解原型继承时 我很快就陷入了困境 这本书的例子之一如下 给定一个 Shape 其原型有一个绘制方法 以及两个子形状 一个 Tr