1

我正在尝试用 Javascript/Coffeescript编写Dart演示之一。就代码而言,一切似乎都运行良好,但画布上什么也没有出现。我已经在 Firefox 和 Chrome 中对此进行了测试,但没有收到任何控制台错误或任何东西。我无法完全弄清楚这一点。任何想法为什么我的画布保持空白?

这是我在http://jsbin.com/orazag/1/edit的代码

对于后代,它也是如此。

HTML:

<!DOCTYPE html>

<!-- Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
     for details. All rights reserved. Use of this source code is governed by a
     BSD-style license that can be found in the LICENSE file. -->

<html>
  <head>
    <meta charset="utf-8">
    <title>Solar System Demo</title>
    <link type="text/css" rel="stylesheet" href="solar.css">
  </head>
  <body>
    <h1>Solar System</h1>

    <p>A solar system visualization using requestAnimationFrame.</p>

    <div>
      <canvas id="container" width="500px" height="400px"></canvas>
    </div>

    <footer>
      <p id="summary"> </p>
      <p id="notes"> </p>
    </footer>

    <script type="text/javascript" src="solar.js"></script>
  </body>
</html>

CSS:

/* Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file */
/* for details. All rights reserved. Use of this source code is governed by a */
/* BSD-style license that can be found in the LICENSE file. */

body {
  background-color: #F8F8F8;
  font-family: 'Open Sans', sans-serif;
  font-size: 14px;
  font-weight: normal;
  line-height: 1.2em;
  margin: 15px;
}

p {
  color: #333;
}

#container {
  border: 1px solid #ccc;
  background-color: #fff;
}

#summary {
  float: left;
}

#notes {
  float: right;
  width: 120px;
  text-align: right;
}

.error {
  font-style: italic;
  color: red;
}

咖啡脚本:

window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame

main = ->
   solarSystem = new SolarSystem document.getElementById 'container'
   solarSystem.start()
   return

fpsAverage = null
showFps = (fps) ->
   fpsAverage ?= fps
   fpsAverage = fps * 0.05 + fpsAverage * 0.95
   document.getElementById('notes').textContent = Math.round(fpsAverage) + ' fps'
   return

class Point
    constructor: (@x, @y) ->

class SolarSystem
    constructor: (@canvas) ->
        @renderTime = null
    start: ->
        @width = @canvas.parentNode.clientWidth
        @height = @canvas.parentNode.clientHeight
        @canvas.width = @width
        @_start()
        return
    _start: ->
        # Create the Sun.
        @sun = new PlanetaryBody @, 'Sun', '#ff2', 14.0
        # Add planets.
        @sun.addPlanet new PlanetaryBody @, 'Mercury', 'orange', 0.382, 0.387, 0.241
        @sun.addPlanet new PlanetaryBody @, 'Venus', 'green', 0.949, 0.723, 0.615

        earth = new PlanetaryBody @, 'Earth', '#33f', 1.0, 1.0, 1.0
        @sun.addPlanet earth
        earth.addPlanet new PlanetaryBody @, 'Moon', 'gray', 0.2, 0.14, 0.075

        @sun.addPlanet new PlanetaryBody @, 'Mars', 'red', 0.532, 1.524, 1.88
        @addAsteroidBelt @sun, 150

        f = 0.1
        h = 1 / 1500.0
        g = 1 / 72.0

        jupiter = new PlanetaryBody @, 'Jupiter', 'gray', 4.0, 5.203, 11.86
        @sun.addPlanet jupiter
        jupiter.addPlanet new PlanetaryBody @, 'Io', 'gray', 3.6 * f, 421 * h, 1.769 * g
        jupiter.addPlanet new PlanetaryBody @, 'Europa', 'gray', 3.1 * f, 671 * h, 3.551 * g
        jupiter.addPlanet new PlanetaryBody @, 'Ganymede', 'gray', 5.3 * f, 1070 * h, 7.154 * g
        jupiter.addPlanet new PlanetaryBody @, 'Callisto', 'gray', 4.8 * f, 1882 * h, 16.689 * g

        @requestRedraw()
        return
    draw: ->
        @requestRedraw()
        time = Date.now()
        if @renderTime?
            showFps Math.round 1000 / (time - @renderTime)
        @renderTime = time
        context = @canvas.getContext '2d'
        @drawBackground context
        @drawPlanets context
        return
    drawBackground: (context) ->
        context.fillStyle = 'white'
        context.rect 0, 0, @width, @height
        context.fill()
        return
    drawPlanets: (context) ->
        @sun.draw context, @width / 2, @height /2
        return
    requestRedraw: ->
        window.requestAnimationFrame => @draw()
        return
    addAsteroidBelt: (body, count) ->
        # Asteroids are generally between 2.06 and 3.27 AUs.
        for [0...count]
            radius = 2.06 + Math.random() * (3.27 - 2.06)
            body.addPlanet new PlanetaryBody @, 'asteroid', '#777', 0.1 * Math.random(), radius, radius * 2
        return
    normalizeOrbitRadius: (r) ->
        r * (@width / 10.0)
    normalizePlanetSize: (r) ->
        Math.log(r + 1) * (@width / 100.0)

class PlanetaryBody
    constructor: (@solarSystem, @name, @color, bodySize, orbitRadius = 0.0, @orbitPeriod = 0.0) ->
        @bodySize = solarSystem.normalizePlanetSize bodySize
        @orbitRadius = solarSystem.normalizeOrbitRadius orbitRadius
        @orbitSpeed = @_calculateSpeed orbitPeriod
        @planets = []
    addPlanet: (planet) ->
        @planets.push planet
    draw: (context, x, y) ->
        pos = @_calculatePos x, y
        @drawSelf context, pos.x, pos.y
        @drawChildren context, pos.x, pos.y
        return
    drawSelf: (context, x, y) ->
        context.save()
        try
            context.lineWidth = 0.5
            context.fillStyle = @color
            context.strokeStyle = @color
            if @bodySize >= 2.0
                context.shadowOffsetX = 2
                context.shadowOffsetY = 2
                context.shadowBlur = 2
                context.shadowColor = '#ddd'

            context.beginPath()
            context.arc x, y, @bodySize, 0, Math.PI * 2, false
            context.fill()
            context.closePath()
            context.stroke()

            context.shadowOffsetX = 0
            context.shadowOffsetY = 0
            context.shadowBlur = 0

            context.beginPath()
            context.arc x, y, @bodySize, 0, Math.PI * 2, false
            context.fill()
            context.closePath()
            context.stroke()
        finally
           context.restore()
        return
    drawChildren: (context, x, y) ->
        for planet in @planets
            planet.draw context, x, y
        return
    _calculateSpeed: (period) ->
        if period == 0.0
            0.0
        else
            1 / (60.0 * 24.0 * 2 * period)
    _calculatePos: (x, y) ->
        if @orbitSpeed == 0.0
            new Point x, y
        else
            angle = @solarSystem.renderTime * @orbitSpeed
            new Point @orbitRadius * Math.cos(angle) + x, @orbitRadius * Math.sin(angle) + y

window.onload = main

或者,如果您愿意,这里是等效的 Javascript:

// Generated by CoffeeScript 1.4.0
(function() {
  var PlanetaryBody, Point, SolarSystem, fpsAverage, main, showFps;

  window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;

  main = function() {
    var solarSystem;
    solarSystem = new SolarSystem(document.getElementById('container'));
    solarSystem.start();
  };

  fpsAverage = null;

  showFps = function(fps) {
    if (fpsAverage == null) {
      fpsAverage = fps;
    }
    fpsAverage = fps * 0.05 + fpsAverage * 0.95;
    document.getElementById('notes').textContent = Math.round(fpsAverage) + ' fps';
  };

  Point = (function() {

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

    return Point;

  })();

  SolarSystem = (function() {

    function SolarSystem(canvas) {
      this.canvas = canvas;
      this.renderTime = null;
    }

    SolarSystem.prototype.start = function() {
      this.width = this.canvas.parentNode.clientWidth;
      this.height = this.canvas.parentNode.clientHeight;
      this.canvas.width = this.width;
      this._start();
    };

    SolarSystem.prototype._start = function() {
      var earth, f, g, h, jupiter;
      this.sun = new PlanetaryBody(this, 'Sun', '#ff2', 14.0);
      this.sun.addPlanet(new PlanetaryBody(this, 'Mercury', 'orange', 0.382, 0.387, 0.241));
      this.sun.addPlanet(new PlanetaryBody(this, 'Venus', 'green', 0.949, 0.723, 0.615));
      earth = new PlanetaryBody(this, 'Earth', '#33f', 1.0, 1.0, 1.0);
      this.sun.addPlanet(earth);
      earth.addPlanet(new PlanetaryBody(this, 'Moon', 'gray', 0.2, 0.14, 0.075));
      this.sun.addPlanet(new PlanetaryBody(this, 'Mars', 'red', 0.532, 1.524, 1.88));
      this.addAsteroidBelt(this.sun, 150);
      f = 0.1;
      h = 1 / 1500.0;
      g = 1 / 72.0;
      jupiter = new PlanetaryBody(this, 'Jupiter', 'gray', 4.0, 5.203, 11.86);
      this.sun.addPlanet(jupiter);
      jupiter.addPlanet(new PlanetaryBody(this, 'Io', 'gray', 3.6 * f, 421 * h, 1.769 * g));
      jupiter.addPlanet(new PlanetaryBody(this, 'Europa', 'gray', 3.1 * f, 671 * h, 3.551 * g));
      jupiter.addPlanet(new PlanetaryBody(this, 'Ganymede', 'gray', 5.3 * f, 1070 * h, 7.154 * g));
      jupiter.addPlanet(new PlanetaryBody(this, 'Callisto', 'gray', 4.8 * f, 1882 * h, 16.689 * g));
      this.requestRedraw();
    };

    SolarSystem.prototype.draw = function() {
      var context, time;
      this.requestRedraw();
      time = Date.now();
      if (this.renderTime != null) {
        showFps(Math.round(1000 / (time - this.renderTime)));
      }
      this.renderTime = time;
      context = this.canvas.getContext('2d');
      this.drawBackground(context);
      this.drawPlanets(context);
    };

    SolarSystem.prototype.drawBackground = function(context) {
      context.fillStyle = 'white';
      context.rect(0, 0, this.width, this.height);
      context.fill();
    };

    SolarSystem.prototype.drawPlanets = function(context) {
      this.sun.draw(context, this.width / 2, this.height / 2);
    };

    SolarSystem.prototype.requestRedraw = function() {
      var _this = this;
      window.requestAnimationFrame(function() {
        return _this.draw();
      });
    };

    SolarSystem.prototype.addAsteroidBelt = function(body, count) {
      var radius, _i;
      for (_i = 0; 0 <= count ? _i < count : _i > count; 0 <= count ? _i++ : _i--) {
        radius = 2.06 + Math.random() * (3.27 - 2.06);
        body.addPlanet(new PlanetaryBody(this, 'asteroid', '#777', 0.1 * Math.random(), radius, radius * 2));
      }
    };

    SolarSystem.prototype.normalizeOrbitRadius = function(r) {
      return r * (this.width / 10.0);
    };

    SolarSystem.prototype.normalizePlanetSize = function(r) {
      return Math.log(r + 1) * (this.width / 100.0);
    };

    return SolarSystem;

  })();

  PlanetaryBody = (function() {

    function PlanetaryBody(solarSystem, name, color, bodySize, orbitRadius, orbitPeriod) {
      this.solarSystem = solarSystem;
      this.name = name;
      this.color = color;
      if (orbitRadius == null) {
        orbitRadius = 0.0;
      }
      this.orbitPeriod = orbitPeriod != null ? orbitPeriod : 0.0;
      this.bodySize = solarSystem.normalizePlanetSize(bodySize);
      this.orbitRadius = solarSystem.normalizeOrbitRadius(orbitRadius);
      this.orbitSpeed = this._calculateSpeed(orbitPeriod);
      this.planets = [];
    }

    PlanetaryBody.prototype.addPlanet = function(planet) {
      return this.planets.push(planet);
    };

    PlanetaryBody.prototype.draw = function(context, x, y) {
      var pos;
      pos = this._calculatePos(x, y);
      this.drawSelf(context, pos.x, pos.y);
      this.drawChildren(context, pos.x, pos.y);
    };

    PlanetaryBody.prototype.drawSelf = function(context, x, y) {
      context.save();
      try {
        context.lineWidth = 0.5;
        context.fillStyle = this.color;
        context.strokeStyle = this.color;
        if (this.bodySize >= 2.0) {
          context.shadowOffsetX = 2;
          context.shadowOffsetY = 2;
          context.shadowBlur = 2;
          context.shadowColor = '#ddd';
        }
        context.beginPath();
        context.arc(x, y, this.bodySize, 0, Math.PI * 2, false);
        context.fill();
        context.closePath();
        context.stroke();
        context.shadowOffsetX = 0;
        context.shadowOffsetY = 0;
        context.shadowBlur = 0;
        context.beginPath();
        context.arc(x, y, this.bodySize, 0, Math.PI * 2, false);
        context.fill();
        context.closePath();
        context.stroke();
      } finally {
        context.restore();
      }
    };

    PlanetaryBody.prototype.drawChildren = function(context, x, y) {
      var planet, _i, _len, _ref;
      _ref = this.planets;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        planet = _ref[_i];
        planet.draw(context, x, y);
      }
    };

    PlanetaryBody.prototype._calculateSpeed = function(period) {
      if (period === 0.0) {
        return 0.0;
      } else {
        return 1 / (60.0 * 24.0 * 2 * period);
      }
    };

    PlanetaryBody.prototype._calculatePos = function(x, y) {
      var angle;
      if (this.orbitSpeed === 0.0) {
        return new Point(x, y);
      } else {
        angle = this.solarSystem.renderTime * this.orbitSpeed;
        return new Point(this.orbitRadius * Math.cos(angle) + x, this.orbitRadius * Math.sin(angle) + y);
      }
    };

    return PlanetaryBody;

  })();

  window.onload = main;

}).call(this);
4

1 回答 1

2

我的基本调试过程是:

  1. 是否调用了绘图函数?console.log('drawing')在绘图功能中告诉我,是的。
  2. 绘制函数是否发送了正确的值?console.log(x, y)在绘图功能中告诉我两者都是NaN

因此,随着一些console.log散布在周围,我发现发送到您的绘图函数的 X 和 Y 是NaN。所以在某个地方你做一些糟糕的数学。我将其追溯到_calculateSpeed您传入的构造函数中的方法,orbitPeriod但构造接受它 as @orbitPeriod,这当然是完全不同的事情。

class PlanetaryBody
    constructor: (@solarSystem, @name, @color, bodySize, orbitRadius = 0.0, @orbitPeriod = 0.0) ->
        @bodySize = solarSystem.normalizePlanetSize bodySize
        @orbitRadius = solarSystem.normalizeOrbitRadius orbitRadius

        # This line right here:
        @orbitSpeed = @_calculateSpeed orbitPeriod

        # Should be this instead!
        @orbitSpeed = @_calculateSpeed @orbitPeriod

        @planets = []

console.log是您的朋友,请将其添加到您认为数据混乱的地方,以便像专业人士一样进行调试。

于 2012-11-10T06:55:24.580 回答