为什么这个函数不能在setInterval循环之外找到?(javascript)

why this functions can't be found outside the setInterval loop? (javascript)

本文关键字:javascript 循环 函数 不能 setInterval 为什么      更新时间:2023-09-26

我使用planetaryjs包在js中绘制地球仪

有一个函数planetary.plugins.pings.add。它在这个循环中起作用:

setInterval(function() {
    var lat = 30.2500;
    var lng = 120.1667;
    var color = 'white';
    globe.plugins.pings.add(lng, lat, { color: color, ttl: 30000, angle: Math.random() * 10 });
}, 200);

但是我只想画一个ping,所以我选择

    var lat = 30.2500;
    var lng = 120.1667;
    var color = 'white';
    globe.plugins.pings.add(lng, lat, { color: color, ttl: 30000, angle: Math.random() * 10 });

但是firefox告诉我

TypeError: globe.plugins.pings is undefined
有谁知道这是为什么吗?完整的代码在这里(见第67-77行)。来源在这里
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script type='text/javascript' src='http://d3js.org/d3.v3.min.js'></script>
    <script type='text/javascript' src="http://d3js.org/topojson.v1.min.js"></script>
    <script type='text/javascript' src="http://labs.rivendellweb.net/data-vis/planetary/planetaryjs.js"></script>
  </head>
  <body>
    <canvas id='rotatingGlobe' width='800' height='600' style='width: 800px; height: 600px; cursor: move;'></canvas>
        <script>
            (function() {
                      var globe = planetaryjs.planet();
                      // Load our custom `autorotate` plugin; see below.
                      globe.loadPlugin(autorotate(0));
                      // The `earth` plugin draws the oceans and the land; it's actually
                      // a combination of several separate built-in plugins.
                      // Note that we're loading a special TopoJSON file
                      // (world-110m-withlakes.json) so we can render lakes.
                      globe.loadPlugin(planetaryjs.plugins.earth({
                        topojson: { file:   'world-110m-withlakes.json' },
                        oceans:   { fill:   '#000080' },
                        land:     { fill:   '#339966' },
                        borders:  { stroke: '#008000' }
                      }));
                      // Load our custom `lakes` plugin to draw lakes; see below.
                      globe.loadPlugin(lakes({
                        fill: '#000080'
                      }));
                      // The `pings` plugin draws animated pings on the globe.
                      globe.loadPlugin(planetaryjs.plugins.pings());
                      // The `zoom` and `drag` plugins enable
                      // manipulating the globe with the mouse.
                      globe.loadPlugin(planetaryjs.plugins.zoom({
                        scaleExtent: [100, 2000]
                      }));
                      globe.loadPlugin(planetaryjs.plugins.drag({
                        // Dragging the globe should pause the
                        // automatic rotation until we release the mouse.
                        onDragStart: function() {
                          this.plugins.autorotate.pause();
                        },
                        onDragEnd: function() {
                          this.plugins.autorotate.resume();
                        }
                      }));
                      // Set up the globe's initial scale, offset, and rotation.
                      globe.projection
                            .scale(400)
                            .translate([400, 300])
                            .rotate([-100, -30, 0]);
                      // Every few hundred milliseconds, we'll draw another random ping.
                      //var colors = ['red', 'yellow', 'white', 'orange', 'green', 'cyan', 'pink'];
                        setInterval(function() {
                            var lat = 30.2500;
                            var lng = 120.1667;
                            var color = 'white';
                            globe.plugins.pings.add(lng, lat, { color: color, ttl: 30000, angle: Math.random() * 10 });
                        }, 200);
                            var lat = 30.2500;
                            var lng = 120.1667;
                            var color = 'white';
                            globe.plugins.pings.add(lng, lat, { color: color, ttl: 30000, angle: Math.random() * 10 });
                      var canvas = document.getElementById('rotatingGlobe');
                      // Special code to handle high-density displays (e.g. retina, some phones)
                      // In the future, Planetary.js will handle this by itself (or via a plugin).
                      if (window.devicePixelRatio == 2) {
                        canvas.width = 800;
                        canvas.height = 800;
                        context = canvas.getContext('2d');
                        context.scale(2, 2);
                      }
                      // Draw that globe!
                      globe.draw(canvas);
                      // This plugin will automatically rotate the globe around its vertical
                      // axis a configured number of degrees every second.
                      function autorotate(degPerSec) {
                        // Planetary.js plugins are functions that take a `planet` instance
                        // as an argument...
                        return function(planet) {
                          var lastTick = null;
                          var paused = false;
                          planet.plugins.autorotate = {
                            pause:  function() { paused = true;  },
                            resume: function() { paused = false; }
                          };
                          // ...and configure hooks into certain pieces of its lifecycle.
                          planet.onDraw(function() {
                            if (paused || !lastTick) {
                              lastTick = new Date();
                            } else {
                              var now = new Date();
                              var delta = now - lastTick;
                              // This plugin uses the built-in projection (provided by D3)
                              // to rotate the globe each time we draw it.
                              var rotation = planet.projection.rotate();
                              rotation[0] += degPerSec * delta / 1000;
                              if (rotation[0] >= 180) rotation[0] -= 360;
                              planet.projection.rotate(rotation);
                              lastTick = now;
                            }
                          });
                        };
                      };
                      // This plugin takes lake data from the special
                      // TopoJSON we're loading and draws them on the map.
                      function lakes(options) {
                        options = options || {};
                        var lakes = null;
                        return function(planet) {
                          planet.onInit(function() {
                            // We can access the data loaded from the TopoJSON plugin
                            // on its namespace on `planet.plugins`. We're loading a custom
                            // TopoJSON file with an object called "ne_110m_lakes".
                            var world = planet.plugins.topojson.world;
                            lakes = topojson.feature(world, world.objects.ne_110m_lakes);
                          });
                          planet.onDraw(function() {
                            planet.withSavedContext(function(context) {
                              context.beginPath();
                              planet.path.context(context)(lakes);
                              context.fillStyle = options.fill || 'black';
                              context.fill();
                            });
                          });
                        };
                      };
                    })();

        </script>


  </body>
</html>

将setInterval替换为setTimeout。

直接调用失败的原因是global .plugins.ping在globe.draw(canvas);调用之后才初始化。你也可以把它移到后面。

与用代码块替换它相比,setTimeout将代码块的执行移动到执行队列的末尾,即直到global .draw(canvas)之后;,并初始化global .plugins.ping -但与setInterval不同,它只运行一次。

最好使用某种类型的回调,而不是仅仅响应随机超时。就像这样。planet.onInit( function([done]){} )

DOM在执行时没有初始化,您应该将初始化包装在document.addEventListener('DOMContentLoaded', function () { /* your code here */ });