android 3D球面的点,使用D3.js创建3D球面圆点环绕动画(带详细注解)
JavaScript
语言:
JaveScriptBabelCoffeeScript
确定
/**
* Create spherical spiral for given turns with almost same gap distance
* @see [Archimedean Spherical Spiral]{@link http://en.wikipedia.org/wiki/Spiral#Spherical_spiral}
* @param {number} turns - Times of turns around z-axis
* @param {number} [count=800] - Number of points on spiral
* @param {number} [radius=1] - Radius of sphere
* @returns {Point[]} - Points (r,θ,φ) of spiral in spherical coordinates
*/
function createSphericalSpiral(turns, count, radius) {
'use strict';
// Spherical coordinate system in mathematics
// (radial distance r, azimuthal angle θ, polar angle φ)
// @see [Spherical coordinate system]{@link http://en.wikipedia.org/wiki/Spherical_coordinate_system}
count = count || 800;
radius = radius || 1;
var step = 2 / count;
var phi, theta, point, points = [];
for (var i = -1; i <= 1; i += step) {
phi = Math.acos(i);
theta = 2 * turns * phi % (2 * Math.PI);
point = {
'radius': radius,
'theta': theta,
'phi': phi
};
points.push(point);
}
return points;
}
/**
* Convert from spherical coordinates (r,θ,φ) to Cartesian coordinates (x,y,z)
* @see {@link http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates}
* @param {{radius:number,theta:number,phi:number}} point - Point in spherical coordinates
* @returns {{x:number,y:number,z:number}} - Point in Cartesian coordinates
*/
function convert2xyz(point) {
'use strict';
var x = point.radius * Math.sin(point.phi) * Math.sin(point.theta);
var y = point.radius * Math.sin(point.phi) * Math.cos(point.theta);
var z = point.radius * Math.cos(point.phi);
return {
'x': x,
'y': y,
'z': z
};
}
// useage
// var spiral = createSphericalSpiral(10, 1000);
// spiralInXYZ = spiral.map(convert2xyz);
/**
* draw spherical spiral by d3 3.0
* load http://d3js.org/d3.v3.min.js first
*/
var spiral = createSphericalSpiral(10, 400);
function convert2GeoProjection(point) {
var longitude = point.theta * 180 / Math.PI;
var latitude = point.phi * 180 / Math.PI - 90;
return [longitude, latitude];
}
var width = 600,
height = 600,
speed = 0.01,
start = Date.now();
var canvas = d3.select('body').append('canvas')
.attr('width', width)
.attr('height', height);
var context = canvas.node().getContext('2d');
var projection = d3.geo.orthographic()
.scale(width / 2.2)
.clipAngle(90)
.translate([width / 2, height / 2])
.precision(0.5);
var path = d3.geo.path()
.projection(projection)
.context(context);
var sphere = {
type: 'Sphere'
};
var graticule = d3.geo.graticule();
var grid = graticule();
var spiralPositions = spiral.map(convert2GeoProjection);
var spiralLine = {
'type': 'LineString',
'coordinates': spiralPositions
};
var spiralMultiPoint = {
'type': 'MultiPoint',
'coordinates': spiralPositions
};
d3.timer(function() {
projection.rotate([speed * (Date.now() - start), -15, -10]);
context.clearRect(0, 0, width, height);
context.beginPath();
path(sphere);
context.fillStyle = '#fff';
context.fill();
context.beginPath();
path(grid);
context.lineWidth = 0.5;
context.strokeStyle = '#999';
context.stroke();
context.beginPath();
path(spiralLine);
context.lineWidth = 1.5;
context.strokeStyle = '#F00';
context.stroke();
context.beginPath();
path(spiralMultiPoint);
context.fillStyle = '#F00';
context.fill();
}, 1000);