我使用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行)。来源是here
<!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>
答案 0 :(得分:3)
用setTimeout替换setInterval。
直接调用失败的原因是global_plugins.pings在调用globe.draw(canvas);
之前未初始化。你也可以在此之后移动它。
与通过代码块替换它相比,setTimeout将代码块的执行移动到执行队列的末尾,即直到globe.draw(canvas)之后;调用并调整globe.plugins.pings - 但与setInterval不同,它只运行一次。
答案 1 :(得分:3)
最好使用某种回调而不是仅仅回复随机超时。
像这样的东西。
planet.onInit( function([done]){} )
答案 2 :(得分:1)
在执行时没有初始化DOM,你应该将初始化包装在document.addEventListener('DOMContentLoaded', function () { /* your code here */ });