Merge branch 'master' into default-namespace

This commit is contained in:
Mike Bostock 2011-11-23 12:44:49 -08:00
Родитель a35fc55410 2df8c62c14
Коммит cc3f5da0bb
194 изменённых файлов: 8695 добавлений и 1919 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -1,2 +1,3 @@
_site
node_modules
.DS_Store

4
.npmignore Normal file
Просмотреть файл

@ -0,0 +1,4 @@
examples/
test/
lib/
.DS_Store

Просмотреть файл

@ -1,23 +1,22 @@
# See the README for installation instructions.
JS_COMPILER = ./node_modules/uglify-js/bin/uglifyjs
JS_TESTER = ./node_modules/vows/bin/vows
NODE_PATH ?= ./node_modules
JS_COMPILER = $(NODE_PATH)/uglify-js/bin/uglifyjs
JS_TESTER = $(NODE_PATH)/vows/bin/vows
JS_FILES = \
d3.js \
d3.chart.js \
d3.layout.js \
d3.csv.js \
d3.geo.js \
d3.geom.js \
d3.time.js
all: \
d3.js \
d3.min.js \
d3.chart.js \
d3.chart.min.js \
d3.layout.js \
d3.layout.min.js \
d3.csv.js \
d3.csv.min.js \
d3.geo.js \
d3.geo.min.js \
d3.geom.js \
d3.geom.min.js \
d3.time.js \
d3.time.min.js
$(JS_FILES) \
$(JS_FILES:.js=.min.js) \
package.json
# Modify this rule to build your own custom release.
# Run `make d3.custom.min.js` to produce the minified version.
@ -36,17 +35,22 @@ d3.custom.js: \
src/end.js
d3.core.js: \
src/compat/date.js \
src/compat/style.js \
src/core/core.js \
src/core/date.js \
src/core/object.js \
src/core/array.js \
src/core/this.js \
src/core/functor.js \
src/core/rebind.js \
src/core/ascending.js \
src/core/descending.js \
src/core/mean.js \
src/core/median.js \
src/core/min.js \
src/core/max.js \
src/core/extent.js \
src/core/random.js \
src/core/number.js \
src/core/sum.js \
src/core/quantile.js \
src/core/zip.js \
@ -72,6 +76,7 @@ d3.core.js: \
src/core/ns.js \
src/core/dispatch.js \
src/core/format.js \
src/core/formatPrefix.js \
src/core/ease.js \
src/core/event.js \
src/core/interpolate.js \
@ -91,8 +96,6 @@ d3.core.js: \
src/core/selection-insert.js \
src/core/selection-remove.js \
src/core/selection-data.js \
src/core/selection-enter.js \
src/core/selection-enter-select.js \
src/core/selection-filter.js \
src/core/selection-map.js \
src/core/selection-sort.js \
@ -103,6 +106,8 @@ d3.core.js: \
src/core/selection-node.js \
src/core/selection-transition.js \
src/core/selection-root.js \
src/core/selection-enter.js \
src/core/selection-enter-select.js \
src/core/transition.js \
src/core/transition-select.js \
src/core/transition-selectAll.js \
@ -115,6 +120,7 @@ d3.core.js: \
src/core/transition-each.js \
src/core/transition-transition.js \
src/core/timer.js \
src/core/transform.js \
src/core/noop.js
d3.scale.js: \
@ -144,7 +150,8 @@ d3.svg.js: \
src/svg/mouse.js \
src/svg/touches.js \
src/svg/symbol.js \
src/svg/axis.js
src/svg/axis.js \
src/svg/brush.js
d3.behavior.js: \
src/behavior/behavior.js \
@ -182,9 +189,15 @@ d3.geo.js: \
src/geo/geo.js \
src/geo/azimuthal.js \
src/geo/albers.js \
src/geo/bonne.js \
src/geo/equirectangular.js \
src/geo/mercator.js \
src/geo/type.js \
src/geo/path.js \
src/geo/bounds.js \
src/geo/circle.js \
src/geo/greatArc.js \
src/geo/greatCircle.js \
src/end.js
d3.csv.js: \
@ -237,10 +250,17 @@ test: all
@rm -f $@
$(JS_COMPILER) < $< > $@
d3.js d3%.js: Makefile
d3.%: Makefile
@rm -f $@
cat $(filter %.js,$^) > $@
@chmod a-w $@
install:
mkdir -p node_modules
npm install
package.json: d3.js src/package.js
node src/package.js > $@
clean:
rm -f d3*.js

Просмотреть файл

@ -45,7 +45,7 @@ developing on Mac OS X, an easy way to install Node and NPM is using
Next, from the root directory of this repository, install D3's dependencies:
npm install
make install
You can see the list of dependencies in package.json. The packages will be
installed in the node_modules directory.
You can see the list of dependencies in package.json. NPM will install the
packages in the node_modules directory.

2
d3.chart.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

2
d3.csv.min.js поставляемый
Просмотреть файл

@ -1 +1 @@
(function(){function b(a){return/[",\n]/.test(a)?'"'+a.replace(/\"/g,'""')+'"':a}function a(a){return a.map(b).join(",")}d3.csv=function(a,b){d3.text(a,"text/csv",function(a){b(a&&d3.csv.parse(a))})},d3.csv.parse=function(a){var b;return d3.csv.parseRows(a,function(a,c){if(c){var d={},e=-1,f=b.length;while(++e<f)d[b[e]]=a[e];return d}b=a;return null})},d3.csv.parseRows=function(a,b){function j(){if(f.lastIndex>=a.length)return d;if(i){i=!1;return c}var b=f.lastIndex;if(a.charCodeAt(b)===34){var e=b;while(e++<a.length)if(a.charCodeAt(e)===34){if(a.charCodeAt(e+1)!==34)break;e++}f.lastIndex=e+2;var g=a.charCodeAt(e+1);g===13?(i=!0,a.charCodeAt(e+2)===10&&f.lastIndex++):g===10&&(i=!0);return a.substring(b+1,e).replace(/""/g,'"')}var h=f.exec(a);if(h){i=h[0].charCodeAt(0)!==44;return a.substring(b,h.index)}f.lastIndex=a.length;return a.substring(b)}var c={},d={},e=[],f=/\r\n|[,\r\n]/g,g=0,h,i;f.lastIndex=0;while((h=j())!==d){var k=[];while(h!==c&&h!==d)k.push(h),h=j();if(b&&!(k=b(k,g++)))continue;e.push(k)}return e},d3.csv.format=function(b){return b.map(a).join("\n")}})()
(function(){function a(a){return a.map(b).join(",")}function b(a){return/[",\n]/.test(a)?'"'+a.replace(/\"/g,'""')+'"':a}d3.csv=function(a,b){d3.text(a,"text/csv",function(a){b(a&&d3.csv.parse(a))})},d3.csv.parse=function(a){var b;return d3.csv.parseRows(a,function(a,c){if(c){var d={},e=-1,f=b.length;while(++e<f)d[b[e]]=a[e];return d}return b=a,null})},d3.csv.parseRows=function(a,b){function j(){if(f.lastIndex>=a.length)return d;if(i)return i=!1,c;var b=f.lastIndex;if(a.charCodeAt(b)===34){var e=b;while(e++<a.length)if(a.charCodeAt(e)===34){if(a.charCodeAt(e+1)!==34)break;e++}f.lastIndex=e+2;var g=a.charCodeAt(e+1);return g===13?(i=!0,a.charCodeAt(e+2)===10&&f.lastIndex++):g===10&&(i=!0),a.substring(b+1,e).replace(/""/g,'"')}var h=f.exec(a);return h?(i=h[0].charCodeAt(0)!==44,a.substring(b,h.index)):(f.lastIndex=a.length,a.substring(b))}var c={},d={},e=[],f=/\r\n|[,\r\n]/g,g=0,h,i;f.lastIndex=0;while((h=j())!==d){var k=[];while(h!==c&&h!==d)k.push(h),h=j();if(b&&!(k=b(k,g++)))continue;e.push(k)}return e},d3.csv.format=function(b){return b.map(a).join("\n")}})();

508
d3.geo.js
Просмотреть файл

@ -1,7 +1,9 @@
(function(){d3.geo = {};
var d3_geo_radians = Math.PI / 180;
// TODO clip input coordinates on opposite hemisphere
d3.geo.azimuthal = function() {
var mode = "orthographic", // or stereographic
var mode = "orthographic", // or stereographic, gnomonic, equidistant or equalarea
origin,
scale = 200,
translate = [480, 250],
@ -11,13 +13,19 @@ d3.geo.azimuthal = function() {
sy0;
function azimuthal(coordinates) {
var x1 = coordinates[0] * d3_radians - x0,
y1 = coordinates[1] * d3_radians,
var x1 = coordinates[0] * d3_geo_radians - x0,
y1 = coordinates[1] * d3_geo_radians,
cx1 = Math.cos(x1),
sx1 = Math.sin(x1),
cy1 = Math.cos(y1),
sy1 = Math.sin(y1),
k = mode == "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1,
cc = mode !== "orthographic" ? sy0 * sy1 + cy0 * cy1 * cx1 : null,
c,
k = mode === "stereographic" ? 1 / (1 + cc)
: mode === "gnomonic" ? 1 / cc
: mode === "equidistant" ? (c = Math.acos(cc), c ? c / Math.sin(c) : 0)
: mode === "equalarea" ? Math.sqrt(2 / (1 + cc))
: 1,
x = k * cy1 * sx1,
y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
return [
@ -26,17 +34,34 @@ d3.geo.azimuthal = function() {
];
}
azimuthal.invert = function(coordinates) {
var x = (coordinates[0] - translate[0]) / scale,
y = (coordinates[1] - translate[1]) / scale,
p = Math.sqrt(x * x + y * y),
c = mode === "stereographic" ? 2 * Math.atan(p)
: mode === "gnomonic" ? Math.atan(p)
: mode === "equidistant" ? p
: mode === "equalarea" ? 2 * Math.asin(.5 * p)
: Math.asin(p),
sc = Math.sin(c),
cc = Math.cos(c);
return [
(x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_geo_radians,
Math.asin(cc * sy0 - (p ? (y * sc * cy0) / p : 0)) / d3_geo_radians
];
};
azimuthal.mode = function(x) {
if (!arguments.length) return mode;
mode = x;
mode = x + "";
return azimuthal;
};
azimuthal.origin = function(x) {
if (!arguments.length) return origin;
origin = x;
x0 = origin[0] * d3_radians;
y0 = origin[1] * d3_radians;
x0 = origin[0] * d3_geo_radians;
y0 = origin[1] * d3_geo_radians;
cy0 = Math.cos(y0);
sy0 = Math.sin(y0);
return azimuthal;
@ -65,27 +90,39 @@ d3.geo.albers = function() {
parallels = [29.5, 45.5],
scale = 1000,
translate = [480, 250],
lng0, // d3_radians * origin[0]
lng0, // d3_geo_radians * origin[0]
n,
C,
p0;
function albers(coordinates) {
var t = n * (d3_radians * coordinates[0] - lng0),
p = Math.sqrt(C - 2 * n * Math.sin(d3_radians * coordinates[1])) / n;
var t = n * (d3_geo_radians * coordinates[0] - lng0),
p = Math.sqrt(C - 2 * n * Math.sin(d3_geo_radians * coordinates[1])) / n;
return [
scale * p * Math.sin(t) + translate[0],
scale * (p * Math.cos(t) - p0) + translate[1]
];
}
albers.invert = function(coordinates) {
var x = (coordinates[0] - translate[0]) / scale,
y = (coordinates[1] - translate[1]) / scale,
p0y = p0 + y,
t = Math.atan2(x, p0y),
p = Math.sqrt(x * x + p0y * p0y);
return [
(lng0 + t / n) / d3_geo_radians,
Math.asin((C - p * p * n * n) / (2 * n)) / d3_geo_radians
];
};
function reload() {
var phi1 = d3_radians * parallels[0],
phi2 = d3_radians * parallels[1],
lat0 = d3_radians * origin[1],
var phi1 = d3_geo_radians * parallels[0],
phi2 = d3_geo_radians * parallels[1],
lat0 = d3_geo_radians * origin[1],
s = Math.sin(phi1),
c = Math.cos(phi1);
lng0 = d3_radians * origin[0];
lng0 = d3_geo_radians * origin[0];
n = .5 * (s + Math.sin(phi2));
C = c * c + 2 * n * s;
p0 = Math.sqrt(C - 2 * n * Math.sin(lat0)) / n;
@ -170,21 +207,134 @@ d3.geo.albersUsa = function() {
return albersUsa.scale(lower48.scale());
};
d3.geo.bonne = function() {
var scale = 200,
translate = [480, 250],
x0, // origin longitude in radians
y0, // origin latitude in radians
y1, // parallel latitude in radians
c1; // cot(y1)
var d3_radians = Math.PI / 180;
function bonne(coordinates) {
var x = coordinates[0] * d3_geo_radians - x0,
y = coordinates[1] * d3_geo_radians - y0;
if (y1) {
var p = c1 + y1 - y, E = x * Math.cos(y) / p;
x = p * Math.sin(E);
y = p * Math.cos(E) - c1;
} else {
x *= Math.cos(y);
y *= -1;
}
return [
scale * x + translate[0],
scale * y + translate[1]
];
}
bonne.invert = function(coordinates) {
var x = (coordinates[0] - translate[0]) / scale,
y = (coordinates[1] - translate[1]) / scale;
if (y1) {
var c = c1 + y, p = Math.sqrt(x * x + c * c);
y = c1 + y1 - p;
x = x0 + p * Math.atan2(x, c) / Math.cos(y);
} else {
y *= -1;
x /= Math.cos(y);
}
return [
x / d3_geo_radians,
y / d3_geo_radians
];
};
// 90° for Werner, 0° for Sinusoidal
bonne.parallel = function(x) {
if (!arguments.length) return y1 / d3_geo_radians;
c1 = 1 / Math.tan(y1 = x * d3_geo_radians);
return bonne;
};
bonne.origin = function(x) {
if (!arguments.length) return [x0 / d3_geo_radians, y0 / d3_geo_radians];
x0 = x[0] * d3_geo_radians;
y0 = x[1] * d3_geo_radians;
return bonne;
};
bonne.scale = function(x) {
if (!arguments.length) return scale;
scale = +x;
return bonne;
};
bonne.translate = function(x) {
if (!arguments.length) return translate;
translate = [+x[0], +x[1]];
return bonne;
};
return bonne.origin([0, 0]).parallel(45);
};
d3.geo.equirectangular = function() {
var scale = 500,
translate = [480, 250];
function equirectangular(coordinates) {
var x = coordinates[0] / 360,
y = -coordinates[1] / 360;
return [
scale * x + translate[0],
scale * y + translate[1]
];
}
equirectangular.invert = function(coordinates) {
var x = (coordinates[0] - translate[0]) / scale,
y = (coordinates[1] - translate[1]) / scale;
return [
360 * x,
-360 * y
];
};
equirectangular.scale = function(x) {
if (!arguments.length) return scale;
scale = +x;
return equirectangular;
};
equirectangular.translate = function(x) {
if (!arguments.length) return translate;
translate = [+x[0], +x[1]];
return equirectangular;
};
return equirectangular;
};
d3.geo.mercator = function() {
var scale = 500,
translate = [480, 250];
function mercator(coordinates) {
var x = (coordinates[0]) / 360,
y = (-180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + coordinates[1] * Math.PI / 360))) / 360;
var x = coordinates[0] / 360,
y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_geo_radians / 2)) / d3_geo_radians) / 360;
return [
scale * x + translate[0],
scale * Math.max(-.5, Math.min(.5, y)) + translate[1]
];
}
mercator.invert = function(coordinates) {
var x = (coordinates[0] - translate[0]) / scale,
y = (coordinates[1] - translate[1]) / scale;
return [
360 * x,
2 * Math.atan(Math.exp(-360 * y * d3_geo_radians)) / d3_geo_radians - 90
];
};
mercator.scale = function(x) {
if (!arguments.length) return scale;
scale = +x;
@ -199,6 +349,11 @@ d3.geo.mercator = function() {
return mercator;
};
function d3_geo_type(types, defaultValue) {
return function(object) {
return object && object.type in types ? types[object.type](object) : defaultValue;
};
}
/**
* Returns a function that, given a GeoJSON object (e.g., a feature), returns
* the corresponding SVG path. The function can be customized by overriding the
@ -215,26 +370,26 @@ d3.geo.path = function() {
if (typeof pointRadius === "function") {
pointCircle = d3_path_circle(pointRadius.apply(this, arguments));
}
return d3_geo_pathType(pathTypes, d);
return pathType(d) || null;
}
function project(coordinates) {
return projection(coordinates).join(",");
}
var pathTypes = {
var pathType = d3_geo_type({
FeatureCollection: function(f) {
FeatureCollection: function(o) {
var path = [],
features = f.features,
features = o.features,
i = -1, // features.index
n = features.length;
while (++i < n) path.push(d3_geo_pathType(pathTypes, features[i].geometry));
while (++i < n) path.push(pathType(features[i].geometry));
return path.join("");
},
Feature: function(f) {
return d3_geo_pathType(pathTypes, f.geometry);
Feature: function(o) {
return pathType(o.geometry);
},
Point: function(o) {
@ -290,10 +445,11 @@ d3.geo.path = function() {
while (++i < n) {
subcoordinates = coordinates[i];
j = -1;
m = subcoordinates.length;
path.push("M");
while (++j < m) path.push(project(subcoordinates[j]), "L");
path[path.length - 1] = "Z";
if ((m = subcoordinates.length - 1) > 0) {
path.push("M");
while (++j < m) path.push(project(subcoordinates[j]), "L");
path[path.length - 1] = "Z";
}
}
return path.join("");
},
@ -316,10 +472,11 @@ d3.geo.path = function() {
while (++j < m) {
subsubcoordinates = subcoordinates[j];
k = -1;
p = subsubcoordinates.length - 1;
path.push("M");
while (++k < p) path.push(project(subsubcoordinates[k]), "L");
path[path.length - 1] = "Z";
if ((p = subsubcoordinates.length - 1) > 0) {
path.push("M");
while (++k < p) path.push(project(subsubcoordinates[k]), "L");
path[path.length - 1] = "Z";
}
}
}
return path.join("");
@ -330,32 +487,27 @@ d3.geo.path = function() {
geometries = o.geometries,
i = -1, // geometries index
n = geometries.length;
while (++i < n) path.push(d3_geo_pathType(pathTypes, geometries[i]));
while (++i < n) path.push(pathType(geometries[i]));
return path.join("");
}
};
});
var areaTypes = {
var areaType = path.area = d3_geo_type({
FeatureCollection: function(f) {
FeatureCollection: function(o) {
var area = 0,
features = f.features,
features = o.features,
i = -1, // features.index
n = features.length;
while (++i < n) area += d3_geo_pathType(areaTypes, features[i]);
while (++i < n) area += areaType(features[i]);
return area;
},
Feature: function(f) {
return d3_geo_pathType(areaTypes, f.geometry);
Feature: function(o) {
return areaType(o.geometry);
},
Point: d3_geo_pathZero,
MultiPoint: d3_geo_pathZero,
LineString: d3_geo_pathZero,
MultiLineString: d3_geo_pathZero,
Polygon: function(o) {
return polygonArea(o.coordinates);
},
@ -374,11 +526,11 @@ d3.geo.path = function() {
geometries = o.geometries,
i = -1, // geometries index
n = geometries.length;
while (++i < n) sum += d3_geo_pathType(areaTypes, geometries[i]);
while (++i < n) sum += areaType(geometries[i]);
return sum;
}
};
}, 0);
function polygonArea(coordinates) {
var sum = area(coordinates[0]), // exterior ring
@ -390,23 +542,25 @@ d3.geo.path = function() {
function polygonCentroid(coordinates) {
var polygon = d3.geom.polygon(coordinates[0].map(projection)), // exterior ring
centroid = polygon.centroid(1),
area = polygon.area(),
centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1),
x = centroid[0],
y = centroid[1],
z = Math.abs(polygon.area()),
z = area,
i = 0, // coordinates index
n = coordinates.length;
while (++i < n) {
polygon = d3.geom.polygon(coordinates[i].map(projection)); // holes
centroid = polygon.centroid(1);
area = polygon.area();
centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1);
x -= centroid[0];
y -= centroid[1];
z -= Math.abs(polygon.area());
z -= area;
}
return [x, y, 6 * z]; // weighted centroid
}
var centroidTypes = {
var centroidType = path.centroid = d3_geo_type({
// TODO FeatureCollection
// TODO Point
@ -415,8 +569,8 @@ d3.geo.path = function() {
// TODO MultiLineString
// TODO GeometryCollection
Feature: function(f) {
return d3_geo_pathType(centroidTypes, f.geometry);
Feature: function(o) {
return centroidType(o.geometry);
},
Polygon: function(o) {
@ -442,8 +596,7 @@ d3.geo.path = function() {
return [x / z, y / z];
}
};
});
function area(coordinates) {
return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
@ -454,14 +607,6 @@ d3.geo.path = function() {
return path;
};
path.area = function(d) {
return d3_geo_pathType(areaTypes, d);
};
path.centroid = function(d) {
return d3_geo_pathType(centroidTypes, d);
};
path.pointRadius = function(x) {
if (typeof x === "function") pointRadius = x;
else {
@ -480,14 +625,6 @@ function d3_path_circle(radius) {
+ "a" + radius + "," + radius + " 0 1,1 0," + (+2 * radius)
+ "z";
}
function d3_geo_pathZero() {
return 0;
}
function d3_geo_pathType(types, o) {
return o && o.type in types ? types[o.type](o) : "";
}
/**
* Given a GeoJSON object, returns the corresponding bounding box. The bounding
* box is represented by a two-dimensional array: [[left, bottom], [right,
@ -564,4 +701,231 @@ function d3_geo_boundsPolygon(o, f) {
f.apply(null, a[i]);
}
}
// TODO breakAtDateLine?
d3.geo.circle = function() {
var origin = [0, 0],
degrees = 90 - 1e-2,
radians = degrees * d3_geo_radians,
arc = d3.geo.greatArc().target(Object);
function circle() {
// TODO render a circle as a Polygon
}
function visible(point) {
return arc.distance(point) < radians;
}
circle.clip = function(d) {
arc.source(typeof origin === "function" ? origin.apply(this, arguments) : origin);
return clipType(d);
};
var clipType = d3_geo_type({
FeatureCollection: function(o) {
var features = o.features.map(clipType).filter(Object);
return features && (o = Object.create(o), o.features = features, o);
},
Feature: function(o) {
var geometry = clipType(o.geometry);
return geometry && (o = Object.create(o), o.geometry = geometry, o);
},
Point: function(o) {
return visible(o.coordinates) && o;
},
MultiPoint: function(o) {
var coordinates = o.coordinates.filter(visible);
return coordinates.length && {
type: o.type,
coordinates: coordinates
};
},
LineString: function(o) {
var coordinates = clip(o.coordinates);
return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
},
MultiLineString: function(o) {
var coordinates = o.coordinates.map(clip).filter(function(d) { return d.length; });
return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
},
Polygon: function(o) {
var coordinates = o.coordinates.map(clip);
return coordinates[0].length && (o = Object.create(o), o.coordinates = coordinates, o);
},
MultiPolygon: function(o) {
var coordinates = o.coordinates.map(function(d) { return d.map(clip); }).filter(function(d) { return d[0].length; });
return coordinates.length && (o = Object.create(o), o.coordinates = coordinates, o);
},
GeometryCollection: function(o) {
var geometries = o.geometries.map(clipType).filter(Object);
return geometries.length && (o = Object.create(o), o.geometries = geometries, o);
}
});
function clip(coordinates) {
var i = -1,
n = coordinates.length,
clipped = [],
p0,
p1,
p2,
d0,
d1;
while (++i < n) {
d1 = arc.distance(p2 = coordinates[i]);
if (d1 < radians) {
if (p1) clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1)));
clipped.push(p2);
p0 = p1 = null;
} else {
p1 = p2;
if (!p0 && clipped.length) {
clipped.push(d3_geo_greatArcInterpolate(clipped[clipped.length - 1], p1)((radians - d0) / (d1 - d0)));
p0 = p1;
}
}
d0 = d1;
}
if (p1 && clipped.length) {
d1 = arc.distance(p2 = clipped[0]);
clipped.push(d3_geo_greatArcInterpolate(p1, p2)((d0 - radians) / (d0 - d1)));
}
return resample(clipped);
}
// Resample coordinates, creating great arcs between each.
function resample(coordinates) {
var i = 0,
n = coordinates.length,
j,
m,
resampled = n ? [coordinates[0]] : coordinates,
resamples,
origin = arc.source();
while (++i < n) {
resamples = arc.source(coordinates[i - 1])(coordinates[i]).coordinates;
for (j = 0, m = resamples.length; ++j < m;) resampled.push(resamples[j]);
}
arc.source(origin);
return resampled;
}
circle.origin = function(x) {
if (!arguments.length) return origin;
origin = x;
return circle;
};
circle.angle = function(x) {
if (!arguments.length) return degrees;
radians = (degrees = +x) * d3_geo_radians;
return circle;
};
// Precision is specified in degrees.
circle.precision = function(x) {
if (!arguments.length) return arc.precision();
arc.precision(x);
return circle;
};
return circle;
}
d3.geo.greatArc = function() {
var source = d3_geo_greatArcSource,
target = d3_geo_greatArcTarget,
precision = 6 * d3_geo_radians;
function greatArc() {
var a = typeof source === "function" ? source.apply(this, arguments) : source,
b = typeof target === "function" ? target.apply(this, arguments) : target,
i = d3_geo_greatArcInterpolate(a, b),
dt = precision / i.d,
t = 0,
coordinates = [a];
while ((t += dt) < 1) coordinates.push(i(t));
coordinates.push(b);
return {
type: "LineString",
coordinates: coordinates
};
}
// Length returned in radians; multiply by radius for distance.
greatArc.distance = function() {
var a = typeof source === "function" ? source.apply(this, arguments) : source,
b = typeof target === "function" ? target.apply(this, arguments) : target;
return d3_geo_greatArcInterpolate(a, b).d;
};
greatArc.source = function(x) {
if (!arguments.length) return source;
source = x;
return greatArc;
};
greatArc.target = function(x) {
if (!arguments.length) return target;
target = x;
return greatArc;
};
// Precision is specified in degrees.
greatArc.precision = function(x) {
if (!arguments.length) return precision / d3_geo_radians;
precision = x * d3_geo_radians;
return greatArc;
};
return greatArc;
};
function d3_geo_greatArcSource(d) {
return d.source;
}
function d3_geo_greatArcTarget(d) {
return d.target;
}
function d3_geo_greatArcInterpolate(a, b) {
var x0 = a[0] * d3_geo_radians, cx0 = Math.cos(x0), sx0 = Math.sin(x0),
y0 = a[1] * d3_geo_radians, cy0 = Math.cos(y0), sy0 = Math.sin(y0),
x1 = b[0] * d3_geo_radians, cx1 = Math.cos(x1), sx1 = Math.sin(x1),
y1 = b[1] * d3_geo_radians, cy1 = Math.cos(y1), sy1 = Math.sin(y1),
d = interpolate.d = Math.acos(Math.max(-1, Math.min(1, sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)))),
sd = Math.sin(d);
// From http://williams.best.vwh.net/avform.htm#Intermediate
function interpolate(t) {
var A = Math.sin(d - (t *= d)) / sd,
B = Math.sin(t) / sd,
x = A * cy0 * cx0 + B * cy1 * cx1,
y = A * cy0 * sx0 + B * cy1 * sx1,
z = A * sy0 + B * sy1;
return [
Math.atan2(y, x) / d3_geo_radians,
Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_geo_radians
];
}
return interpolate;
}
d3.geo.greatCircle = d3.geo.circle;
})();

2
d3.geo.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -198,7 +198,7 @@ d3.geom.polygon = function(coordinates) {
a,
b,
c;
if (!arguments.length) k = 1 / (6 * coordinates.area());
if (!arguments.length) k = -1 / (6 * coordinates.area());
while (++i < n) {
a = coordinates[i];
b = coordinates[i + 1];
@ -268,6 +268,17 @@ function d3_geom_polygonIntersect(c, d, a, b) {
// http://blog.thejit.org/assets/voronoijs/voronoi.js
// See lib/jit/LICENSE for details.
// Notes:
//
// This implementation does not clip the returned polygons, so if you want to
// clip them to a particular shape you will need to do that either in SVG or by
// post-processing with d3.geom.polygon's clip method.
//
// If any vertices are coincident or have NaN positions, the behavior of this
// method is undefined. Most likely invalid polygons will be returned. You
// should filter invalid points, and consolidate coincident points, before
// computing the tessellation.
/**
* @param vertices [[x1, y1], [x2, y2], ]
* @returns polygons [[[x1, y1], [x2, y2], ], ]
@ -275,7 +286,6 @@ function d3_geom_polygonIntersect(c, d, a, b) {
d3.geom.voronoi = function(vertices) {
var polygons = vertices.map(function() { return []; });
// Note: we expect the caller to clip the polygons, if needed.
d3_voronoi_tessellate(vertices, function(e) {
var s1,
s2,

2
d3.geom.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

1182
d3.js поставляемый

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -113,16 +113,19 @@ d3.layout.chord = function() {
k = (2 * Math.PI - padding * n) / k;
// Compute the start and end angle for each group and subgroup.
// Note: Opera has a bug reordering object literal properties!
x = 0, i = -1; while (++i < n) {
x0 = x, j = -1; while (++j < n) {
var di = groupIndex[i],
dj = subgroupIndex[i][j],
v = matrix[di][dj];
dj = subgroupIndex[di][j],
v = matrix[di][dj],
a0 = x,
a1 = x += v * k;
subgroups[di + "-" + dj] = {
index: di,
subindex: dj,
startAngle: x,
endAngle: x += v * k,
startAngle: a0,
endAngle: a1,
value: v
};
}
@ -153,7 +156,9 @@ d3.layout.chord = function() {
function resort() {
chords.sort(function(a, b) {
return sortChords(a.target.value, b.target.value);
return sortChords(
(a.source.value + a.target.value) / 2,
(b.source.value + b.target.value) / 2);
});
}
@ -221,9 +226,10 @@ d3.layout.force = function() {
nodes = [],
links = [],
distances,
strengths;
strengths,
charges;
function repulse(node, kc) {
function repulse(node) {
return function(quad, x1, y1, x2, y2) {
if (quad.point !== node) {
var dx = quad.cx - node.x,
@ -232,30 +238,32 @@ d3.layout.force = function() {
/* Barnes-Hut criterion. */
if ((x2 - x1) * dn < theta) {
var k = kc * quad.count * dn * dn;
node.x += dx * k;
node.y += dy * k;
var k = quad.charge * dn * dn;
node.px -= dx * k;
node.py -= dy * k;
return true;
}
if (quad.point && isFinite(dn)) {
var k = kc * dn * dn;
node.x += dx * k;
node.y += dy * k;
var k = quad.pointCharge * dn * dn;
node.px -= dx * k;
node.py -= dy * k;
}
}
return !quad.charge;
};
}
function tick() {
var n = nodes.length,
m = links.length,
q = d3.geom.quadtree(nodes),
q,
i, // current index
o, // current object
s, // current source
t, // current target
l, // current distance
k, // current force
x, // x-distance
y; // y-distance
@ -270,30 +278,32 @@ d3.layout.force = function() {
l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
x *= l;
y *= l;
t.x -= x / t.weight;
t.y -= y / t.weight;
s.x += x / s.weight;
s.y += y / s.weight;
t.x -= x * (k = s.weight / (t.weight + s.weight));
t.y -= y * k;
s.x += x * (k = 1 - k);
s.y += y * k;
}
}
// apply gravity forces
var kg = alpha * gravity;
x = size[0] / 2;
y = size[1] / 2;
i = -1; while (++i < n) {
o = nodes[i];
o.x += (x - o.x) * kg;
o.y += (y - o.y) * kg;
if (k = alpha * gravity) {
x = size[0] / 2;
y = size[1] / 2;
i = -1; if (k) while (++i < n) {
o = nodes[i];
o.x += (x - o.x) * k;
o.y += (y - o.y) * k;
}
}
// compute quadtree center of mass
d3_layout_forceAccumulate(q);
// apply charge forces
var kc = alpha * charge;
i = -1; while (++i < n) {
q.visit(repulse(nodes[i], kc));
// compute quadtree center of mass and apply charge forces
if (charge) {
d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
i = -1; while (++i < n) {
if (!(o = nodes[i]).fixed) {
q.visit(repulse(o));
}
}
}
// position verlet integration
@ -308,17 +318,12 @@ d3.layout.force = function() {
}
}
event.tick.dispatch({type: "tick", alpha: alpha});
event.tick({type: "tick", alpha: alpha});
// simulated annealing, basically
return (alpha *= .99) < .005;
}
force.on = function(type, listener) {
event[type].add(listener);
return force;
};
force.nodes = function(x) {
if (!arguments.length) return nodes;
nodes = x;
@ -360,7 +365,7 @@ d3.layout.force = function() {
force.charge = function(x) {
if (!arguments.length) return charge;
charge = x;
charge = typeof x === "function" ? x : +x;
return force;
};
@ -411,6 +416,17 @@ d3.layout.force = function() {
if (isNaN(o.py)) o.py = o.y;
}
charges = [];
if (typeof charge === "function") {
for (i = 0; i < n; ++i) {
charges[i] = +charge.call(this, nodes[i], i);
}
} else {
for (i = 0; i < n; ++i) {
charges[i] = charge;
}
}
// initialize node position based on first neighbor
function position(dimension, size) {
var neighbors = neighbor(i),
@ -468,7 +484,7 @@ d3.layout.force = function() {
d3_layout_forceDragForce = force;
}
return force;
return d3.rebind(force, event, "on");
};
var d3_layout_forceDragForce,
@ -494,10 +510,10 @@ function d3_layout_forceDrag() {
d3_layout_forceDragForce.resume(); // restart annealing
}
function d3_layout_forceAccumulate(quad) {
function d3_layout_forceAccumulate(quad, alpha, charges) {
var cx = 0,
cy = 0;
quad.count = 0;
quad.charge = 0;
if (!quad.leaf) {
var nodes = quad.nodes,
n = nodes.length,
@ -506,10 +522,10 @@ function d3_layout_forceAccumulate(quad) {
while (++i < n) {
c = nodes[i];
if (c == null) continue;
d3_layout_forceAccumulate(c);
quad.count += c.count;
cx += c.count * c.cx;
cy += c.count * c.cy;
d3_layout_forceAccumulate(c, alpha, charges);
quad.charge += c.charge;
cx += c.charge * c.cx;
cy += c.charge * c.cy;
}
}
if (quad.point) {
@ -518,12 +534,13 @@ function d3_layout_forceAccumulate(quad) {
quad.point.x += Math.random() - .5;
quad.point.y += Math.random() - .5;
}
quad.count++;
cx += quad.point.x;
cy += quad.point.y;
var k = alpha * charges[quad.point.index];
quad.charge += quad.pointCharge = k;
cx += k * quad.point.x;
cy += k * quad.point.y;
}
quad.cx = cx / quad.count;
quad.cy = cy / quad.count;
quad.cx = cx / quad.charge;
quad.cy = cy / quad.charge;
}
function d3_layout_forceLinkDistance(link) {
@ -543,9 +560,9 @@ d3.layout.partition = function() {
node.y = node.depth * dy;
node.dx = dx;
node.dy = dy;
if (children) {
if (children && (n = children.length)) {
var i = -1,
n = children.length,
n,
c,
d;
dx = node.value ? dx / node.value : 0;
@ -559,9 +576,9 @@ d3.layout.partition = function() {
function depth(node) {
var children = node.children,
d = 0;
if (children) {
if (children && (n = children.length)) {
var i = -1,
n = children.length;
n;
while (++i < n) d = Math.max(d, depth(children[i]));
}
return 1 + d;
@ -583,33 +600,31 @@ d3.layout.partition = function() {
};
d3.layout.pie = function() {
var value = Number,
sort = null,
sort = d3_layout_pieSortByValue,
startAngle = 0,
endAngle = 2 * Math.PI;
function pie(data, i) {
// Compute the numeric values for each data element.
var values = data.map(function(d, i) { return +value.call(pie, d, i); });
// Compute the start angle.
var a = +(typeof startAngle === "function"
? startAngle.apply(this, arguments)
: startAngle);
// Compute the angular range (end - start).
var k = (typeof endAngle === "function"
// Compute the angular scale factor: from value to radians.
var k = ((typeof endAngle === "function"
? endAngle.apply(this, arguments)
: endAngle) - startAngle;
: endAngle) - startAngle)
/ d3.sum(values);
// Optionally sort the data.
var index = d3.range(data.length);
if (sort != null) index.sort(function(i, j) {
return sort(data[i], data[j]);
});
// Compute the numeric values for each data element.
var values = data.map(value);
// Convert k into a scale factor from value to angle, using the sum.
k /= values.reduce(function(p, d) { return p + d; }, 0);
if (sort != null) index.sort(sort === d3_layout_pieSortByValue
? function(i, j) { return values[j] - values[i]; }
: function(i, j) { return sort(data[i], data[j]); });
// Compute the arcs!
var arcs = index.map(function(i) {
@ -676,6 +691,8 @@ d3.layout.pie = function() {
return pie;
};
var d3_layout_pieSortByValue = {};
// data is two-dimensional array of x,y; we populate y0
d3.layout.stack = function() {
var values = Object,
@ -1027,9 +1044,9 @@ d3.layout.hierarchy = function() {
node = d3_layout_hierarchyInline ? data : {data: data};
node.depth = depth;
nodes.push(node);
if (childs) {
if (childs && (n = childs.length)) {
var i = -1,
n = childs.length,
n,
c = node.children = [],
v = 0,
j = depth + 1;
@ -1051,9 +1068,9 @@ d3.layout.hierarchy = function() {
function revalue(node, depth) {
var children = node.children,
v = 0;
if (children) {
if (children && (n = children.length)) {
var i = -1,
n = children.length,
n,
j = depth + 1;
while (++i < n) v += revalue(children[i], j);
} else if (value) {
@ -1098,10 +1115,10 @@ d3.layout.hierarchy = function() {
// A method assignment helper for hierarchy subclasses.
function d3_layout_hierarchyRebind(object, hierarchy) {
object.sort = d3.rebind(object, hierarchy.sort);
object.children = d3.rebind(object, hierarchy.children);
d3.rebind(object, hierarchy, "sort", "children", "value");
// Add an alias for links, for convenience.
object.links = d3_layout_hierarchyLinks;
object.value = d3.rebind(object, hierarchy.value);
// If the new API is used, enabling inlining.
object.nodes = function(d) {
@ -1301,7 +1318,7 @@ function d3_layout_packUnlink(node) {
function d3_layout_packTree(node) {
var children = node.children;
if (children) {
if (children && children.length) {
children.forEach(d3_layout_packTree);
node.r = d3_layout_packCircle(children);
} else {
@ -1321,19 +1338,22 @@ function d3_layout_packTransform(node, x, y, k) {
}
function d3_layout_packPlace(a, b, c) {
var da = b.r + c.r,
db = a.r + c.r,
var db = a.r + c.r,
dx = b.x - a.x,
dy = b.y - a.y,
dc = Math.sqrt(dx * dx + dy * dy),
cos = (db * db + dc * dc - da * da) / (2 * db * dc),
theta = Math.acos(cos),
x = cos * db,
h = Math.sin(theta) * db;
dx /= dc;
dy /= dc;
c.x = a.x + x * dx + h * dy;
c.y = a.y + x * dy - h * dx;
dy = b.y - a.y;
if (db && (dx || dy)) {
var da = b.r + c.r,
dc = Math.sqrt(dx * dx + dy * dy),
cos = Math.max(-1, Math.min(1, (db * db + dc * dc - da * da) / (2 * db * dc))),
theta = Math.acos(cos),
x = cos * (db /= dc),
y = Math.sin(theta) * db;
c.x = a.x + x * dx + y * dy;
c.y = a.y + x * dy - y * dx;
} else {
c.x = a.x + db;
c.y = a.y;
}
}
// Implements a hierarchical layout using the cluster (or dendogram) algorithm.
d3.layout.cluster = function() {
@ -1351,9 +1371,10 @@ d3.layout.cluster = function() {
// First walk, computing the initial x & y values.
d3_layout_treeVisitAfter(root, function(node) {
if (node.children) {
node.x = d3_layout_clusterX(node.children);
node.y = d3_layout_clusterY(node.children);
var children = node.children;
if (children && children.length) {
node.x = d3_layout_clusterX(children);
node.y = d3_layout_clusterY(children);
} else {
node.x = previousNode ? x += separation(node, previousNode) : 0;
node.y = 0;
@ -1405,12 +1426,12 @@ function d3_layout_clusterX(children) {
function d3_layout_clusterLeft(node) {
var children = node.children;
return children ? d3_layout_clusterLeft(children[0]) : node;
return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
}
function d3_layout_clusterRight(node) {
var children = node.children;
return children ? d3_layout_clusterRight(children[children.length - 1]) : node;
var children = node.children, n;
return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
}
// Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
d3.layout.tree = function() {
@ -1456,9 +1477,9 @@ d3.layout.tree = function() {
function secondWalk(node, x) {
node.x = node._tree.prelim + x;
var children = node.children;
if (children) {
if (children && (n = children.length)) {
var i = -1,
n = children.length;
n;
x += node._tree.mod;
while (++i < n) {
secondWalk(children[i], x);
@ -1563,18 +1584,21 @@ function d3_layout_treeSeparation(a, b) {
// }
function d3_layout_treeLeft(node) {
return node.children ? node.children[0] : node._tree.thread;
var children = node.children;
return children && children.length ? children[0] : node._tree.thread;
}
function d3_layout_treeRight(node) {
return node.children ? node.children[node.children.length - 1] : node._tree.thread;
var children = node.children,
n;
return children && (n = children.length) ? children[n - 1] : node._tree.thread;
}
function d3_layout_treeSearch(node, compare) {
var children = node.children;
if (children) {
if (children && (n = children.length)) {
var child,
n = children.length,
n,
i = -1;
while (++i < n) {
if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
@ -1600,11 +1624,11 @@ function d3_layout_treeDeepest(a, b) {
function d3_layout_treeVisitAfter(node, callback) {
function visit(node, previousSibling) {
var children = node.children;
if (children) {
if (children && (n = children.length)) {
var child,
previousChild = null,
i = -1,
n = children.length;
n;
while (++i < n) {
child = children[i];
visit(child, previousChild);
@ -1672,57 +1696,61 @@ d3.layout.treemap = function() {
// Recursively arranges the specified node's children into squarified rows.
function squarify(node) {
if (!node.children) return;
var rect = pad(node),
row = [],
children = node.children.slice(), // copy-on-write
child,
best = Infinity, // the best row score so far
score, // the current row score
u = Math.min(rect.dx, rect.dy), // initial orientation
n;
scale(children, rect.dx * rect.dy / node.value);
row.area = 0;
while ((n = children.length) > 0) {
row.push(child = children[n - 1]);
row.area += child.area;
if ((score = worst(row, u)) <= best) { // continue with this orientation
children.pop();
best = score;
} else { // abort, and try a different orientation
row.area -= row.pop().area;
position(row, u, rect, false);
u = Math.min(rect.dx, rect.dy);
row.length = row.area = 0;
best = Infinity;
var children = node.children;
if (children && children.length) {
var rect = pad(node),
row = [],
remaining = children.slice(), // copy-on-write
child,
best = Infinity, // the best row score so far
score, // the current row score
u = Math.min(rect.dx, rect.dy), // initial orientation
n;
scale(remaining, rect.dx * rect.dy / node.value);
row.area = 0;
while ((n = remaining.length) > 0) {
row.push(child = remaining[n - 1]);
row.area += child.area;
if ((score = worst(row, u)) <= best) { // continue with this orientation
remaining.pop();
best = score;
} else { // abort, and try a different orientation
row.area -= row.pop().area;
position(row, u, rect, false);
u = Math.min(rect.dx, rect.dy);
row.length = row.area = 0;
best = Infinity;
}
}
if (row.length) {
position(row, u, rect, true);
row.length = row.area = 0;
}
children.forEach(squarify);
}
if (row.length) {
position(row, u, rect, true);
row.length = row.area = 0;
}
node.children.forEach(squarify);
}
// Recursively resizes the specified node's children into existing rows.
// Preserves the existing layout!
function stickify(node) {
if (!node.children) return;
var rect = pad(node),
children = node.children.slice(), // copy-on-write
child,
row = [];
scale(children, rect.dx * rect.dy / node.value);
row.area = 0;
while (child = children.pop()) {
row.push(child);
row.area += child.area;
if (child.z != null) {
position(row, child.z ? rect.dx : rect.dy, rect, !children.length);
row.length = row.area = 0;
var children = node.children;
if (children && children.length) {
var rect = pad(node),
remaining = children.slice(), // copy-on-write
child,
row = [];
scale(remaining, rect.dx * rect.dy / node.value);
row.area = 0;
while (child = remaining.pop()) {
row.push(child);
row.area += child.area;
if (child.z != null) {
position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
row.length = row.area = 0;
}
}
children.forEach(stickify);
}
node.children.forEach(stickify);
}
// Computes the score for the specified row, as the worst aspect ratio.

2
d3.layout.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

4
d3.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -78,6 +78,7 @@ var d3_time_formats = {
H: function(d) { return d3_time_zfill2(d.getHours()); },
I: function(d) { return d3_time_zfill2(d.getHours() % 12 || 12); },
j: d3_time_dayOfYear,
L: function(d) { return d3_time_zfill3(d.getMilliseconds()); },
m: function(d) { return d3_time_zfill2(d.getMonth() + 1); },
M: function(d) { return d3_time_zfill2(d.getMinutes()); },
p: function(d) { return d.getHours() >= 12 ? "PM" : "AM"; },
@ -104,6 +105,7 @@ var d3_time_parsers = {
H: d3_time_parseHour24,
I: d3_time_parseHour12,
// j: function(d, s, i) { /*TODO day of year [001,366] */ return i; },
L: d3_time_parseMilliseconds,
m: d3_time_parseMonthNumber,
M: d3_time_parseMinutes,
p: d3_time_parseAmPm,
@ -277,6 +279,12 @@ function d3_time_parseSeconds(date, string, i) {
return n ? (date.setSeconds(+n[0]), i += n[0].length) : -1;
}
function d3_time_parseMilliseconds(date, string, i) {
d3_time_numberRe.lastIndex = 0;
var n = d3_time_numberRe.exec(string.substring(i, i + 3));
return n ? (date.setMilliseconds(+n[0]), i += n[0].length) : -1;
}
// Note: we don't look at the next directive.
var d3_time_numberRe = /\s*\d+/;
@ -294,18 +302,22 @@ function d3_time_year(d) {
return new d3_time(d.getFullYear(), 0, 1);
}
function d3_time_daysElapsed(d0, d1) {
return ~~((d1 - d0) / 864e5 - (d1.getTimezoneOffset() - d0.getTimezoneOffset()) / 1440);
}
function d3_time_dayOfYear(d) {
return d3_time_zfill3(1 + ~~((d - d3_time_year(d)) / 864e5));
return d3_time_zfill3(1 + d3_time_daysElapsed(d3_time_year(d), d));
}
function d3_time_weekNumberSunday(d) {
var d0 = d3_time_year(d);
return d3_time_zfill2(~~(((d - d0) / 864e5 + d0.getDay()) / 7));
return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + d0.getDay()) / 7));
}
function d3_time_weekNumberMonday(d) {
var d0 = d3_time_year(d);
return d3_time_zfill2(~~(((d - d0) / 864e5 + (d0.getDay() + 6) % 7) / 7));
return d3_time_zfill2(~~((d3_time_daysElapsed(d0, d) + (d0.getDay() + 6) % 7) / 7));
}
// TODO table of time zone offset names?
@ -320,9 +332,14 @@ d3.time.format.utc = function(template) {
var local = d3.time.format(template);
function format(date) {
var utc = new d3_time_format_utc();
utc._ = date;
return local(utc);
try {
d3_time = d3_time_format_utc;
var utc = new d3_time();
utc._ = date;
return local(utc);
} finally {
d3_time = Date;
}
}
format.parse = function(string) {
@ -364,7 +381,19 @@ d3_time_format_utc.prototype = {
setMonth: function(x) { this._.setUTCMonth(x); },
setSeconds: function(x) { this._.setUTCSeconds(x); }
};
d3.time.format.iso = d3.time.format.utc("%Y-%m-%dT%H:%M:%SZ");
var d3_time_formatIso = d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");
d3.time.format.iso = Date.prototype.toISOString ? d3_time_formatIsoNative : d3_time_formatIso;
function d3_time_formatIsoNative(date) {
return date.toISOString();
}
d3_time_formatIsoNative.parse = function(string) {
return new Date(string);
};
d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
function d3_time_range(floor, step, number) {
return function(t0, t1, dt) {
var time = floor(t0), times = [];
@ -541,12 +570,7 @@ function d3_time_scale(linear, methods, format) {
};
// TOOD expose d3_scale_linear_rebind?
scale.range = d3.rebind(scale, linear.range);
scale.rangeRound = d3.rebind(scale, linear.rangeRound);
scale.interpolate = d3.rebind(scale, linear.interpolate);
scale.clamp = d3.rebind(scale, linear.clamp);
return scale;
return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
}
// TODO expose d3_scaleExtent?

2
d3.time.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -51,7 +51,7 @@ var svg = d3.select("body").append("svg:svg")
svg.append("svg:rect")
.attr("width", w)
.attr("height", h)
.attr("height", h);
svg.append("svg:g")
.attr("class", "x grid")

Просмотреть файл

@ -2,7 +2,7 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Polar Stereographic Projection</title>
<title>Azimuthal Projection</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.geo.js"></script>
<script type="text/javascript" src="../../lib/jquery/jquery.min.js"></script>
@ -12,6 +12,13 @@
<body>
<h3>Azimuthal Projection</h3>
<script type="text/javascript" src="azimuthal.js"></script><p>
<select id="mode">
<option value="stereographic">stereographic</option>
<option value="orthographic">orthographic</option>
<option value="equidistant">equidistant</option>
<option value="gnomonic">gnomonic</option>
<option value="equalarea">equalarea</option>
</select>
<div id="lon">origin.longitude: <span>0</span></div>
<div id="lat">origin.latitude: <span>0</span></div><p>
<div id="scale">scale: <span>240</span></div><p>
@ -28,6 +35,7 @@ $("#lon").slider({
var origin = xy.origin();
origin[0] = ui.value;
xy.origin(origin);
circle.origin(origin);
refresh();
}
});
@ -41,6 +49,7 @@ $("#lat").slider({
var origin = xy.origin();
origin[1] = ui.value;
xy.origin(origin);
circle.origin(origin);
refresh();
}
});
@ -79,6 +88,12 @@ $("#translate-y").slider({
}
});
$("#mode").change(function() {
var mode = $(this).val();
xy.mode(mode);
refresh(500);
});
</script>
</body>
</html>

Просмотреть файл

@ -1,4 +1,5 @@
var xy = d3.geo.azimuthal().scale(240).mode("stereographic"),
circle = d3.geo.greatCircle(),
path = d3.geo.path().projection(xy),
svg = d3.select("body").append("svg:svg");
@ -6,14 +7,15 @@ d3.json("../data/world-countries.json", function(collection) {
svg.selectAll("path")
.data(collection.features)
.enter().append("svg:path")
.attr("d", path)
.attr("d", function(d) { return path(circle.clip(d)); })
.append("svg:title")
.text(function(d) { return d.properties.name; });
});
function refresh() {
svg.selectAll("path")
.attr("d", path);
function refresh(duration) {
var p = svg.selectAll("path");
if (duration) p = p.transition().duration(duration);
p.attr("d", function(d) { return path(circle.clip(d)); });
d3.select("#lon span")
.text(xy.origin()[0]);
d3.select("#lat span")

Просмотреть файл

@ -0,0 +1,223 @@
<!DOCTYPE html>
<html>
<head>
<title>Hierarchical Bar Chart</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.layout.js"></script>
<style type="text/css">
text {
font: 10px sans-serif;
}
rect.background {
fill: white;
}
.axis {
shape-rendering: crispEdges;
}
.axis path, .axis line {
fill: none;
stroke: #000;
}
</style>
</head>
<body>
<script type="text/javascript">
var m = [20, 20, 20, 120], // top right bottom left
w = 960 - m[1] - m[3], // width
h = 500 - m[0] - m[2], // height
x = d3.scale.linear().range([0, w]),
y = 20, // bar height
z = d3.scale.ordinal().range(["steelblue", "#ccc"]), // bar color
duration = 750,
delay = 25;
var hierarchy = d3.layout.partition()
.value(function(d) { return d.size; });
var xAxis = d3.svg.axis()
.scale(x)
.orient("top");
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
svg.append("svg:rect")
.attr("class", "background")
.attr("width", w)
.attr("height", h)
.on("click", up);
svg.append("svg:g")
.attr("class", "x axis");
svg.append("svg:g")
.attr("class", "y axis")
.append("svg:line")
.attr("y1", "100%");
d3.json("../data/flare.json", function(root) {
hierarchy.nodes(root);
x.domain([0, root.value]).nice();
down(root, 0);
});
function down(d, i) {
if (!d.children || this.__transition__) return;
var end = duration + d.children.length * delay;
// Mark any currently-displayed bars as exiting.
var exit = svg.selectAll(".enter").attr("class", "exit");
// Entering nodes immediately obscure the clicked-on bar, so hide it.
exit.selectAll("rect").filter(function(p) { return p === d; })
.style("fill-opacity", 1e-6);
// Enter the new bars for the clicked-on data.
// Per above, entering bars are immediately visible.
var enter = bar(d)
.attr("transform", stack(i))
.style("opacity", 1);
// Have the text fade-in, even though the bars are visible.
// Color the bars as parents; they will fade to children if appropriate.
enter.select("text").style("fill-opacity", 1e-6);
enter.select("rect").style("fill", z(true));
// Update the x-scale domain.
x.domain([0, d3.max(d.children, function(d) { return d.value; })]).nice();
// Update the x-axis.
svg.selectAll(".x.axis").transition().duration(duration).call(xAxis);
// Transition entering bars to their new position.
var enterTransition = enter.transition()
.duration(duration)
.delay(function(d, i) { return i * delay; })
.attr("transform", function(d, i) { return "translate(0," + y * i * 1.2 + ")"; });
// Transition entering text.
enterTransition.select("text").style("fill-opacity", 1);
// Transition entering rects to the new x-scale.
enterTransition.select("rect")
.attr("width", function(d) { return x(d.value); })
.style("fill", function(d) { return z(!!d.children); });
// Transition exiting bars to fade out.
var exitTransition = exit.transition()
.duration(duration)
.style("opacity", 1e-6)
.remove();
// Transition exiting bars to the new x-scale.
exitTransition.selectAll("rect").attr("width", function(d) { return x(d.value); });
// Rebind the current node to the background.
svg.select(".background").data([d]).transition().duration(end); d.index = i;
}
function up(d) {
if (!d.parent || this.__transition__) return;
var end = duration + d.children.length * delay;
// Mark any currently-displayed bars as exiting.
var exit = svg.selectAll(".enter").attr("class", "exit");
// Enter the new bars for the clicked-on data's parent.
var enter = bar(d.parent)
.attr("transform", function(d, i) { return "translate(0," + y * i * 1.2 + ")"; })
.style("opacity", 1e-6);
// Color the bars as appropriate.
// Exiting nodes will obscure the parent bar, so hide it.
enter.select("rect")
.style("fill", function(d) { return z(!!d.children); })
.filter(function(p) { return p === d; })
.style("fill-opacity", 1e-6);
// Update the x-scale domain.
x.domain([0, d3.max(d.parent.children, function(d) { return d.value; })]).nice();
// Update the x-axis.
svg.selectAll(".x.axis").transition().duration(duration).call(xAxis);
// Transition entering bars to fade in over the full duration.
var enterTransition = enter.transition()
.duration(end)
.style("opacity", 1);
// Transition entering rects to the new x-scale.
// When the entering parent rect is done, make it visible!
enterTransition.select("rect")
.attr("width", function(d) { return x(d.value); })
.each("end", function(p) { if (p === d) d3.select(this).style("fill-opacity", null); });
// Transition exiting bars to the parent's position.
var exitTransition = exit.selectAll("g").transition()
.duration(duration)
.delay(function(d, i) { return i * delay; })
.attr("transform", stack(d.index));
// Transition exiting text to fade out.
exitTransition.select("text")
.style("fill-opacity", 1e-6);
// Transition exiting rects to the new scale and fade to parent color.
exitTransition.select("rect")
.attr("width", function(d) { return x(d.value); })
.style("fill", z(true));
// Remove exiting nodes when the last child has finished transitioning.
exit.transition().duration(end).remove();
// Rebind the current parent to the background.
svg.select(".background").data([d.parent]).transition().duration(end);;
}
// Creates a set of bars for the given data node, at the specified index.
function bar(d) {
var bar = svg.insert("svg:g", ".y.axis")
.attr("class", "enter")
.attr("transform", "translate(0,5)")
.selectAll("g")
.data(d.children)
.enter().append("svg:g")
.style("cursor", function(d) { return !d.children ? null : "pointer"; })
.on("click", down);
bar.append("svg:text")
.attr("x", -6)
.attr("y", y / 2)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function(d) { return d.name; });
bar.append("svg:rect")
.attr("width", function(d) { return x(d.value); })
.attr("height", y);
return bar;
}
// A stateful closure for stacking bars horizontally.
function stack(i) {
var x0 = 0;
return function(d) {
var tx = "translate(" + x0 + "," + y * i * 1.2 + ")";
x0 += x(d.value);
return tx;
};
}
</script>
</body>
</html>

159
examples/bonne/bonne.html Normal file
Просмотреть файл

@ -0,0 +1,159 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Bonne Projection</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.geo.js"></script>
<script type="text/javascript" src="../../lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="../../lib/jquery-ui/jquery-ui.min.js"></script>
<style type="text/css">
@import url("../../lib/jquery-ui/jquery-ui.css");
body, .ui-widget {
font: 14px Helvetica Neue;
}
svg {
width: 960px;
height: 500px;
border: solid 1px #ccc;
background: #eee;
}
line {
stroke: brown;
stroke-dasharray: 4,2;
}
path {
fill: #ccc;
stroke: #fff;
}
div {
width: 960px;
}
</style>
</head>
<body>
<h3>Bonne Projection</h3>
<script type="text/javascript">
// Our projection.
var xy = d3.geo.bonne(),
path = d3.geo.path().projection(xy);
var countries = d3.select("body").append("svg:svg")
.attr("id", "countries");
d3.json("../data/world-countries.json", function(collection) {
countries.selectAll("path")
.data(collection.features)
.enter().append("svg:path")
.attr("d", path)
.append("svg:title")
.text(function(d) { return d.properties.name; });
});
function refresh() {
countries.selectAll("path")
.attr("d", path);
d3.select("#lon span")
.text(xy.origin()[0]);
d3.select("#lat span")
.text(xy.origin()[1]);
d3.select("#parallel span")
.text(xy.parallel());
d3.select("#scale span")
.text(xy.scale());
d3.select("#translate-x span")
.text(xy.translate()[0]);
d3.select("#translate-y span")
.text(xy.translate()[1]);
}
</script><p>
<div id="lon">origin.longitude: <span>0</span></div>
<div id="lat">origin.latitude: <span>0</span></div><p>
<div id="parallel">parallel: <span>45</span></div><p>
<div id="scale">scale: <span>200</span></div><p>
<div id="translate-x">translate.x: <span>480</span></div>
<div id="translate-y">translate.y: <span>250</span></div>
<script type="text/javascript">
$("#lon").slider({
min: -180,
max: 180,
step: 1e-1,
value: 0,
slide: function(event, ui) {
var origin = xy.origin();
origin[0] = ui.value;
xy.origin(origin);
refresh();
}
});
$("#lat").slider({
min: -90,
max: 90,
step: 1e-1,
value: 0,
slide: function(event, ui) {
var origin = xy.origin();
origin[1] = ui.value;
xy.origin(origin);
refresh();
}
});
$("#parallel").slider({
min: 0,
max: 90,
value: 45,
slide: function(event, ui) {
xy.parallel(ui.value);
refresh();
}
});
$("#scale").slider({
min: 0,
max: 800,
value: 200,
slide: function(event, ui) {
xy.scale(ui.value);
refresh();
}
});
$("#translate-x").slider({
min: -2000,
max: 2000,
value: 480,
slide: function(event, ui) {
var translate = xy.translate();
translate[0] = ui.value;
xy.translate(translate);
refresh();
}
});
$("#translate-y").slider({
min: -2000,
max: 2000,
value: 250,
slide: function(event, ui) {
var translate = xy.translate();
translate[1] = ui.value;
xy.translate(translate);
refresh();
}
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,92 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Brush</title>
<script type="text/javascript" src="../../d3.js"></script>
<style type="text/css">
svg {
font: 10px sans-serif;
}
circle {
-webkit-transition: fill-opacity 250ms linear;
}
.selecting circle {
fill-opacity: .2;
}
.selecting circle.selected {
stroke: #f00;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script type="text/javascript">
var data = d3.range(800).map(Math.random);
var m = [10, 10, 20, 10],
w = 960 - m[1] - m[3],
h = 100 - m[0] - m[2];
var x = d3.scale.linear().range([0, w]),
y = d3.random.normal(h / 2, h / 8);
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
var circle = svg.selectAll("circle")
.data(data)
.enter().append("svg:circle")
.attr("transform", function(d) { return "translate(" + x(d) + "," + y() + ")"; })
.attr("r", 3.5);
svg.append("svg:g")
.attr("class", "brush")
.call(d3.svg.brush().x(x)
.on("brushstart", brushstart)
.on("brush", brush)
.on("brushend", brushend))
.selectAll("rect")
.attr("height", h);
function brushstart() {
svg.classed("selecting", true);
}
function brush() {
var s = d3.event.target.extent();
circle.classed("selected", function(d) { return s[0] <= d && d <= s[1]; });
}
function brushend() {
svg.classed("selecting", !d3.event.target.empty());
}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Brush</title>
<script type="text/javascript" src="../../d3.js"></script>
<style type="text/css">
svg {
font: 10px sans-serif;
}
circle {
-webkit-transition: fill-opacity 250ms linear;
}
.selecting circle {
fill-opacity: .2;
}
.selecting circle.selected {
stroke: #f00;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script type="text/javascript">
var data = d3.range(800).map(Math.random);
var m = [10, 10, 10, 40],
w = 120 - m[1] - m[3],
h = 960 - m[0] - m[2];
var x = d3.random.normal(w / 2, w / 8),
y = d3.scale.linear().range([h, 0]);
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
svg.append("svg:g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var circle = svg.selectAll("circle")
.data(data)
.enter().append("svg:circle")
.attr("transform", function(d) { return "translate(" + x() + "," + y(d) + ")"; })
.attr("r", 3.5);
svg.append("svg:g")
.attr("class", "brush")
.call(d3.svg.brush().y(y)
.on("brushstart", brushstart)
.on("brush", brush)
.on("brushend", brushend))
.selectAll("rect")
.attr("width", w);
function brushstart() {
svg.classed("selecting", true);
}
function brush() {
var e = d3.event.target.extent();
circle.classed("selected", function(d) { return e[0] <= d && d <= e[1]; });
}
function brushend() {
svg.classed("selecting", !d3.event.target.empty());
}
</script>
</body>
</html>

98
examples/brush/brush.html Normal file
Просмотреть файл

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Brush</title>
<script type="text/javascript" src="../../d3.js"></script>
<style type="text/css">
svg {
font: 10px sans-serif;
}
circle {
-webkit-transition: fill-opacity 250ms linear;
}
.selecting circle {
fill-opacity: .2;
}
.selecting circle.selected {
stroke: #f00;
}
.axis path, .axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.brush .extent {
stroke: #fff;
fill-opacity: .125;
shape-rendering: crispEdges;
}
</style>
</head>
<body>
<script type="text/javascript">
var random = d3.random.normal(.5, .1),
data = d3.range(800).map(function() { return [random(), random()]; });
var m = [10, 10, 20, 40],
w = 960 - m[1] - m[3],
h = 500 - m[0] - m[2];
var x = d3.scale.linear().range([0, w]),
y = d3.scale.linear().range([h, 0]);
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(d3.svg.axis().scale(x).orient("bottom"));
svg.append("svg:g")
.attr("class", "y axis")
.call(d3.svg.axis().scale(y).orient("left"));
var circle = svg.selectAll("circle")
.data(data)
.enter().append("svg:circle")
.attr("transform", function(d) { return "translate(" + x(d[0]) + "," + y(d[1]) + ")"; })
.attr("r", 3.5);
svg.append("svg:g")
.attr("class", "brush")
.call(d3.svg.brush().x(x).y(y)
.on("brushstart", brushstart)
.on("brush", brush)
.on("brushend", brushend));
function brushstart() {
svg.classed("selecting", true);
}
function brush() {
var e = d3.event.target.extent();
circle.classed("selected", function(d) {
return e[0][0] <= d[0] && d[0] <= e[1][0]
&& e[0][1] <= d[1] && d[1] <= e[1][1];
});
}
function brushend() {
svg.classed("selecting", !d3.event.target.empty());
}
</script>
</body>
</html>

Просмотреть файл

@ -1,16 +1,15 @@
#chart {
font: 10px sans-serif;
shape-rendering: crispEdges;
}
.day {
fill: #fff;
stroke: #ccc;
shape-rendering: crispEdges;
}
.month {
fill: none;
stroke: #000;
stroke-width: 2px;
shape-rendering: crispEdges;
}

Просмотреть файл

@ -1,50 +0,0 @@
var calendar = {
format: d3.time.format("%Y-%m-%d"),
dates: function(year) {
var dates = [],
date = new Date(year, 0, 1),
week = 0,
day;
do {
dates.push({
day: day = date.getDay(),
week: week,
month: date.getMonth(),
Date: calendar.format(date)
});
date.setDate(date.getDate() + 1);
if (day === 6) week++;
} while (date.getFullYear() === year);
return dates;
},
months: function(year) {
var months = [],
date = new Date(year, 0, 1),
month,
firstDay,
firstWeek,
day,
week = 0;
do {
firstDay = date.getDay();
firstWeek = week;
month = date.getMonth();
do {
day = date.getDay();
if (day === 6) week++;
date.setDate(date.getDate() + 1);
} while (date.getMonth() === month);
months.push({
firstDay: firstDay,
firstWeek: firstWeek,
lastDay: day,
lastWeek: day === 6 ? week - 1 : week
});
} while (date.getFullYear() === year);
return months;
}
};

Просмотреть файл

@ -0,0 +1,120 @@
<!DOCTYPE html>
<html>
<head>
<title>DJI</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.csv.js"></script>
<script type="text/javascript" src="../../d3.time.js"></script>
<style type="text/css">
body {
font: 10px sans-serif;
}
rect {
fill: #ddd;
}
path.area {
fill: #000;
fill-opacity: .75;
}
.axis, .grid {
shape-rendering: crispEdges;
}
.grid line {
stroke: #fff;
}
.grid line.minor {
stroke-opacity: .5;
}
.grid text {
display: none;
}
.axis line {
stroke: #000;
}
.grid path, .axis path {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript">
var m = [10, 50, 20, 10],
w = 960 - m[1] - m[3],
h = 500 - m[0] - m[2],
parse = d3.time.format("%Y-%m-%d").parse;
// Scales. Note the inverted domain for the y-scale: bigger is up!
var x = d3.time.scale().range([20, w - 20]),
y = d3.scale.linear().range([h - 20, 20]);
// Axes.
var xAxis = d3.svg.axis().scale(x).orient("bottom"),
yAxis = d3.svg.axis().scale(y).orient("right");
// An area generator.
var area = d3.svg.area()
.x(function(d) { return x(d.Date); })
.y0(y(0))
.y1(function(d) { return y(d.Close); });
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
svg.append("svg:rect")
.attr("width", w)
.attr("height", h);
d3.csv("dji.csv", function(data) {
// Parse dates and numbers.
data.reverse().forEach(function(d) {
d.Date = parse(d.Date);
d.Close = +d.Close;
});
// Compute the minimum and maximum date, and the maximum price.
x.domain([data[0].Date, data[data.length - 1].Date]);
y.domain([0, d3.max(data, function(d) { return d.Close; })]);
svg.append("svg:g")
.attr("class", "x grid")
.attr("transform", "translate(0," + h + ")")
.call(xAxis.tickSubdivide(1).tickSize(-h));
svg.append("svg:g")
.attr("class", "y grid")
.attr("transform", "translate(" + w + ",0)")
.call(yAxis.tickSubdivide(1).tickSize(-w));
svg.append("svg:g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis.tickSubdivide(0).tickSize(6));
svg.append("svg:g")
.attr("class", "y axis")
.attr("transform", "translate(" + w + ",0)")
.call(yAxis.tickSubdivide(0).tickSize(6));
svg.append("svg:path")
.attr("class", "area")
.attr("d", area(data));
});
</script>
</body>
</html>

Просмотреть файл

@ -5,7 +5,6 @@
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.csv.js"></script>
<script type="text/javascript" src="../../d3.time.js"></script>
<script type="text/javascript" src="calendar.js"></script>
<link type="text/css" rel="stylesheet" href="../../lib/colorbrewer/colorbrewer.css"/>
<link type="text/css" rel="stylesheet" href="calendar.css"/>
</head>

Просмотреть файл

@ -1,61 +1,65 @@
var w = 960,
pw = 14,
z = ~~((w - pw * 2) / 53),
ph = z >> 1,
h = z * 7;
var m = [19, 20, 20, 19], // top right bottom left margin
w = 960 - m[1] - m[3], // width
h = 136 - m[0] - m[2], // height
z = 17; // cell size
var vis = d3.select("#chart")
.selectAll("svg")
var day = d3.time.format("%w"),
week = d3.time.format("%U"),
percent = d3.format(".1%"),
format = d3.time.format("%Y-%m-%d");
var color = d3.scale.quantize()
.domain([-.05, .05])
.range(d3.range(9));
var svg = d3.select("#chart").selectAll("svg")
.data(d3.range(1990, 2011))
.enter().append("svg:svg")
.attr("width", w)
.attr("height", h + ph * 2)
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.attr("class", "RdYlGn")
.append("svg:g")
.attr("transform", "translate(" + pw + "," + ph + ")");
.attr("transform", "translate(" + (m[3] + (w - z * 53) / 2) + "," + (m[0] + (h - z * 7) / 2) + ")");
vis.append("svg:text")
.attr("transform", "translate(-6," + h / 2 + ")rotate(-90)")
svg.append("svg:text")
.attr("transform", "translate(-6," + z * 3.5 + ")rotate(-90)")
.attr("text-anchor", "middle")
.text(function(d) { return d; });
.text(String);
vis.selectAll("rect.day")
.data(calendar.dates)
var rect = svg.selectAll("rect.day")
.data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("svg:rect")
.attr("x", function(d) { return d.week * z; })
.attr("y", function(d) { return d.day * z; })
.attr("class", "day")
.attr("width", z)
.attr("height", z);
.attr("height", z)
.attr("x", function(d) { return week(d) * z; })
.attr("y", function(d) { return day(d) * z; });
vis.selectAll("path.month")
.data(calendar.months)
svg.selectAll("path.month")
.data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("svg:path")
.attr("class", "month")
.attr("d", function(d) {
return "M" + (d.firstWeek + 1) * z + "," + d.firstDay * z
+ "H" + d.firstWeek * z
+ "V" + 7 * z
+ "H" + d.lastWeek * z
+ "V" + (d.lastDay + 1) * z
+ "H" + (d.lastWeek + 1) * z
+ "V" + 0
+ "H" + (d.firstWeek + 1) * z
+ "Z";
});
.attr("d", monthPath);
d3.csv("dji.csv", function(csv) {
var data = d3.nest()
.key(function(d) { return d.Date; })
.rollup(function(d) { return (d[0].Close - d[0].Open) / d[0].Open; })
.map(csv);
.key(function(d) { return d.Date; })
.rollup(function(d) { return (d[0].Close - d[0].Open) / d[0].Open; })
.map(csv);
var color = d3.scale.quantize()
.domain([-.05, .05])
.range(d3.range(9));
vis.selectAll("rect.day")
.attr("class", function(d) { return "day q" + color(data[d.Date]) + "-9"; })
rect
.attr("class", function(d) { return "day q" + color(data[format(d)]) + "-9"; })
.append("svg:title")
.text(function(d) { return d.Date + ": " + (data[d.Date] * 100).toFixed(1) + "%"; });
.text(function(d) { return (d = format(d)) + (d in data ? ": " + percent(data[d]) : ""); });
});
function monthPath(t0) {
var t1 = new Date(t0.getUTCFullYear(), t0.getUTCMonth() + 1, 0),
d0 = +day(t0), w0 = +week(t0),
d1 = +day(t1), w1 = +week(t1);
return "M" + (w0 + 1) * z + "," + d0 * z
+ "H" + w0 * z + "V" + 7 * z
+ "H" + w1 * z + "V" + (d1 + 1) * z
+ "H" + (w1 + 1) * z + "V" + 0
+ "H" + (w0 + 1) * z + "Z";
}

Просмотреть файл

@ -5,7 +5,6 @@
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.csv.js"></script>
<script type="text/javascript" src="../../d3.time.js"></script>
<script type="text/javascript" src="calendar.js"></script>
<link type="text/css" rel="stylesheet" href="../../lib/colorbrewer/colorbrewer.css"/>
<link type="text/css" rel="stylesheet" href="calendar.css"/>
</head>

Просмотреть файл

@ -1,47 +1,43 @@
var w = 960,
pw = 14,
z = ~~((w - pw * 2) / 53),
ph = z >> 1,
h = z * 7;
var m = [19, 20, 20, 19], // top right bottom left margin
w = 960 - m[1] - m[3], // width
h = 136 - m[0] - m[2], // height
z = 17; // cell size
var vis = d3.select("#chart")
.selectAll("svg")
var day = d3.time.format("%w"),
week = d3.time.format("%U"),
format = d3.time.format("%Y-%m-%d");
var color = d3.scale.quantile()
.range(d3.range(9).reverse());
var svg = d3.select("#chart").selectAll("svg")
.data(d3.range(1993, 2011))
.enter().append("svg:svg")
.attr("width", w)
.attr("height", h + ph * 2)
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.attr("class", "RdYlGn")
.append("svg:g")
.attr("transform", "translate(" + pw + "," + ph + ")");
.attr("transform", "translate(" + (m[3] + (w - z * 53) / 2) + "," + (m[0] + (h - z * 7) / 2) + ")");
vis.append("svg:text")
.attr("transform", "translate(-6," + h / 2 + ")rotate(-90)")
.text(function(d) { return d; });
svg.append("svg:text")
.attr("transform", "translate(-6," + z * 3.5 + ")rotate(-90)")
.attr("text-anchor", "middle")
.text(String);
vis.selectAll("rect.day")
.data(calendar.dates)
var rect = svg.selectAll("rect.day")
.data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("svg:rect")
.attr("x", function(d) { return d.week * z; })
.attr("y", function(d) { return d.day * z; })
.attr("class", "day")
.attr("width", z)
.attr("height", z);
.attr("height", z)
.attr("x", function(d) { return week(d) * z; })
.attr("y", function(d) { return day(d) * z; });
vis.selectAll("path.month")
.data(calendar.months)
svg.selectAll("path.month")
.data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); })
.enter().append("svg:path")
.attr("class", "month")
.attr("d", function(d) {
return "M" + (d.firstWeek + 1) * z + "," + d.firstDay * z
+ "H" + d.firstWeek * z
+ "V" + 7 * z
+ "H" + d.lastWeek * z
+ "V" + (d.lastDay + 1) * z
+ "H" + (d.lastWeek + 1) * z
+ "V" + 0
+ "H" + (d.firstWeek + 1) * z
+ "Z";
});
.attr("d", monthPath);
d3.csv("vix.csv", function(csv) {
var data = d3.nest()
@ -49,12 +45,21 @@ d3.csv("vix.csv", function(csv) {
.rollup(function(d) { return d[0].Open; })
.map(csv);
var color = d3.scale.quantile()
.domain(d3.values(data))
.range(d3.range(9).reverse());
color.domain(d3.values(data));
vis.selectAll("rect.day")
.attr("class", function(d) { return "day q" + color(data[d.Date]) + "-9"; })
rect
.attr("class", function(d) { return "day q" + color(data[format(d)]) + "-9"; })
.append("svg:title")
.text(function(d) { return d.Date + ": " + data[d.Date]; });
.text(function(d) { return (d = format(d)) + (d in data ? ": " + data[d] : ""); });
});
function monthPath(t0) {
var t1 = new Date(t0.getUTCFullYear(), t0.getUTCMonth() + 1, 0),
d0 = +day(t0), w0 = +week(t0),
d1 = +day(t1), w1 = +week(t1);
return "M" + (w0 + 1) * z + "," + d0 * z
+ "H" + w0 * z + "V" + 7 * z
+ "H" + w1 * z + "V" + (d1 + 1) * z
+ "H" + (w1 + 1) * z + "V" + 0
+ "H" + (w0 + 1) * z + "Z";
}

Просмотреть файл

@ -35,6 +35,7 @@ d3.json("../data/us-states.json", function(json) {
.selectAll("path")
.data(json.features)
.enter().append("svg:path")
.attr("d", path)
.attr("transform", function(d) {
var centroid = path.centroid(d),
x = centroid[0],
@ -44,8 +45,7 @@ d3.json("../data/us-states.json", function(json) {
+ "translate(" + -x + "," + -y + ")";
})
.style("stroke-width", function(d) {
return 1 / Math.sqrt(data[+d.id] * 5);
})
.attr("d", path);
return 1 / Math.sqrt(data[+d.id] * 5 || 1);
});
});

Просмотреть файл

@ -0,0 +1,109 @@
<!DOCTYPE html>
<html>
<head>
<title>Crimean War</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.layout.js"></script>
<script type="text/javascript" src="../../d3.time.js"></script>
<script type="text/javascript" src="../../d3.csv.js"></script>
<style type="text/css">
svg {
width: 960px;
height: 500px;
font: 10px sans-serif;
}
.rule {
shape-rendering: crispEdges;
}
path.line {
fill: none;
}
</style>
</head>
<body>
<script type="text/javascript">
var p = [20, 50, 30, 20],
w = 960 - p[1] - p[3],
h = 500 - p[0] - p[2],
x = d3.time.scale().range([0, w]),
y = d3.scale.linear().range([h, 0]),
z = d3.scale.ordinal().range(["lightpink", "darkgray", "lightblue"]),
parse = d3.time.format("%m/%Y").parse,
format = d3.time.format("%b");
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(" + p[3] + "," + p[0] + ")");
d3.csv("crimea.csv", function(crimea) {
// Transpose the data into layers by cause.
var causes = d3.layout.stack()(["wounds", "other", "disease"].map(function(cause) {
return crimea.map(function(d) {
return {x: parse(d.date), y: +d[cause]};
});
}));
// Compute the x-domain (by date) and y-domain (by top).
x.domain([causes[0][0].x, causes[0][causes[0].length - 1].x]);
y.domain([0, d3.max(causes[causes.length - 1], function(d) { return d.y0 + d.y; })]);
// Add an area for each cause.
svg.selectAll("path.area")
.data(causes)
.enter().append("svg:path")
.attr("class", "area")
.style("fill", function(d, i) { return z(i); })
.attr("d", d3.svg.area()
.x(function(d) { return x(d.x); })
.y0(function(d) { return y(d.y0); })
.y1(function(d) { return y(d.y0 + d.y); }));
// Add a line for each cause.
svg.selectAll("path.line")
.data(causes)
.enter().append("svg:path")
.attr("class", "line")
.style("stroke", function(d, i) { return d3.rgb(z(i)).darker(); })
.attr("d", d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y0 + d.y); }));
// Add a label per date.
svg.selectAll("text")
.data(x.ticks(12))
.enter().append("svg:text")
.attr("x", x)
.attr("y", h + 6)
.attr("text-anchor", "middle")
.attr("dy", ".71em")
.text(x.tickFormat(12));
// Add y-axis rules.
var rule = svg.selectAll("g.rule")
.data(y.ticks(5))
.enter().append("svg:g")
.attr("class", "rule")
.attr("transform", function(d) { return "translate(0," + y(d) + ")"; });
rule.append("svg:line")
.attr("x2", w)
.style("stroke", function(d) { return d ? "#fff" : "#000"; })
.style("stroke-opacity", function(d) { return d ? .7 : null; });
rule.append("svg:text")
.attr("x", w + 6)
.attr("dy", ".35em")
.text(d3.format(",d"));
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<title>Custom Elements</title>
<script type="text/javascript" src="../../d3.js"></script>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>
<body>
<script type="text/javascript">
// Register the "custom" namespace prefix for our custom elements.
d3.ns.prefix.custom = "http://github.com/mbostock/d3/examples/dom";
var w = 960,
h = 500;
// Add our "custom" sketch element to the body.
var sketch = d3.select("body").append("custom:sketch")
.attr("width", w)
.attr("height", h)
.call(custom);
// On each mouse move, create a circle that increases in size and fades away.
d3.select(window).on("mousemove", function() {
sketch.append("custom:circle")
.attr("x", d3.event.clientX)
.attr("y", d3.event.clientY)
.attr("radius", 0)
.attr("strokeStyle", "red")
.transition()
.duration(2000)
.ease(Math.sqrt)
.attr("radius", 200)
.attr("strokeStyle", "white")
.remove();
});
function custom(selection) {
selection.each(function() {
var root = this,
canvas = root.parentNode.appendChild(document.createElement("canvas")),
context = canvas.getContext("2d");
canvas.style.position = "absolute";
canvas.style.top = root.offsetTop + "px";
canvas.style.left = root.offsetLeft + "px";
// It'd be nice to use DOM Mutation Events here instead.
// However, they appear to arrive irregularly, causing choppy animation.
d3.timer(redraw);
// Clear the canvas and then iterate over child elements.
function redraw() {
canvas.width = root.getAttribute("width");
canvas.height = root.getAttribute("height");
for (var child = root.firstChild; child; child = child.nextSibling) draw(child);
}
// For now we only support circles with strokeStyle.
// But you should imagine extending this to arbitrary shapes and groups!
function draw(element) {
switch (element.tagName) {
case "circle": {
context.strokeStyle = element.getAttribute("strokeStyle");
context.beginPath();
context.arc(element.getAttribute("x"), element.getAttribute("y"), element.getAttribute("radius"), 0, 2 * Math.PI);
context.stroke();
break;
}
}
}
});
};
</script>
</body>
</html>

Просмотреть файл

@ -1,5 +0,0 @@
These are derived from the cartographic boundary files from the 2000 U.S. Census:
http://www.census.gov/geo/www/cob/bdy_files.html
Then, MapShaper was used to simplify the geometry, and ogr2ogr to convert the shapefiles to GeoJSON. Some additional work was done to preserve the FIPS codes, which are dropped from the shapefiles by MapShaper.

13
examples/data/README.md Normal file
Просмотреть файл

@ -0,0 +1,13 @@
## World Boundaries
These are derived from the public domain [Natural Earth](http://www.naturalearthdata.com/downloads/) cultural vector files, 110m resolution. Then, ogr2ogr was used to convert to GeoJSON. Lastly, the data was cleaned up slightly, removing extra properties and a degenerate edge from Antarctica.
collection.features.forEach(function(d, i) {
d.id = d.properties.ISO_A3;
d.properties = {name: d.properties.SOVEREIGNT};
});
## United States Boundaries
These are derived from the cartographic boundary files from the 2000 [U.S. Census](http://www.census.gov/geo/www/cob/bdy_files.html
). Then, MapShaper was used to simplify the geometry, and ogr2ogr to convert the shapefiles to GeoJSON. Some additional work was done to preserve the FIPS codes, which are dropped from the shapefiles by MapShaper.

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -26,7 +26,7 @@ var w = 400,
data,
color = d3.scale.category20(),
arc = d3.svg.arc(),
donut = d3.layout.pie();
donut = d3.layout.pie().sort(null);
var vis = d3.select("body")
.append("svg:svg")

Просмотреть файл

@ -197,12 +197,12 @@ function init() {
hullg.selectAll("path.hull").remove();
hull = hullg.selectAll("path.hull")
.data(convexHulls(net.nodes, getGroup, off))
.data(convexHulls(net.nodes, getGroup, off))
.enter().append("svg:path")
.attr("class", "hull")
.attr("d", drawCluster)
.style("fill", function(d) { return fill(d.group); })
.on("dblclick", function(d) { expand[d.group] = false; init(); });
.attr("class", "hull")
.attr("d", drawCluster)
.style("fill", function(d) { return fill(d.group); })
.on("dblclick", function(d) { expand[d.group] = false; init(); });
link = linkg.selectAll("line.link").data(net.links, linkid);
link.exit().remove();
@ -213,7 +213,6 @@ function init() {
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; })
.style("stroke-width", function(d) { return d.size || 1; });
link = linkg.selectAll("line.link");
node = nodeg.selectAll("circle.node").data(net.nodes, nodeid);
node.exit().remove();
@ -227,8 +226,7 @@ function init() {
if (d.size) { expand[d.group] = true; init(); }
});
node = nodeg.selectAll("circle.node")
.call(force.drag);
node.call(force.drag);
force.on("tick", function() {
if (!hull.empty()) {

Просмотреть файл

@ -10,8 +10,8 @@
circle.node {
cursor: pointer;
stroke: #3182bd;
stroke-width: 1.5px;
stroke: #000;
stroke-width: .5px;
}
line.link {
@ -28,9 +28,14 @@ line.link {
var w = 960,
h = 500,
node,
link,
root;
var force = d3.layout.force()
.on("tick", tick)
.charge(function(d) { return d._children ? -d.size / 100 : -30; })
.linkDistance(function(d) { return d.target._children ? 80 : 30; })
.size([w, h]);
var vis = d3.select("#chart").append("svg:svg")
@ -39,6 +44,9 @@ var vis = d3.select("#chart").append("svg:svg")
d3.json("../data/flare.json", function(json) {
root = json;
root.fixed = true;
root.x = w / 2;
root.y = h / 2;
update();
});
@ -53,7 +61,7 @@ function update() {
.start();
// Update the links…
var link = vis.selectAll("line.link")
link = vis.selectAll("line.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links.
@ -68,36 +76,35 @@ function update() {
link.exit().remove();
// Update the nodes…
var node = vis.selectAll("circle.node")
node = vis.selectAll("circle.node")
.data(nodes, function(d) { return d.id; })
.style("fill", color);
node.transition()
.attr("r", function(d) { return d.children ? 4.5 : Math.sqrt(d.size) / 10; });
// Enter any new nodes.
node.enter().append("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return Math.sqrt(d.size) / 10 || 4.5; })
.attr("r", function(d) { return d.children ? 4.5 : Math.sqrt(d.size) / 10; })
.style("fill", color)
.on("click", click)
.call(force.drag);
// Exit any old nodes.
node.exit().remove();
}
// Re-select for update.
link = vis.selectAll("line.link");
node = vis.selectAll("circle.node");
function tick() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
// Color leaf nodes orange, and packages white or blue.
@ -122,12 +129,13 @@ function flatten(root) {
var nodes = [], i = 0;
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (node.children) node.size = node.children.reduce(function(p, v) { return p + recurse(v); }, 0);
if (!node.id) node.id = ++i;
nodes.push(node);
return node.size;
}
recurse(root);
root.size = recurse(root);
return nodes;
}

Просмотреть файл

@ -2,14 +2,14 @@ var w = 960,
h = 500,
fill = d3.scale.category20();
var vis = d3.select("#chart")
.append("svg:svg")
var vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);
d3.json("miserables.json", function(json) {
var force = d3.layout.force()
.charge(-60)
.charge(-120)
.linkDistance(30)
.nodes(json.nodes)
.links(json.links)
.size([w, h])
@ -38,11 +38,6 @@ d3.json("miserables.json", function(json) {
node.append("svg:title")
.text(function(d) { return d.name; });
vis.style("opacity", 1e-6)
.transition()
.duration(1000)
.style("opacity", 1);
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })

Просмотреть файл

@ -0,0 +1,78 @@
<!DOCTYPE html>
<html>
<head>
<title>Great Arc</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.geo.js"></script>
<style type="text/css">
#states path {
fill: #ddd;
stroke: #fff;
}
#arcs path {
fill: none;
stroke: #000;
stroke-width: .5px;
stroke-opacity: .2;
}
</style>
</head>
<body>
<script type="text/javascript">
var w = 960,
h = 500;
var projection = d3.geo.azimuthal()
.origin([-115, 50])
.scale(500);
var path = d3.geo.path()
.projection(projection);
var arc = d3.geo.greatArc();
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
var states = svg.append("svg:g")
.attr("id", "states");
var arcs = svg.append("svg:g")
.attr("id", "arcs");
d3.json("../data/us-states.json", function(collection) {
states.selectAll("path")
.data(collection.features)
.enter().append("svg:path")
.attr("d", path);
});
d3.json("../data/us-state-centroids.json", function(collection) {
var links = [];
// Create a link between each state centroid.
collection.features.forEach(function(a) {
collection.features.forEach(function(b) {
if (a !== b) {
links.push({
source: a.geometry.coordinates,
target: b.geometry.coordinates
});
}
});
});
arcs.selectAll("path")
.data(links)
.enter().append("svg:path")
.attr("d", function(d) { return path(arc(d)); });
});
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,70 @@
require("../../test/env");
require("../../d3");
require("../../d3.geo");
var fs = require("fs"),
util = require("util"),
Canvas = require("canvas");
var w = 1920,
h = 1080;
var projection = d3.geo.albersUsa()
.scale(2000)
.translate([w / 2, h / 2]);
var path = d3.geo.path()
.projection(projection);
var canvas = new Canvas(w, h),
context = canvas.getContext("2d");
context.antialias = "none";
context.lineWidth = 8;
context.lineJoin = "round";
d3.json(__dirname + "/../data/us-counties.json", function(collection) {
renderAll("stroke");
renderAll("fill");
fs.writeFile("us-counties.png", canvas.toBuffer());
function renderAll(action) {
collection.features.forEach(function(feature) {
var re = /[MLZ]/g,
d = path(feature),
i = 0,
m;
context[action + "Style"] = "#" + pad((+feature.id).toString(16));
context.beginPath();
re.lastIndex = 1;
while (m = re.exec(d)) render(m.index);
render();
context[action]();
function render(j) {
switch (d.charAt(i)) {
case "M": {
var p = d.substring(i + 1, j).split(",").map(Number);
context.moveTo(p[0], p[1]);
break;
}
case "L": {
var p = d.substring(i + 1, j).split(",").map(Number);
context.lineTo(p[0], p[1]);
break;
}
case "Z": {
context.closePath();
break;
}
}
i = j;
}
});
}
});
function pad(s) {
return s.length < 6 ? new Array(7 - s.length).join("0") + s : s;
}

407
examples/parallel/cars.csv Normal file
Просмотреть файл

@ -0,0 +1,407 @@
name,economy (mpg),cylinders,displacement (cc),power (hp),weight (lb),0-60 mph (s),year
AMC Ambassador Brougham,13,8,360,175,3821,11,73
AMC Ambassador DPL,15,8,390,190,3850,8.5,70
AMC Ambassador SST,17,8,304,150,3672,11.5,72
AMC Concord DL 6,20.2,6,232,90,3265,18.2,79
AMC Concord DL,18.1,6,258,120,3410,15.1,78
AMC Concord DL,23,4,151,,3035,20.5,82
AMC Concord,19.4,6,232,90,3210,17.2,78
AMC Concord,24.3,4,151,90,3003,20.1,80
AMC Gremlin,18,6,232,100,2789,15,73
AMC Gremlin,19,6,232,100,2634,13,71
AMC Gremlin,20,6,232,100,2914,16,75
AMC Gremlin,21,6,199,90,2648,15,70
AMC Hornet Sportabout (Wagon),18,6,258,110,2962,13.5,71
AMC Hornet,18,6,199,97,2774,15.5,70
AMC Hornet,18,6,232,100,2945,16,73
AMC Hornet,19,6,232,100,2901,16,74
AMC Hornet,22.5,6,232,90,3085,17.6,76
AMC Matador (Wagon),14,8,304,150,4257,15.5,74
AMC Matador (Wagon),15,8,304,150,3892,12.5,72
AMC Matador,14,8,304,150,3672,11.5,73
AMC Matador,15,6,258,110,3730,19,75
AMC Matador,15.5,8,304,120,3962,13.9,76
AMC Matador,16,6,258,110,3632,18,74
AMC Matador,18,6,232,100,3288,15.5,71
AMC Pacer D/L,17.5,6,258,95,3193,17.8,76
AMC Pacer,19,6,232,90,3211,17,75
AMC Rebel SST (Wagon),,8,360,175,3850,11,70
AMC Rebel SST,16,8,304,150,3433,12,70
AMC Spirit DL,27.4,4,121,80,2670,15,79
Audi 100 LS,20,4,114,91,2582,14,73
Audi 100 LS,23,4,115,95,2694,15,75
Audi 100 LS,24,4,107,90,2430,14.5,70
Audi 4000,34.3,4,97,78,2188,15.8,80
Audi 5000,20.3,5,131,103,2830,15.9,78
Audi 5000S (Diesel),36.4,5,121,67,2950,19.9,80
Audi Fox,29,4,98,83,2219,16.5,74
BMW 2002,26,4,121,113,2234,12.5,70
BMW 320i,21.5,4,121,110,2600,12.8,77
Buick Century 350,13,8,350,175,4100,13,73
Buick Century Limited,25,6,181,110,2945,16.4,82
Buick Century Luxus (Wagon),13,8,350,150,4699,14.5,74
Buick Century Special,20.6,6,231,105,3380,15.8,78
Buick Century,17,6,231,110,3907,21,75
Buick Century,22.4,6,231,110,3415,15.8,81
Buick Electra 225 Custom,12,8,455,225,4951,11,73
Buick Estate Wagon (Wagon),14,8,455,225,3086,10,70
Buick Estate Wagon (Wagon),16.9,8,350,155,4360,14.9,79
Buick Lesabre Custom,13,8,350,155,4502,13.5,72
Buick Opel Isuzu Deluxe,30,4,111,80,2155,14.8,77
Buick Regal Sport Coupe (Turbo),17.7,6,231,165,3445,13.4,78
Buick Skyhawk,21,6,231,110,3039,15,75
Buick Skylark 320,15,8,350,165,3693,11.5,70
Buick Skylark Limited,28.4,4,151,90,2670,16,79
Buick Skylark,20.5,6,231,105,3425,16.9,77
Buick Skylark,26.6,4,151,84,2635,16.4,81
Cadillac Eldorado,23,8,350,125,3900,17.4,79
Cadillac Seville,16.5,8,350,180,4380,12.1,76
Chevroelt Chevelle Malibu,16,6,250,105,3897,18.5,75
Chevrolet Bel Air,15,8,350,145,4440,14,75
Chevrolet Camaro,27,4,151,90,2950,17.3,82
Chevrolet Caprice Classic,13,8,400,150,4464,12,73
Chevrolet Caprice Classic,17,8,305,130,3840,15.4,79
Chevrolet Caprice Classic,17.5,8,305,145,3880,12.5,77
Chevrolet Cavalier 2-Door,34,4,112,88,2395,18,82
Chevrolet Cavalier Wagon,27,4,112,88,2640,18.6,82
Chevrolet Cavalier,28,4,112,88,2605,19.6,82
Chevrolet Chevelle Concours (Wagon),,8,350,165,4142,11.5,70
Chevrolet Chevelle Concours (Wagon),13,8,307,130,4098,14,72
Chevrolet Chevelle Malibu Classic,16,6,250,100,3781,17,74
Chevrolet Chevelle Malibu Classic,17.5,8,305,140,4215,13,76
Chevrolet Chevelle Malibu,17,6,250,100,3329,15.5,71
Chevrolet Chevelle Malibu,18,8,307,130,3504,12,70
Chevrolet Chevette,29,4,85,52,2035,22.2,76
Chevrolet Chevette,30,4,98,68,2155,16.5,78
Chevrolet Chevette,30.5,4,98,63,2051,17,77
Chevrolet Chevette,32.1,4,98,70,2120,15.5,80
Chevrolet Citation,23.5,6,173,110,2725,12.6,81
Chevrolet Citation,28,4,151,90,2678,16.5,80
Chevrolet Citation,28.8,6,173,115,2595,11.3,79
Chevrolet Concours,17.5,6,250,110,3520,16.4,77
Chevrolet Impala,11,8,400,150,4997,14,73
Chevrolet Impala,13,8,350,165,4274,12,72
Chevrolet Impala,14,8,350,165,4209,12,71
Chevrolet Impala,14,8,454,220,4354,9,70
Chevrolet Malibu Classic (Wagon),19.2,8,267,125,3605,15,79
Chevrolet Malibu,13,8,350,145,3988,13,73
Chevrolet Malibu,20.5,6,200,95,3155,18.2,78
Chevrolet Monte Carlo Landau,15.5,8,350,170,4165,11.4,77
Chevrolet Monte Carlo Landau,19.2,8,305,145,3425,13.2,78
Chevrolet Monte Carlo S,15,8,350,145,4082,13,73
Chevrolet Monte Carlo,15,8,400,150,3761,9.5,70
Chevrolet Monza 2+2,20,8,262,110,3221,13.5,75
Chevrolet Nova Custom,16,6,250,100,3278,18,73
Chevrolet Nova,15,6,250,100,3336,17,74
Chevrolet Nova,18,6,250,105,3459,16,75
Chevrolet Nova,22,6,250,105,3353,14.5,76
Chevrolet Vega (Wagon),22,4,140,72,2408,19,71
Chevrolet Vega 2300,28,4,140,90,2264,15.5,71
Chevrolet Vega,20,4,140,90,2408,19.5,72
Chevrolet Vega,21,4,140,72,2401,19.5,73
Chevrolet Vega,25,4,140,75,2542,17,74
Chevrolet Woody,24.5,4,98,60,2164,22.1,76
Chevy C10,13,8,350,145,4055,12,76
Chevy C20,10,8,307,200,4376,15,70
Chevy S-10,31,4,119,82,2720,19.4,82
Chrysler Cordoba,15.5,8,400,190,4325,12.2,77
Chrysler Lebaron Medallion,26,4,156,92,2585,14.5,82
Chrysler Lebaron Salon,17.6,6,225,85,3465,16.6,81
Chrysler Lebaron Town & Country (Wagon),18.5,8,360,150,3940,13,79
Chrysler New Yorker Brougham,13,8,440,215,4735,11,73
Chrysler Newport Royal,13,8,400,190,4422,12.5,72
Citroen DS-21 Pallas,,4,133,115,3090,17.5,70
Datsun 1200,35,4,72,69,1613,18,71
Datsun 200SX,23.9,4,119,97,2405,14.9,78
Datsun 200SX,32.9,4,119,100,2615,14.8,81
Datsun 210,31.8,4,85,65,2020,19.2,79
Datsun 210,37,4,85,65,1975,19.4,81
Datsun 210,40.8,4,85,65,2110,19.2,80
Datsun 280ZX,32.7,6,168,132,2910,11.4,80
Datsun 310 GX,38,4,91,67,1995,16.2,82
Datsun 310,37.2,4,86,65,2019,16.4,80
Datsun 510 (Wagon),28,4,97,92,2288,17,72
Datsun 510 Hatchback,37,4,119,92,2434,15,80
Datsun 510,27.2,4,119,97,2300,14.7,78
Datsun 610,22,4,108,94,2379,16.5,73
Datsun 710,24,4,119,97,2545,17,75
Datsun 710,32,4,83,61,2003,19,74
Datsun 810 Maxima,24.2,6,146,120,2930,13.8,81
Datsun 810,22,6,146,97,2815,14.5,77
Datsun B-210,32,4,85,70,1990,17,76
Datsun B210 GX,39.4,4,85,70,2070,18.6,78
Datsun B210,31,4,79,67,1950,19,74
Datsun F-10 Hatchback,33.5,4,85,70,1945,16.8,77
Datsun PL510,27,4,97,88,2130,14.5,70
Datsun PL510,27,4,97,88,2130,14.5,71
Dodge Aries SE,29,4,135,84,2525,16,82
Dodge Aries Wagon (Wagon),25.8,4,156,92,2620,14.4,81
Dodge Aspen 6,20.6,6,225,110,3360,16.6,79
Dodge Aspen SE,20,6,225,100,3651,17.7,76
Dodge Aspen,18.6,6,225,110,3620,18.7,78
Dodge Aspen,19.1,6,225,90,3381,18.7,80
Dodge Challenger SE,15,8,383,170,3563,10,70
Dodge Charger 2.2,36,4,135,84,2370,13,82
Dodge Colt (Wagon),28,4,98,80,2164,15,72
Dodge Colt Hardtop,25,4,97.5,80,2126,17,72
Dodge Colt Hatchback Custom,35.7,4,98,80,1915,14.4,79
Dodge Colt M/M,33.5,4,98,83,2075,15.9,77
Dodge Colt,26,4,98,79,2255,17.7,76
Dodge Colt,27.9,4,156,105,2800,14.4,80
Dodge Colt,28,4,90,75,2125,14.5,74
Dodge Coronet Brougham,16,8,318,150,4190,13,76
Dodge Coronet Custom (Wagon),14,8,318,150,4457,13.5,74
Dodge Coronet Custom,15,8,318,150,3777,12.5,73
Dodge D100,13,8,318,150,3755,14,76
Dodge D200,11,8,318,210,4382,13.5,70
Dodge Dart Custom,15,8,318,150,3399,11,73
Dodge Diplomat,19.4,8,318,140,3735,13.2,78
Dodge Magnum XE,17.5,8,318,140,4080,13.7,78
Dodge Monaco (Wagon),12,8,383,180,4955,11.5,71
Dodge Monaco Brougham,15.5,8,318,145,4140,13.7,77
Dodge Omni,30.9,4,105,75,2230,14.5,78
Dodge Rampage,32,4,135,84,2295,11.6,82
Dodge St. Regis,18.2,8,318,135,3830,15.2,79
Fiat 124 Sport Coupe,26,4,98,90,2265,15.5,73
Fiat 124 TC,26,4,116,75,2246,14,74
Fiat 124B,30,4,88,76,2065,14.5,71
Fiat 128,24,4,90,75,2108,15.5,74
Fiat 128,29,4,68,49,1867,19.5,73
Fiat 131,28,4,107,86,2464,15.5,76
Fiat Strada Custom,37.3,4,91,69,2130,14.7,79
Fiat X1.9,31,4,79,67,2000,16,74
Ford Capri II,25,4,140,92,2572,14.9,76
Ford Country Squire (Wagon),13,8,400,170,4746,12,71
Ford Country Squire (Wagon),15.5,8,351,142,4054,14.3,79
Ford Country,12,8,400,167,4906,12.5,73
Ford Escort 2H,29.9,4,98,65,2380,20.7,81
Ford Escort 4W,34.4,4,98,65,2045,16.2,81
Ford F108,13,8,302,130,3870,15,76
Ford F250,10,8,360,215,4615,14,70
Ford Fairmont (Auto),20.2,6,200,85,2965,15.8,78
Ford Fairmont (Man),25.1,4,140,88,2720,15.4,78
Ford Fairmont 4,22.3,4,140,88,2890,17.3,79
Ford Fairmont Futura,24,4,140,92,2865,16.4,82
Ford Fairmont,26.4,4,140,88,2870,18.1,80
Ford Fiesta,36.1,4,98,66,1800,14.4,78
Ford Futura,18.1,8,302,139,3205,11.2,78
Ford Galaxie 500,14,8,351,153,4129,13,72
Ford Galaxie 500,14,8,351,153,4154,13.5,71
Ford Galaxie 500,15,8,429,198,4341,10,70
Ford Gran Torino (Wagon),13,8,302,140,4294,16,72
Ford Gran Torino (Wagon),14,8,302,140,4638,16,74
Ford Gran Torino,14,8,302,137,4042,14.5,73
Ford Gran Torino,14.5,8,351,152,4215,12.8,76
Ford Gran Torino,16,8,302,140,4141,14,74
Ford Granada Ghia,18,6,250,78,3574,21,76
Ford Granada GL,20.2,6,200,88,3060,17.1,81
Ford Granada L,22,6,232,112,2835,14.7,82
Ford Granada,18.5,6,250,98,3525,19,77
Ford LTD Landau,17.6,8,302,129,3725,13.4,79
Ford LTD,13,8,351,158,4363,13,73
Ford LTD,14,8,351,148,4657,13.5,75
Ford Maverick,15,6,250,72,3158,19.5,75
Ford Maverick,18,6,250,88,3021,16.5,73
Ford Maverick,21,6,200,,2875,17,74
Ford Maverick,21,6,200,85,2587,16,70
Ford Maverick,24,6,200,81,3012,17.6,76
Ford Mustang Boss 302,,8,302,140,3353,8,70
Ford Mustang Cobra,23.6,4,140,,2905,14.3,80
Ford Mustang GL,27,4,140,86,2790,15.6,82
Ford Mustang II 2+2,25.5,4,140,89,2755,15.8,77
Ford Mustang II,13,8,302,129,3169,12,75
Ford Mustang,18,6,250,88,3139,14.5,71
Ford Pinto (Wagon),22,4,122,86,2395,16,72
Ford Pinto Runabout,21,4,122,86,2226,16.5,72
Ford Pinto,18,6,171,97,2984,14.5,75
Ford Pinto,19,4,122,85,2310,18.5,73
Ford Pinto,23,4,140,83,2639,17,75
Ford Pinto,25,4,98,,2046,19,71
Ford Pinto,26,4,122,80,2451,16.5,74
Ford Pinto,26.5,4,140,72,2565,13.6,76
Ford Ranger,28,4,120,79,2625,18.6,82
Ford Thunderbird,16,8,351,149,4335,14.5,77
Ford Torino (Wagon),,8,351,153,4034,11,70
Ford Torino 500,19,6,250,88,3302,15.5,71
Ford Torino,17,8,302,140,3449,10.5,70
Hi 1200D,9,8,304,193,4732,18.5,70
Honda Accord CVCC,31.5,4,98,68,2045,18.5,77
Honda Accord LX,29.5,4,98,68,2135,16.6,78
Honda Accord,32.4,4,107,72,2290,17,80
Honda Accord,36,4,107,75,2205,14.5,82
Honda Civic (Auto),32,4,91,67,1965,15.7,82
Honda Civic 1300,35.1,4,81,60,1760,16.1,81
Honda Civic 1500 GL,44.6,4,91,67,1850,13.8,80
Honda Civic CVCC,33,4,91,53,1795,17.5,75
Honda Civic CVCC,36.1,4,91,60,1800,16.4,78
Honda Civic,24,4,120,97,2489,15,74
Honda Civic,33,4,91,53,1795,17.4,76
Honda Civic,38,4,91,67,1965,15,82
Honda Prelude,33.7,4,107,75,2210,14.4,81
Maxda GLC Deluxe,34.1,4,86,65,1975,15.2,79
Maxda RX-3,18,3,70,90,2124,13.5,73
Mazda 626,31.3,4,120,75,2542,17.5,80
Mazda 626,31.6,4,120,74,2635,18.3,81
Mazda GLC 4,34.1,4,91,68,1985,16,81
Mazda GLC Custom L,37,4,91,68,2025,18.2,82
Mazda GLC Custom,31,4,91,68,1970,17.6,82
Mazda GLC Deluxe,32.8,4,78,52,1985,19.4,78
Mazda GLC,46.6,4,86,65,2110,17.9,80
Mazda RX-2 Coupe,19,3,70,97,2330,13.5,72
Mazda RX-4,21.5,3,80,110,2720,13.5,77
Mazda RX-7 Gs,23.7,3,70,100,2420,12.5,80
Mercedes-Benz 240D,30,4,146,67,3250,21.8,80
Mercedes-Benz 280S,16.5,6,168,120,3820,16.7,76
Mercedes-Benz 300D,25.4,5,183,77,3530,20.1,79
Mercury Capri 2000,23,4,122,86,2220,14,71
Mercury Capri V6,21,6,155,107,2472,14,73
Mercury Cougar Brougham,15,8,302,130,4295,14.9,77
Mercury Grand Marquis,16.5,8,351,138,3955,13.2,79
Mercury Lynx L,36,4,98,70,2125,17.3,82
Mercury Marquis Brougham,12,8,429,198,4952,11.5,73
Mercury Marquis,11,8,429,208,4633,11,72
Mercury Monarch Ghia,20.2,8,302,139,3570,12.8,78
Mercury Monarch,15,6,250,72,3432,21,75
Mercury Zephyr 6,19.8,6,200,85,2990,18.2,79
Mercury Zephyr,20.8,6,200,85,3070,16.7,78
Nissan Stanza XE,36,4,120,88,2160,14.5,82
Oldsmobile Cutlass Ciera (Diesel),38,6,262,85,3015,17,82
Oldsmobile Cutlass LS,26.6,8,350,105,3725,19,81
Oldsmobile Cutlass Salon Brougham,19.9,8,260,110,3365,15.5,78
Oldsmobile Cutlass Salon Brougham,23.9,8,260,90,3420,22.2,79
Oldsmobile Cutlass Supreme,17,8,260,110,4060,19,77
Oldsmobile Delta 88 Royale,12,8,350,160,4456,13.5,72
Oldsmobile Omega Brougham,26.8,6,173,115,2700,12.9,79
Oldsmobile Omega,11,8,350,180,3664,11,73
Oldsmobile Starfire SX,23.8,4,151,85,2855,17.6,78
Oldsmobile Vista Cruiser,12,8,350,180,4499,12.5,73
Opel 1900,25,4,116,81,2220,16.9,76
Opel 1900,28,4,116,90,2123,14,71
Opel Manta,24,4,116,75,2158,15.5,73
Opel Manta,26,4,97,78,2300,14.5,74
Peugeot 304,30,4,79,70,2074,19.5,71
Peugeot 504 (Wagon),21,4,120,87,2979,19.5,72
Peugeot 504,19,4,120,88,3270,21.9,76
Peugeot 504,23,4,120,88,2957,17,75
Peugeot 504,25,4,110,87,2672,17.5,70
Peugeot 504,27.2,4,141,71,3190,24.8,79
Peugeot 505S Turbo Diesel,28.1,4,141,80,3230,20.4,81
Peugeot 604SL,16.2,6,163,133,3410,15.8,78
Plymouth Arrow GS,25.5,4,122,96,2300,15.5,77
Plymouth Barracuda 340,14,8,340,160,3609,8,70
Plymouth Champ,39,4,86,64,1875,16.4,81
Plymouth Cricket,26,4,91,70,1955,20.5,71
Plymouth Custom Suburb,13,8,360,170,4654,13,73
Plymouth Duster,20,6,198,95,3102,16.5,74
Plymouth Duster,22,6,198,95,2833,15.5,70
Plymouth Duster,23,6,198,95,2904,16,73
Plymouth Fury Gran Sedan,14,8,318,150,4237,14.5,73
Plymouth Fury III,14,8,318,150,4096,13,71
Plymouth Fury III,14,8,440,215,4312,8.5,70
Plymouth Fury III,15,8,318,150,4135,13.5,72
Plymouth Fury,18,6,225,95,3785,19,75
Plymouth Grand Fury,16,8,318,150,4498,14.5,75
Plymouth Horizon 4,34.7,4,105,63,2215,14.9,81
Plymouth Horizon Miser,38,4,105,63,2125,14.7,82
Plymouth Horizon TC3,34.5,4,105,70,2150,14.9,79
Plymouth Horizon,34.2,4,105,70,2200,13.2,79
Plymouth Reliant,27.2,4,135,84,2490,15.7,81
Plymouth Reliant,30,4,135,84,2385,12.9,81
Plymouth Sapporo,23.2,4,156,105,2745,16.7,78
Plymouth Satellite (Wagon),,8,383,175,4166,10.5,70
Plymouth Satellite Custom (Wagon),14,8,318,150,4077,14,72
Plymouth Satellite Custom,16,6,225,105,3439,15.5,71
Plymouth Satellite Sebring,18,6,225,105,3613,16.5,74
Plymouth Satellite,18,8,318,150,3436,11,70
Plymouth Valiant Custom,19,6,225,95,3264,16,75
Plymouth Valiant,18,6,225,105,3121,16.5,73
Plymouth Valiant,22,6,225,100,3233,15.4,76
Plymouth Volare Custom,19,6,225,100,3630,17.7,77
Plymouth Volare Premier V8,13,8,318,150,3940,13.2,76
Plymouth Volare,20.5,6,225,100,3430,17.2,78
Pontiac Astro,23,4,140,78,2592,18.5,75
Pontiac Catalina Brougham,14,8,400,175,4464,11.5,71
Pontiac Catalina,14,8,400,175,4385,12,72
Pontiac Catalina,14,8,455,225,4425,10,70
Pontiac Catalina,16,8,400,170,4668,11.5,75
Pontiac Firebird,19,6,250,100,3282,15,71
Pontiac Grand Prix Lj,16,8,400,180,4220,11.1,77
Pontiac Grand Prix,16,8,400,230,4278,9.5,73
Pontiac J2000 Se Hatchback,31,4,112,85,2575,16.2,82
Pontiac Lemans V6,21.5,6,231,115,3245,15.4,79
Pontiac Phoenix LJ,19.2,6,231,105,3535,19.2,78
Pontiac Phoenix,27,4,151,90,2735,18,82
Pontiac Phoenix,33.5,4,151,90,2556,13.2,79
Pontiac Safari (Wagon),13,8,400,175,5140,12,71
Pontiac Sunbird Coupe,24.5,4,151,88,2740,16,77
Pontiac Ventura Sj,18.5,6,250,110,3645,16.2,76
Renault 12 (Wagon),26,4,96,69,2189,18,72
Renault 12TL,27,4,101,83,2202,15.3,76
Renault 18I,34.5,4,100,,2320,15.8,81
Renault 5 Gtl,36,4,79,58,1825,18.6,77
Renault Lecar Deluxe,40.9,4,85,,1835,17.3,80
Saab 900S,,4,121,110,2800,15.4,81
Saab 99E,25,4,104,95,2375,17.5,70
Saab 99GLE,21.6,4,121,115,2795,15.7,78
Saab 99LE,24,4,121,110,2660,14,73
Saab 99LE,25,4,121,115,2671,13.5,75
Subaru DL,30,4,97,67,1985,16.4,77
Subaru DL,33.8,4,97,67,2145,18,80
Subaru,26,4,108,93,2391,15.5,74
Subaru,32.3,4,97,67,2065,17.8,81
Toyota Carina,20,4,97,88,2279,19,73
Toyota Celica GT Liftback,21.1,4,134,95,2515,14.8,78
Toyota Celica GT,32,4,144,96,2665,13.9,82
Toyota Corolla 1200,31,4,71,65,1773,19,71
Toyota Corolla 1200,32,4,71,65,1836,21,74
Toyota Corolla 1600 (Wagon),27,4,97,88,2100,16.5,72
Toyota Corolla Liftback,26,4,97,75,2265,18.2,77
Toyota Corolla Tercel,38.1,4,89,60,1968,18.8,80
Toyota Corolla,28,4,97,75,2155,16.4,76
Toyota Corolla,29,4,97,75,2171,16,75
Toyota Corolla,32.2,4,108,75,2265,15.2,80
Toyota Corolla,32.4,4,108,75,2350,16.8,81
Toyota Corolla,34,4,108,70,2245,16.9,82
Toyota Corona Hardtop,24,4,113,95,2278,15.5,72
Toyota Corona Liftback,29.8,4,134,90,2711,15.5,80
Toyota Corona Mark II,24,4,113,95,2372,15,70
Toyota Corona,24,4,134,96,2702,13.5,75
Toyota Corona,25,4,113,95,2228,14,71
Toyota Corona,27.5,4,134,95,2560,14.2,78
Toyota Corona,31,4,76,52,1649,16.5,74
Toyota Cressida,25.4,6,168,116,2900,12.6,81
Toyota Mark II,19,6,156,108,2930,15.5,76
Toyota Mark II,20,6,156,122,2807,13.5,73
Toyota Starlet,39.1,4,79,58,1755,16.9,81
Toyota Tercel,37.7,4,89,62,2050,17.3,81
Toyouta Corona Mark II (Wagon),23,4,120,97,2506,14.5,72
Triumph TR7 Coupe,35,4,122,88,2500,15.1,80
Vokswagen Rabbit,29.8,4,89,62,1845,15.3,80
Volkswagen 1131 Deluxe Sedan,26,4,97,46,1835,20.5,70
Volkswagen 411 (Wagon),22,4,121,76,2511,18,72
Volkswagen Dasher (Diesel),43.4,4,90,48,2335,23.7,80
Volkswagen Dasher,25,4,90,71,2223,16.5,75
Volkswagen Dasher,26,4,79,67,1963,15.5,74
Volkswagen Dasher,30.5,4,97,78,2190,14.1,77
Volkswagen Jetta,33,4,105,74,2190,14.2,81
Volkswagen Model 111,27,4,97,60,1834,19,71
Volkswagen Pickup,44,4,97,52,2130,24.6,82
Volkswagen Rabbit C (Diesel),44.3,4,90,48,2085,21.7,80
Volkswagen Rabbit Custom Diesel,43.1,4,90,48,1985,21.5,78
Volkswagen Rabbit Custom,29,4,97,78,1940,14.5,77
Volkswagen Rabbit Custom,31.9,4,89,71,1925,14,79
Volkswagen Rabbit L,36,4,105,74,1980,15.3,82
Volkswagen Rabbit,29,4,90,70,1937,14,75
Volkswagen Rabbit,29,4,90,70,1937,14.2,76
Volkswagen Rabbit,29.5,4,97,71,1825,12.2,76
Volkswagen Rabbit,41.5,4,98,76,2144,14.7,80
Volkswagen Scirocco,31.5,4,89,71,1990,14.9,78
Volkswagen Super Beetle 117,,4,97,48,1978,20,71
Volkswagen Super Beetle,26,4,97,46,1950,21,73
Volkswagen Type 3,23,4,97,54,2254,23.5,72
Volvo 144EA,19,4,121,112,2868,15.5,73
Volvo 145E (Wagon),18,4,121,112,2933,14.5,72
Volvo 244DL,22,4,121,98,2945,14.5,75
Volvo 245,20,4,130,102,3150,15.7,76
Volvo 264GL,17,6,163,125,3140,13.6,78
Volvo Diesel,30.7,6,145,76,3160,19.6,81
1 name economy (mpg) cylinders displacement (cc) power (hp) weight (lb) 0-60 mph (s) year
2 AMC Ambassador Brougham 13 8 360 175 3821 11 73
3 AMC Ambassador DPL 15 8 390 190 3850 8.5 70
4 AMC Ambassador SST 17 8 304 150 3672 11.5 72
5 AMC Concord DL 6 20.2 6 232 90 3265 18.2 79
6 AMC Concord DL 18.1 6 258 120 3410 15.1 78
7 AMC Concord DL 23 4 151 3035 20.5 82
8 AMC Concord 19.4 6 232 90 3210 17.2 78
9 AMC Concord 24.3 4 151 90 3003 20.1 80
10 AMC Gremlin 18 6 232 100 2789 15 73
11 AMC Gremlin 19 6 232 100 2634 13 71
12 AMC Gremlin 20 6 232 100 2914 16 75
13 AMC Gremlin 21 6 199 90 2648 15 70
14 AMC Hornet Sportabout (Wagon) 18 6 258 110 2962 13.5 71
15 AMC Hornet 18 6 199 97 2774 15.5 70
16 AMC Hornet 18 6 232 100 2945 16 73
17 AMC Hornet 19 6 232 100 2901 16 74
18 AMC Hornet 22.5 6 232 90 3085 17.6 76
19 AMC Matador (Wagon) 14 8 304 150 4257 15.5 74
20 AMC Matador (Wagon) 15 8 304 150 3892 12.5 72
21 AMC Matador 14 8 304 150 3672 11.5 73
22 AMC Matador 15 6 258 110 3730 19 75
23 AMC Matador 15.5 8 304 120 3962 13.9 76
24 AMC Matador 16 6 258 110 3632 18 74
25 AMC Matador 18 6 232 100 3288 15.5 71
26 AMC Pacer D/L 17.5 6 258 95 3193 17.8 76
27 AMC Pacer 19 6 232 90 3211 17 75
28 AMC Rebel SST (Wagon) 8 360 175 3850 11 70
29 AMC Rebel SST 16 8 304 150 3433 12 70
30 AMC Spirit DL 27.4 4 121 80 2670 15 79
31 Audi 100 LS 20 4 114 91 2582 14 73
32 Audi 100 LS 23 4 115 95 2694 15 75
33 Audi 100 LS 24 4 107 90 2430 14.5 70
34 Audi 4000 34.3 4 97 78 2188 15.8 80
35 Audi 5000 20.3 5 131 103 2830 15.9 78
36 Audi 5000S (Diesel) 36.4 5 121 67 2950 19.9 80
37 Audi Fox 29 4 98 83 2219 16.5 74
38 BMW 2002 26 4 121 113 2234 12.5 70
39 BMW 320i 21.5 4 121 110 2600 12.8 77
40 Buick Century 350 13 8 350 175 4100 13 73
41 Buick Century Limited 25 6 181 110 2945 16.4 82
42 Buick Century Luxus (Wagon) 13 8 350 150 4699 14.5 74
43 Buick Century Special 20.6 6 231 105 3380 15.8 78
44 Buick Century 17 6 231 110 3907 21 75
45 Buick Century 22.4 6 231 110 3415 15.8 81
46 Buick Electra 225 Custom 12 8 455 225 4951 11 73
47 Buick Estate Wagon (Wagon) 14 8 455 225 3086 10 70
48 Buick Estate Wagon (Wagon) 16.9 8 350 155 4360 14.9 79
49 Buick Lesabre Custom 13 8 350 155 4502 13.5 72
50 Buick Opel Isuzu Deluxe 30 4 111 80 2155 14.8 77
51 Buick Regal Sport Coupe (Turbo) 17.7 6 231 165 3445 13.4 78
52 Buick Skyhawk 21 6 231 110 3039 15 75
53 Buick Skylark 320 15 8 350 165 3693 11.5 70
54 Buick Skylark Limited 28.4 4 151 90 2670 16 79
55 Buick Skylark 20.5 6 231 105 3425 16.9 77
56 Buick Skylark 26.6 4 151 84 2635 16.4 81
57 Cadillac Eldorado 23 8 350 125 3900 17.4 79
58 Cadillac Seville 16.5 8 350 180 4380 12.1 76
59 Chevroelt Chevelle Malibu 16 6 250 105 3897 18.5 75
60 Chevrolet Bel Air 15 8 350 145 4440 14 75
61 Chevrolet Camaro 27 4 151 90 2950 17.3 82
62 Chevrolet Caprice Classic 13 8 400 150 4464 12 73
63 Chevrolet Caprice Classic 17 8 305 130 3840 15.4 79
64 Chevrolet Caprice Classic 17.5 8 305 145 3880 12.5 77
65 Chevrolet Cavalier 2-Door 34 4 112 88 2395 18 82
66 Chevrolet Cavalier Wagon 27 4 112 88 2640 18.6 82
67 Chevrolet Cavalier 28 4 112 88 2605 19.6 82
68 Chevrolet Chevelle Concours (Wagon) 8 350 165 4142 11.5 70
69 Chevrolet Chevelle Concours (Wagon) 13 8 307 130 4098 14 72
70 Chevrolet Chevelle Malibu Classic 16 6 250 100 3781 17 74
71 Chevrolet Chevelle Malibu Classic 17.5 8 305 140 4215 13 76
72 Chevrolet Chevelle Malibu 17 6 250 100 3329 15.5 71
73 Chevrolet Chevelle Malibu 18 8 307 130 3504 12 70
74 Chevrolet Chevette 29 4 85 52 2035 22.2 76
75 Chevrolet Chevette 30 4 98 68 2155 16.5 78
76 Chevrolet Chevette 30.5 4 98 63 2051 17 77
77 Chevrolet Chevette 32.1 4 98 70 2120 15.5 80
78 Chevrolet Citation 23.5 6 173 110 2725 12.6 81
79 Chevrolet Citation 28 4 151 90 2678 16.5 80
80 Chevrolet Citation 28.8 6 173 115 2595 11.3 79
81 Chevrolet Concours 17.5 6 250 110 3520 16.4 77
82 Chevrolet Impala 11 8 400 150 4997 14 73
83 Chevrolet Impala 13 8 350 165 4274 12 72
84 Chevrolet Impala 14 8 350 165 4209 12 71
85 Chevrolet Impala 14 8 454 220 4354 9 70
86 Chevrolet Malibu Classic (Wagon) 19.2 8 267 125 3605 15 79
87 Chevrolet Malibu 13 8 350 145 3988 13 73
88 Chevrolet Malibu 20.5 6 200 95 3155 18.2 78
89 Chevrolet Monte Carlo Landau 15.5 8 350 170 4165 11.4 77
90 Chevrolet Monte Carlo Landau 19.2 8 305 145 3425 13.2 78
91 Chevrolet Monte Carlo S 15 8 350 145 4082 13 73
92 Chevrolet Monte Carlo 15 8 400 150 3761 9.5 70
93 Chevrolet Monza 2+2 20 8 262 110 3221 13.5 75
94 Chevrolet Nova Custom 16 6 250 100 3278 18 73
95 Chevrolet Nova 15 6 250 100 3336 17 74
96 Chevrolet Nova 18 6 250 105 3459 16 75
97 Chevrolet Nova 22 6 250 105 3353 14.5 76
98 Chevrolet Vega (Wagon) 22 4 140 72 2408 19 71
99 Chevrolet Vega 2300 28 4 140 90 2264 15.5 71
100 Chevrolet Vega 20 4 140 90 2408 19.5 72
101 Chevrolet Vega 21 4 140 72 2401 19.5 73
102 Chevrolet Vega 25 4 140 75 2542 17 74
103 Chevrolet Woody 24.5 4 98 60 2164 22.1 76
104 Chevy C10 13 8 350 145 4055 12 76
105 Chevy C20 10 8 307 200 4376 15 70
106 Chevy S-10 31 4 119 82 2720 19.4 82
107 Chrysler Cordoba 15.5 8 400 190 4325 12.2 77
108 Chrysler Lebaron Medallion 26 4 156 92 2585 14.5 82
109 Chrysler Lebaron Salon 17.6 6 225 85 3465 16.6 81
110 Chrysler Lebaron Town & Country (Wagon) 18.5 8 360 150 3940 13 79
111 Chrysler New Yorker Brougham 13 8 440 215 4735 11 73
112 Chrysler Newport Royal 13 8 400 190 4422 12.5 72
113 Citroen DS-21 Pallas 4 133 115 3090 17.5 70
114 Datsun 1200 35 4 72 69 1613 18 71
115 Datsun 200SX 23.9 4 119 97 2405 14.9 78
116 Datsun 200SX 32.9 4 119 100 2615 14.8 81
117 Datsun 210 31.8 4 85 65 2020 19.2 79
118 Datsun 210 37 4 85 65 1975 19.4 81
119 Datsun 210 40.8 4 85 65 2110 19.2 80
120 Datsun 280ZX 32.7 6 168 132 2910 11.4 80
121 Datsun 310 GX 38 4 91 67 1995 16.2 82
122 Datsun 310 37.2 4 86 65 2019 16.4 80
123 Datsun 510 (Wagon) 28 4 97 92 2288 17 72
124 Datsun 510 Hatchback 37 4 119 92 2434 15 80
125 Datsun 510 27.2 4 119 97 2300 14.7 78
126 Datsun 610 22 4 108 94 2379 16.5 73
127 Datsun 710 24 4 119 97 2545 17 75
128 Datsun 710 32 4 83 61 2003 19 74
129 Datsun 810 Maxima 24.2 6 146 120 2930 13.8 81
130 Datsun 810 22 6 146 97 2815 14.5 77
131 Datsun B-210 32 4 85 70 1990 17 76
132 Datsun B210 GX 39.4 4 85 70 2070 18.6 78
133 Datsun B210 31 4 79 67 1950 19 74
134 Datsun F-10 Hatchback 33.5 4 85 70 1945 16.8 77
135 Datsun PL510 27 4 97 88 2130 14.5 70
136 Datsun PL510 27 4 97 88 2130 14.5 71
137 Dodge Aries SE 29 4 135 84 2525 16 82
138 Dodge Aries Wagon (Wagon) 25.8 4 156 92 2620 14.4 81
139 Dodge Aspen 6 20.6 6 225 110 3360 16.6 79
140 Dodge Aspen SE 20 6 225 100 3651 17.7 76
141 Dodge Aspen 18.6 6 225 110 3620 18.7 78
142 Dodge Aspen 19.1 6 225 90 3381 18.7 80
143 Dodge Challenger SE 15 8 383 170 3563 10 70
144 Dodge Charger 2.2 36 4 135 84 2370 13 82
145 Dodge Colt (Wagon) 28 4 98 80 2164 15 72
146 Dodge Colt Hardtop 25 4 97.5 80 2126 17 72
147 Dodge Colt Hatchback Custom 35.7 4 98 80 1915 14.4 79
148 Dodge Colt M/M 33.5 4 98 83 2075 15.9 77
149 Dodge Colt 26 4 98 79 2255 17.7 76
150 Dodge Colt 27.9 4 156 105 2800 14.4 80
151 Dodge Colt 28 4 90 75 2125 14.5 74
152 Dodge Coronet Brougham 16 8 318 150 4190 13 76
153 Dodge Coronet Custom (Wagon) 14 8 318 150 4457 13.5 74
154 Dodge Coronet Custom 15 8 318 150 3777 12.5 73
155 Dodge D100 13 8 318 150 3755 14 76
156 Dodge D200 11 8 318 210 4382 13.5 70
157 Dodge Dart Custom 15 8 318 150 3399 11 73
158 Dodge Diplomat 19.4 8 318 140 3735 13.2 78
159 Dodge Magnum XE 17.5 8 318 140 4080 13.7 78
160 Dodge Monaco (Wagon) 12 8 383 180 4955 11.5 71
161 Dodge Monaco Brougham 15.5 8 318 145 4140 13.7 77
162 Dodge Omni 30.9 4 105 75 2230 14.5 78
163 Dodge Rampage 32 4 135 84 2295 11.6 82
164 Dodge St. Regis 18.2 8 318 135 3830 15.2 79
165 Fiat 124 Sport Coupe 26 4 98 90 2265 15.5 73
166 Fiat 124 TC 26 4 116 75 2246 14 74
167 Fiat 124B 30 4 88 76 2065 14.5 71
168 Fiat 128 24 4 90 75 2108 15.5 74
169 Fiat 128 29 4 68 49 1867 19.5 73
170 Fiat 131 28 4 107 86 2464 15.5 76
171 Fiat Strada Custom 37.3 4 91 69 2130 14.7 79
172 Fiat X1.9 31 4 79 67 2000 16 74
173 Ford Capri II 25 4 140 92 2572 14.9 76
174 Ford Country Squire (Wagon) 13 8 400 170 4746 12 71
175 Ford Country Squire (Wagon) 15.5 8 351 142 4054 14.3 79
176 Ford Country 12 8 400 167 4906 12.5 73
177 Ford Escort 2H 29.9 4 98 65 2380 20.7 81
178 Ford Escort 4W 34.4 4 98 65 2045 16.2 81
179 Ford F108 13 8 302 130 3870 15 76
180 Ford F250 10 8 360 215 4615 14 70
181 Ford Fairmont (Auto) 20.2 6 200 85 2965 15.8 78
182 Ford Fairmont (Man) 25.1 4 140 88 2720 15.4 78
183 Ford Fairmont 4 22.3 4 140 88 2890 17.3 79
184 Ford Fairmont Futura 24 4 140 92 2865 16.4 82
185 Ford Fairmont 26.4 4 140 88 2870 18.1 80
186 Ford Fiesta 36.1 4 98 66 1800 14.4 78
187 Ford Futura 18.1 8 302 139 3205 11.2 78
188 Ford Galaxie 500 14 8 351 153 4129 13 72
189 Ford Galaxie 500 14 8 351 153 4154 13.5 71
190 Ford Galaxie 500 15 8 429 198 4341 10 70
191 Ford Gran Torino (Wagon) 13 8 302 140 4294 16 72
192 Ford Gran Torino (Wagon) 14 8 302 140 4638 16 74
193 Ford Gran Torino 14 8 302 137 4042 14.5 73
194 Ford Gran Torino 14.5 8 351 152 4215 12.8 76
195 Ford Gran Torino 16 8 302 140 4141 14 74
196 Ford Granada Ghia 18 6 250 78 3574 21 76
197 Ford Granada GL 20.2 6 200 88 3060 17.1 81
198 Ford Granada L 22 6 232 112 2835 14.7 82
199 Ford Granada 18.5 6 250 98 3525 19 77
200 Ford LTD Landau 17.6 8 302 129 3725 13.4 79
201 Ford LTD 13 8 351 158 4363 13 73
202 Ford LTD 14 8 351 148 4657 13.5 75
203 Ford Maverick 15 6 250 72 3158 19.5 75
204 Ford Maverick 18 6 250 88 3021 16.5 73
205 Ford Maverick 21 6 200 2875 17 74
206 Ford Maverick 21 6 200 85 2587 16 70
207 Ford Maverick 24 6 200 81 3012 17.6 76
208 Ford Mustang Boss 302 8 302 140 3353 8 70
209 Ford Mustang Cobra 23.6 4 140 2905 14.3 80
210 Ford Mustang GL 27 4 140 86 2790 15.6 82
211 Ford Mustang II 2+2 25.5 4 140 89 2755 15.8 77
212 Ford Mustang II 13 8 302 129 3169 12 75
213 Ford Mustang 18 6 250 88 3139 14.5 71
214 Ford Pinto (Wagon) 22 4 122 86 2395 16 72
215 Ford Pinto Runabout 21 4 122 86 2226 16.5 72
216 Ford Pinto 18 6 171 97 2984 14.5 75
217 Ford Pinto 19 4 122 85 2310 18.5 73
218 Ford Pinto 23 4 140 83 2639 17 75
219 Ford Pinto 25 4 98 2046 19 71
220 Ford Pinto 26 4 122 80 2451 16.5 74
221 Ford Pinto 26.5 4 140 72 2565 13.6 76
222 Ford Ranger 28 4 120 79 2625 18.6 82
223 Ford Thunderbird 16 8 351 149 4335 14.5 77
224 Ford Torino (Wagon) 8 351 153 4034 11 70
225 Ford Torino 500 19 6 250 88 3302 15.5 71
226 Ford Torino 17 8 302 140 3449 10.5 70
227 Hi 1200D 9 8 304 193 4732 18.5 70
228 Honda Accord CVCC 31.5 4 98 68 2045 18.5 77
229 Honda Accord LX 29.5 4 98 68 2135 16.6 78
230 Honda Accord 32.4 4 107 72 2290 17 80
231 Honda Accord 36 4 107 75 2205 14.5 82
232 Honda Civic (Auto) 32 4 91 67 1965 15.7 82
233 Honda Civic 1300 35.1 4 81 60 1760 16.1 81
234 Honda Civic 1500 GL 44.6 4 91 67 1850 13.8 80
235 Honda Civic CVCC 33 4 91 53 1795 17.5 75
236 Honda Civic CVCC 36.1 4 91 60 1800 16.4 78
237 Honda Civic 24 4 120 97 2489 15 74
238 Honda Civic 33 4 91 53 1795 17.4 76
239 Honda Civic 38 4 91 67 1965 15 82
240 Honda Prelude 33.7 4 107 75 2210 14.4 81
241 Maxda GLC Deluxe 34.1 4 86 65 1975 15.2 79
242 Maxda RX-3 18 3 70 90 2124 13.5 73
243 Mazda 626 31.3 4 120 75 2542 17.5 80
244 Mazda 626 31.6 4 120 74 2635 18.3 81
245 Mazda GLC 4 34.1 4 91 68 1985 16 81
246 Mazda GLC Custom L 37 4 91 68 2025 18.2 82
247 Mazda GLC Custom 31 4 91 68 1970 17.6 82
248 Mazda GLC Deluxe 32.8 4 78 52 1985 19.4 78
249 Mazda GLC 46.6 4 86 65 2110 17.9 80
250 Mazda RX-2 Coupe 19 3 70 97 2330 13.5 72
251 Mazda RX-4 21.5 3 80 110 2720 13.5 77
252 Mazda RX-7 Gs 23.7 3 70 100 2420 12.5 80
253 Mercedes-Benz 240D 30 4 146 67 3250 21.8 80
254 Mercedes-Benz 280S 16.5 6 168 120 3820 16.7 76
255 Mercedes-Benz 300D 25.4 5 183 77 3530 20.1 79
256 Mercury Capri 2000 23 4 122 86 2220 14 71
257 Mercury Capri V6 21 6 155 107 2472 14 73
258 Mercury Cougar Brougham 15 8 302 130 4295 14.9 77
259 Mercury Grand Marquis 16.5 8 351 138 3955 13.2 79
260 Mercury Lynx L 36 4 98 70 2125 17.3 82
261 Mercury Marquis Brougham 12 8 429 198 4952 11.5 73
262 Mercury Marquis 11 8 429 208 4633 11 72
263 Mercury Monarch Ghia 20.2 8 302 139 3570 12.8 78
264 Mercury Monarch 15 6 250 72 3432 21 75
265 Mercury Zephyr 6 19.8 6 200 85 2990 18.2 79
266 Mercury Zephyr 20.8 6 200 85 3070 16.7 78
267 Nissan Stanza XE 36 4 120 88 2160 14.5 82
268 Oldsmobile Cutlass Ciera (Diesel) 38 6 262 85 3015 17 82
269 Oldsmobile Cutlass LS 26.6 8 350 105 3725 19 81
270 Oldsmobile Cutlass Salon Brougham 19.9 8 260 110 3365 15.5 78
271 Oldsmobile Cutlass Salon Brougham 23.9 8 260 90 3420 22.2 79
272 Oldsmobile Cutlass Supreme 17 8 260 110 4060 19 77
273 Oldsmobile Delta 88 Royale 12 8 350 160 4456 13.5 72
274 Oldsmobile Omega Brougham 26.8 6 173 115 2700 12.9 79
275 Oldsmobile Omega 11 8 350 180 3664 11 73
276 Oldsmobile Starfire SX 23.8 4 151 85 2855 17.6 78
277 Oldsmobile Vista Cruiser 12 8 350 180 4499 12.5 73
278 Opel 1900 25 4 116 81 2220 16.9 76
279 Opel 1900 28 4 116 90 2123 14 71
280 Opel Manta 24 4 116 75 2158 15.5 73
281 Opel Manta 26 4 97 78 2300 14.5 74
282 Peugeot 304 30 4 79 70 2074 19.5 71
283 Peugeot 504 (Wagon) 21 4 120 87 2979 19.5 72
284 Peugeot 504 19 4 120 88 3270 21.9 76
285 Peugeot 504 23 4 120 88 2957 17 75
286 Peugeot 504 25 4 110 87 2672 17.5 70
287 Peugeot 504 27.2 4 141 71 3190 24.8 79
288 Peugeot 505S Turbo Diesel 28.1 4 141 80 3230 20.4 81
289 Peugeot 604SL 16.2 6 163 133 3410 15.8 78
290 Plymouth Arrow GS 25.5 4 122 96 2300 15.5 77
291 Plymouth Barracuda 340 14 8 340 160 3609 8 70
292 Plymouth Champ 39 4 86 64 1875 16.4 81
293 Plymouth Cricket 26 4 91 70 1955 20.5 71
294 Plymouth Custom Suburb 13 8 360 170 4654 13 73
295 Plymouth Duster 20 6 198 95 3102 16.5 74
296 Plymouth Duster 22 6 198 95 2833 15.5 70
297 Plymouth Duster 23 6 198 95 2904 16 73
298 Plymouth Fury Gran Sedan 14 8 318 150 4237 14.5 73
299 Plymouth Fury III 14 8 318 150 4096 13 71
300 Plymouth Fury III 14 8 440 215 4312 8.5 70
301 Plymouth Fury III 15 8 318 150 4135 13.5 72
302 Plymouth Fury 18 6 225 95 3785 19 75
303 Plymouth Grand Fury 16 8 318 150 4498 14.5 75
304 Plymouth Horizon 4 34.7 4 105 63 2215 14.9 81
305 Plymouth Horizon Miser 38 4 105 63 2125 14.7 82
306 Plymouth Horizon TC3 34.5 4 105 70 2150 14.9 79
307 Plymouth Horizon 34.2 4 105 70 2200 13.2 79
308 Plymouth Reliant 27.2 4 135 84 2490 15.7 81
309 Plymouth Reliant 30 4 135 84 2385 12.9 81
310 Plymouth Sapporo 23.2 4 156 105 2745 16.7 78
311 Plymouth Satellite (Wagon) 8 383 175 4166 10.5 70
312 Plymouth Satellite Custom (Wagon) 14 8 318 150 4077 14 72
313 Plymouth Satellite Custom 16 6 225 105 3439 15.5 71
314 Plymouth Satellite Sebring 18 6 225 105 3613 16.5 74
315 Plymouth Satellite 18 8 318 150 3436 11 70
316 Plymouth Valiant Custom 19 6 225 95 3264 16 75
317 Plymouth Valiant 18 6 225 105 3121 16.5 73
318 Plymouth Valiant 22 6 225 100 3233 15.4 76
319 Plymouth Volare Custom 19 6 225 100 3630 17.7 77
320 Plymouth Volare Premier V8 13 8 318 150 3940 13.2 76
321 Plymouth Volare 20.5 6 225 100 3430 17.2 78
322 Pontiac Astro 23 4 140 78 2592 18.5 75
323 Pontiac Catalina Brougham 14 8 400 175 4464 11.5 71
324 Pontiac Catalina 14 8 400 175 4385 12 72
325 Pontiac Catalina 14 8 455 225 4425 10 70
326 Pontiac Catalina 16 8 400 170 4668 11.5 75
327 Pontiac Firebird 19 6 250 100 3282 15 71
328 Pontiac Grand Prix Lj 16 8 400 180 4220 11.1 77
329 Pontiac Grand Prix 16 8 400 230 4278 9.5 73
330 Pontiac J2000 Se Hatchback 31 4 112 85 2575 16.2 82
331 Pontiac Lemans V6 21.5 6 231 115 3245 15.4 79
332 Pontiac Phoenix LJ 19.2 6 231 105 3535 19.2 78
333 Pontiac Phoenix 27 4 151 90 2735 18 82
334 Pontiac Phoenix 33.5 4 151 90 2556 13.2 79
335 Pontiac Safari (Wagon) 13 8 400 175 5140 12 71
336 Pontiac Sunbird Coupe 24.5 4 151 88 2740 16 77
337 Pontiac Ventura Sj 18.5 6 250 110 3645 16.2 76
338 Renault 12 (Wagon) 26 4 96 69 2189 18 72
339 Renault 12TL 27 4 101 83 2202 15.3 76
340 Renault 18I 34.5 4 100 2320 15.8 81
341 Renault 5 Gtl 36 4 79 58 1825 18.6 77
342 Renault Lecar Deluxe 40.9 4 85 1835 17.3 80
343 Saab 900S 4 121 110 2800 15.4 81
344 Saab 99E 25 4 104 95 2375 17.5 70
345 Saab 99GLE 21.6 4 121 115 2795 15.7 78
346 Saab 99LE 24 4 121 110 2660 14 73
347 Saab 99LE 25 4 121 115 2671 13.5 75
348 Subaru DL 30 4 97 67 1985 16.4 77
349 Subaru DL 33.8 4 97 67 2145 18 80
350 Subaru 26 4 108 93 2391 15.5 74
351 Subaru 32.3 4 97 67 2065 17.8 81
352 Toyota Carina 20 4 97 88 2279 19 73
353 Toyota Celica GT Liftback 21.1 4 134 95 2515 14.8 78
354 Toyota Celica GT 32 4 144 96 2665 13.9 82
355 Toyota Corolla 1200 31 4 71 65 1773 19 71
356 Toyota Corolla 1200 32 4 71 65 1836 21 74
357 Toyota Corolla 1600 (Wagon) 27 4 97 88 2100 16.5 72
358 Toyota Corolla Liftback 26 4 97 75 2265 18.2 77
359 Toyota Corolla Tercel 38.1 4 89 60 1968 18.8 80
360 Toyota Corolla 28 4 97 75 2155 16.4 76
361 Toyota Corolla 29 4 97 75 2171 16 75
362 Toyota Corolla 32.2 4 108 75 2265 15.2 80
363 Toyota Corolla 32.4 4 108 75 2350 16.8 81
364 Toyota Corolla 34 4 108 70 2245 16.9 82
365 Toyota Corona Hardtop 24 4 113 95 2278 15.5 72
366 Toyota Corona Liftback 29.8 4 134 90 2711 15.5 80
367 Toyota Corona Mark II 24 4 113 95 2372 15 70
368 Toyota Corona 24 4 134 96 2702 13.5 75
369 Toyota Corona 25 4 113 95 2228 14 71
370 Toyota Corona 27.5 4 134 95 2560 14.2 78
371 Toyota Corona 31 4 76 52 1649 16.5 74
372 Toyota Cressida 25.4 6 168 116 2900 12.6 81
373 Toyota Mark II 19 6 156 108 2930 15.5 76
374 Toyota Mark II 20 6 156 122 2807 13.5 73
375 Toyota Starlet 39.1 4 79 58 1755 16.9 81
376 Toyota Tercel 37.7 4 89 62 2050 17.3 81
377 Toyouta Corona Mark II (Wagon) 23 4 120 97 2506 14.5 72
378 Triumph TR7 Coupe 35 4 122 88 2500 15.1 80
379 Vokswagen Rabbit 29.8 4 89 62 1845 15.3 80
380 Volkswagen 1131 Deluxe Sedan 26 4 97 46 1835 20.5 70
381 Volkswagen 411 (Wagon) 22 4 121 76 2511 18 72
382 Volkswagen Dasher (Diesel) 43.4 4 90 48 2335 23.7 80
383 Volkswagen Dasher 25 4 90 71 2223 16.5 75
384 Volkswagen Dasher 26 4 79 67 1963 15.5 74
385 Volkswagen Dasher 30.5 4 97 78 2190 14.1 77
386 Volkswagen Jetta 33 4 105 74 2190 14.2 81
387 Volkswagen Model 111 27 4 97 60 1834 19 71
388 Volkswagen Pickup 44 4 97 52 2130 24.6 82
389 Volkswagen Rabbit C (Diesel) 44.3 4 90 48 2085 21.7 80
390 Volkswagen Rabbit Custom Diesel 43.1 4 90 48 1985 21.5 78
391 Volkswagen Rabbit Custom 29 4 97 78 1940 14.5 77
392 Volkswagen Rabbit Custom 31.9 4 89 71 1925 14 79
393 Volkswagen Rabbit L 36 4 105 74 1980 15.3 82
394 Volkswagen Rabbit 29 4 90 70 1937 14 75
395 Volkswagen Rabbit 29 4 90 70 1937 14.2 76
396 Volkswagen Rabbit 29.5 4 97 71 1825 12.2 76
397 Volkswagen Rabbit 41.5 4 98 76 2144 14.7 80
398 Volkswagen Scirocco 31.5 4 89 71 1990 14.9 78
399 Volkswagen Super Beetle 117 4 97 48 1978 20 71
400 Volkswagen Super Beetle 26 4 97 46 1950 21 73
401 Volkswagen Type 3 23 4 97 54 2254 23.5 72
402 Volvo 144EA 19 4 121 112 2868 15.5 73
403 Volvo 145E (Wagon) 18 4 121 112 2933 14.5 72
404 Volvo 244DL 22 4 121 98 2945 14.5 75
405 Volvo 245 20 4 130 102 3150 15.7 76
406 Volvo 264GL 17 6 163 125 3140 13.6 78
407 Volvo Diesel 30.7 6 145 76 3160 19.6 81

Просмотреть файл

@ -0,0 +1,134 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Parallel Coordinates</title>
<style type="text/css">
svg {
font: 10px sans-serif;
}
.background path {
fill: none;
stroke: #ccc;
stroke-opacity: .4;
shape-rendering: crispEdges;
}
.foreground path {
fill: none;
stroke: steelblue;
stroke-opacity: .7;
}
.brush .extent {
fill-opacity: .3;
stroke: #fff;
shape-rendering: crispEdges;
}
.axis line, .axis path {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.axis text {
text-shadow: 0 1px 0 #fff;
}
</style>
</head>
<body>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.csv.js"></script>
<script type="text/javascript">
var m = [30, 10, 10, 10],
w = 960 - m[1] - m[3],
h = 500 - m[0] - m[2];
var x = d3.scale.ordinal().rangePoints([0, w], 1),
y = {};
var line = d3.svg.line(),
axis = d3.svg.axis().orient("left"),
background,
foreground;
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
d3.csv("cars.csv", function(cars) {
// Extract the list of dimensions and create a scale for each.
x.domain(dimensions = d3.keys(cars[0]).filter(function(d) {
return d != "name" && (y[d] = d3.scale.linear()
.domain(d3.extent(cars, function(p) { return +p[d]; }))
.range([h, 0]));
}));
// Add grey background lines for context.
background = svg.append("svg:g")
.attr("class", "background")
.selectAll("path")
.data(cars)
.enter().append("svg:path")
.attr("d", path);
// Add blue foreground lines for focus.
foreground = svg.append("svg:g")
.attr("class", "foreground")
.selectAll("path")
.data(cars)
.enter().append("svg:path")
.attr("d", path);
// Add a group element for each dimension.
var g = svg.selectAll(".dimension")
.data(dimensions)
.enter().append("svg:g")
.attr("class", "dimension")
.attr("transform", function(d) { return "translate(" + x(d) + ")"; });
// Add an axis and title.
g.append("svg:g")
.attr("class", "axis")
.each(function(d) { d3.select(this).call(axis.scale(y[d])); })
.append("svg:text")
.attr("text-anchor", "middle")
.attr("y", -9)
.text(String);
// Add and store a brush for each axis.
g.append("svg:g")
.attr("class", "brush")
.each(function(d) { d3.select(this).call(y[d].brush = d3.svg.brush().y(y[d]).on("brush", brush)); })
.selectAll("rect")
.attr("x", -8)
.attr("width", 16);
});
// Returns the path for a given data point.
function path(d) {
return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; }));
}
// Handles a brush event, toggling the display of foreground lines.
function brush() {
var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }),
extents = actives.map(function(p) { return y[p].brush.extent(); });
foreground.style("display", function(d) {
return actives.every(function(p, i) {
return extents[i][0] <= d[p] && d[p] <= extents[i][1];
}) ? null : "none";
});
}
</script>
</body>
</html>

Просмотреть файл

@ -18,14 +18,13 @@ body {
var w = 400,
h = 400,
r = Math.min(w, h) / 2,
data = d3.range(10).map(Math.random),
data = d3.range(10).map(Math.random).sort(d3.descending),
color = d3.scale.category20(),
arc = d3.svg.arc().outerRadius(r),
donut = d3.layout.pie();
var vis = d3.select("body")
.append("svg:svg")
.data([data.sort(d3.descending)])
var vis = d3.select("body").append("svg:svg")
.data([data])
.attr("width", w)
.attr("height", h);

Просмотреть файл

@ -20,7 +20,7 @@ var w = 400,
r = Math.min(w, h) / 2,
data = d3.range(10).map(Math.random),
color = d3.scale.category20(),
donut = d3.layout.pie().sort(d3.descending),
donut = d3.layout.pie(),
arc = d3.svg.arc().innerRadius(r * .6).outerRadius(r);
var vis = d3.select("body")

Просмотреть файл

@ -0,0 +1,661 @@
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.csv.js"></script>
<script type="text/javascript" src="../../d3.geo.js"></script>
<script type="text/javascript" src="../../d3.geom.js"></script>
<script type="text/javascript" src="../../d3.layout.js"></script>
<script type="text/javascript" src="../../d3.time.js"></script>
<style type="text/css">
svg {
border: solid 1px #000;
display: block;
margin: auto;
font-family: "Helvetica Neue";
}
.line {
fill: none;
stroke: #000;
stroke-width: 2px;
}
</style>
</head>
<body>
<script type="text/javascript">
var m = [120, 60, 60, 60],
w = 1280 - m[1] - m[3],
h = 720 - m[0] - m[2];
var x = d3.time.scale().range([0, w - 60]),
y = d3.scale.linear().range([h / 4 - 20, 0]),
duration = 1500,
delay = 500;
var color = d3.scale.category10();
var svg = d3.select("body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
var stocks,
symbols;
// A line generator, for the dark stroke.
var line = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
// A line generator, for the dark stroke.
var axis = d3.svg.line()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y(h);
// A area generator, for the dark stroke.
var area = d3.svg.area()
.interpolate("basis")
.x(function(d) { return x(d.date); })
.y0(h / 4 - 20)
.y1(function(d) { return y(d.price); });
d3.csv("../data/stocks.csv", function(data) {
var parse = d3.time.format("%b %Y").parse,
filter = {AAPL: 1, AMZN: 1, MSFT: 1, IBM: 1};
stocks = data.filter(function(d) { return d.symbol in filter; });
// Nest stock values by symbol.
symbols = d3.nest()
.key(function(d) { return d.symbol; })
.entries(stocks);
// Parse dates and numbers. We assume values are sorted by date.
// Also compute the maximum price per symbol, needed for the y-domain.
symbols.forEach(function(s) {
s.values.forEach(function(d) { d.date = parse(d.date); d.price = +d.price; });
s.maxPrice = d3.max(s.values, function(d) { return d.price; });
s.sumPrice = d3.sum(s.values, function(d) { return d.price; });
});
// Sort by maximum price, descending.
symbols.sort(function(a, b) { return b.maxPrice - a.maxPrice; });
// Compute the minimum and maximum date across symbols.
x.domain([
d3.min(symbols, function(d) { return d.values[0].date; }),
d3.max(symbols, function(d) { return d.values[d.values.length - 1].date; })
]);
var g = svg.selectAll("g")
.data(symbols)
.enter().append("svg:g")
.attr("class", "symbol");
setTimeout(lines, duration);
});
function lines() {
var g = svg.selectAll(".symbol")
.attr("transform", function(d, i) { return "translate(0," + i * h / 4 + ")"; });
g.each(function(d) {
var e = d3.select(this);
e.append("svg:path")
.attr("class", "line");
e.append("svg:circle")
.attr("r", 5)
.style("fill", function(d) { return color(d.key); })
.style("stroke", "#000")
.style("stroke-width", "2px");
e.append("svg:text")
.attr("x", 12)
.attr("dy", ".31em")
.text(d.key);
});
function draw(k) {
g.each(function(d) {
var e = d3.select(this);
y.domain([0, d.maxPrice]);
e.select("path")
.attr("d", function(d) { return line(d.values.slice(0, k + 1)); });
e.selectAll("circle, text")
.data(function(d) { return [d.values[k], d.values[k]]; })
.attr("transform", function(d) { return "translate(" + x(d.date) + "," + y(d.price) + ")"; });
});
}
var k = 1, n = symbols[0].values.length;
d3.timer(function() {
draw(k);
if ((k += 2) >= n - 1) {
draw(n - 1);
setTimeout(horizons, 500);
return true;
}
});
}
function horizons() {
svg.insert("svg:defs", ".symbol")
.append("svg:clipPath")
.attr("id", "clip")
.append("svg:rect")
.attr("width", w)
.attr("height", h / 4 - 20);
var color = d3.scale.ordinal()
.range(["#c6dbef", "#9ecae1", "#6baed6"]);
var g = svg.selectAll(".symbol")
.attr("clip-path", "url(#clip)");
g.select("circle").transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + (w - 60) + "," + (-h / 4) + ")"; })
.remove();
g.select("text").transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + (w - 60) + "," + (h / 4 - 20) + ")"; })
.attr("dy", "0em");
g.each(function(d) {
y.domain([0, d.maxPrice]);
d3.select(this).selectAll(".area")
.data(d3.range(3))
.enter().insert("svg:path", ".line")
.attr("class", "area")
.attr("transform", function(d) { return "translate(0," + (d * (h / 4 - 20)) + ")"; })
.attr("d", area(d.values))
.style("fill", function(d, i) { return color(i); })
.style("fill-opacity", 1e-6);
y.domain([0, d.maxPrice / 3]);
d3.select(this).selectAll(".line").transition()
.duration(duration)
.attr("d", line(d.values))
.style("stroke-opacity", 1e-6);
d3.select(this).selectAll(".area").transition()
.duration(duration)
.style("fill-opacity", 1)
.attr("d", area(d.values))
.each("end", function() { d3.select(this).style("fill-opacity", null); });
});
setTimeout(areas, duration + delay);
}
function areas() {
var g = svg.selectAll(".symbol");
axis
.y(h / 4 - 21);
g.select(".line")
.attr("d", function(d) { return axis(d.values); });
g.each(function(d) {
y.domain([0, d.maxPrice]);
d3.select(this).select(".line").transition()
.duration(duration)
.style("stroke-opacity", 1)
.each("end", function() { d3.select(this).style("stroke-opacity", null); });
d3.select(this).selectAll(".area")
.filter(function(d, i) { return i; })
.transition()
.duration(duration)
.style("fill-opacity", 1e-6)
.attr("d", area(d.values))
.remove();
d3.select(this).selectAll(".area")
.filter(function(d, i) { return !i; })
.transition()
.duration(duration)
.style("fill", color(d.key))
.attr("d", area(d.values));
});
svg.select("defs").transition()
.duration(duration)
.remove();
g.transition()
.duration(duration)
.each("end", function() { d3.select(this).attr("clip-path", null); });
setTimeout(stackedArea, duration + delay);
}
function stackedArea() {
var stack = d3.layout.stack()
.values(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.price; })
.out(function(d, y0, y) { d.price0 = y0; })
.order("reverse");
stack(symbols);
y
.domain([0, d3.max(symbols[0].values.map(function(d) { return d.price + d.price0; }))])
.range([h, 0]);
line
.y(function(d) { return y(d.price0); });
area
.y0(function(d) { return y(d.price0); })
.y1(function(d) { return y(d.price0 + d.price); });
var t = svg.selectAll(".symbol").transition()
.duration(duration)
.attr("transform", "translate(0,0)")
.each("end", function() { d3.select(this).attr("transform", null); });
t.select("path.area")
.attr("d", function(d) { return area(d.values); });
t.select("path.line")
.style("stroke-opacity", function(d, i) { return i < 3 ? 1e-6 : 1; })
.attr("d", function(d) { return line(d.values); });
t.select("text")
.attr("transform", function(d) { d = d.values[d.values.length - 1]; return "translate(" + (w - 60) + "," + y(d.price / 2 + d.price0) + ")"; });
setTimeout(streamgraph, duration + delay);
}
function streamgraph() {
var stack = d3.layout.stack()
.values(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.price; })
.out(function(d, y0, y) { d.price0 = y0; })
.order("reverse")
.offset("wiggle");
stack(symbols);
line
.y(function(d) { return y(d.price0); });
var t = svg.selectAll(".symbol").transition()
.duration(duration);
t.select("path.area")
.attr("d", function(d) { return area(d.values); });
t.select("path.line")
.style("stroke-opacity", 1e-6)
.attr("d", function(d) { return line(d.values); });
t.select("text")
.attr("transform", function(d) { d = d.values[d.values.length - 1]; return "translate(" + (w - 60) + "," + y(d.price / 2 + d.price0) + ")"; });
setTimeout(overlappingArea, duration + delay);
}
function overlappingArea() {
var g = svg.selectAll(".symbol");
line
.y(function(d) { return y(d.price0 + d.price); });
g.select(".line")
.attr("d", function(d) { return line(d.values); });
y
.domain([0, d3.max(symbols.map(function(d) { return d.maxPrice; }))])
.range([h, 0]);
area
.y0(h)
.y1(function(d) { return y(d.price); });
line
.y(function(d) { return y(d.price); });
var t = g.transition()
.duration(duration);
t.select(".line")
.style("stroke-opacity", 1)
.attr("d", function(d) { return line(d.values); });
t.select(".area")
.style("fill-opacity", .5)
.attr("d", function(d) { return area(d.values); });
t.select("text")
.attr("dy", ".31em")
.attr("transform", function(d) { d = d.values[d.values.length - 1]; return "translate(" + (w - 60) + "," + y(d.price) + ")"; });
svg.append("svg:line")
.attr("class", "line")
.attr("x1", 0)
.attr("x2", w - 60)
.attr("y1", h)
.attr("y2", h)
.style("stroke-opacity", 1e-6)
.transition()
.duration(duration)
.style("stroke-opacity", 1);
setTimeout(groupedBar, duration + delay);
}
function groupedBar() {
x = d3.scale.ordinal()
.domain(symbols[0].values.map(function(d) { return d.date; }))
.rangeBands([0, w - 60], .1);
var x1 = d3.scale.ordinal()
.domain(symbols.map(function(d) { return d.key; }))
.rangeBands([0, x.rangeBand()]);
var g = svg.selectAll(".symbol");
var t = g.transition()
.duration(duration);
t.select(".line")
.style("stroke-opacity", 1e-6)
.remove();
t.select(".area")
.style("fill-opacity", 1e-6)
.remove();
g.each(function(p, j) {
d3.select(this).selectAll("rect")
.data(function(d) { return d.values; })
.enter().append("svg:rect")
.attr("x", function(d) { return x(d.date) + x1(p.key); })
.attr("y", function(d) { return y(d.price); })
.attr("width", x1.rangeBand())
.attr("height", function(d) { return h - y(d.price); })
.style("fill", color(p.key))
.style("fill-opacity", 1e-6)
.transition()
.duration(duration)
.style("fill-opacity", 1);
});
setTimeout(stackedBar, duration + delay);
}
function stackedBar() {
x.rangeRoundBands([0, w - 60], .1);
var stack = d3.layout.stack()
.values(function(d) { return d.values; })
.x(function(d) { return d.date; })
.y(function(d) { return d.price; })
.out(function(d, y0, y) { d.price0 = y0; })
.order("reverse");
var g = svg.selectAll(".symbol");
stack(symbols);
y
.domain([0, d3.max(symbols[0].values.map(function(d) { return d.price + d.price0; }))])
.range([h, 0]);
var t = g.transition()
.duration(duration / 2);
t.select("text")
.delay(symbols[0].values.length * 10)
.attr("transform", function(d) { d = d.values[d.values.length - 1]; return "translate(" + (w - 60) + "," + y(d.price / 2 + d.price0) + ")"; });
t.selectAll("rect")
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.price0 + d.price); })
.attr("height", function(d) { return h - y(d.price); })
.each("end", function() {
d3.select(this)
.style("stroke", "#fff")
.style("stroke-opacity", 1e-6)
.transition()
.duration(duration / 2)
.attr("x", function(d) { return x(d.date); })
.attr("width", x.rangeBand())
.style("stroke-opacity", 1);
});
setTimeout(transposeBar, duration + symbols[0].values.length * 10 + delay);
}
function transposeBar() {
x
.domain(symbols.map(function(d) { return d.key; }))
.rangeRoundBands([0, w], .2);
y
.domain([0, d3.max(symbols.map(function(d) { return d3.sum(d.values.map(function(d) { return d.price; })); }))]);
var stack = d3.layout.stack()
.x(function(d, i) { return i; })
.y(function(d) { return d.price; })
.out(function(d, y0, y) { d.price0 = y0; });
stack(d3.zip.apply(null, symbols.map(function(d) { return d.values; }))); // transpose!
var g = svg.selectAll(".symbol");
var t = g.transition()
.duration(duration / 2);
t.selectAll("rect")
.delay(function(d, i) { return i * 10; })
.attr("y", function(d) { return y(d.price0 + d.price) - 1; })
.attr("height", function(d) { return h - y(d.price) + 1; })
.attr("x", function(d) { return x(d.symbol); })
.attr("width", x.rangeBand())
.style("stroke-opacity", 1e-6);
t.select("text")
.attr("x", 0)
.attr("transform", function(d) { return "translate(" + (x(d.key) + x.rangeBand() / 2) + "," + h + ")"; })
.attr("dy", "1.31em")
.each("end", function() { d3.select(this).attr("x", null).attr("text-anchor", "middle"); });
svg.select("line").transition()
.duration(duration)
.attr("x2", w);
setTimeout(donut, duration / 2 + symbols[0].values.length * 10 + delay);
}
function donut() {
var g = svg.selectAll(".symbol");
g.selectAll("rect").remove();
var pie = d3.layout.pie()
.value(function(d) { return d.sumPrice; });
var arc = d3.svg.arc();
g.append("svg:path")
.style("fill", function(d) { return color(d.key); })
.data(function() { return pie(symbols); })
.transition()
.duration(duration)
.tween("arc", arcTween);
g.select("text").transition()
.duration(duration)
.attr("dy", ".31em");
svg.select("line").transition()
.duration(duration)
.attr("y1", 2 * h)
.attr("y2", 2 * h)
.remove();
function arcTween(d) {
var path = d3.select(this),
text = d3.select(this.parentNode.appendChild(this.previousSibling)),
x0 = x(d.data.key),
y0 = h - y(d.data.sumPrice);
return function(t) {
var r = h / 2 / Math.min(1, t + 1e-3),
a = Math.cos(t * Math.PI / 2),
xx = (-r + (a) * (x0 + x.rangeBand()) + (1 - a) * (w + h) / 2),
yy = ((a) * h + (1 - a) * h / 2),
f = {
innerRadius: r - x.rangeBand() / (2 - a),
outerRadius: r,
startAngle: a * (Math.PI / 2 - y0 / r) + (1 - a) * d.startAngle,
endAngle: a * (Math.PI / 2) + (1 - a) * d.endAngle
};
path.attr("transform", "translate(" + xx + "," + yy + ")");
path.attr("d", arc(f));
text.attr("transform", "translate(" + arc.centroid(f) + ")translate(" + xx + "," + yy + ")rotate(" + ((f.startAngle + f.endAngle) / 2 + 3 * Math.PI / 2) * 180 / Math.PI + ")");
};
}
setTimeout(donutExplode, duration + delay);
}
/*
function donutTransition() {
var r0 = h / 2 - x.rangeBand() / 2,
r1 = h / 2,
pie1 = d3.layout.pie().value(function(d) { return d.sumPrice; })(symbols),
pie2 = d3.layout.pie().value(function(d) { return d.maxPrice; })(symbols),
arc = d3.svg.arc();
svg.selectAll(".symbol path")
.map(function(d, i) {
d = pie1[i];
d.innerRadius = r0;
d.outerRadius = r1;
d.next = pie2[i];
return d;
})
.each(transitionSplit);
function transitionSplit(d, i) {
d3.select(this).transition()
.duration(duration / 2)
.tween("arc", tweenArc({
innerRadius: i & 1 ? r0 : (r0 + r1) / 2,
outerRadius: i & 1 ? (r0 + r1) / 2 : r1
}))
.each("end", transitionRotate);
}
function transitionRotate(d, i) {
var a0 = d.next.startAngle + d.next.endAngle,
a1 = d.startAngle - d.endAngle;
d3.select(this).transition()
.duration(duration / 2)
.tween("arc", tweenArc({
startAngle: (a0 + a1) / 2,
endAngle: (a0 - a1) / 2
}))
.each("end", transitionResize);
}
function transitionResize(d, i) {
d3.select(this).transition()
.duration(duration / 2)
.tween("arc", tweenArc({
startAngle: d.next.startAngle,
endAngle: d.next.endAngle
}))
.each("end", transitionUnite);
}
function transitionUnite(d, i) {
d3.select(this).transition()
.duration(duration / 2)
.tween("arc", tweenArc({
innerRadius: r0,
outerRadius: r1
}));
}
function tweenArc(b) {
return function(a) {
var path = d3.select(this),
text = d3.select(this.nextSibling),
i = d3.interpolate(a, b);
for (var key in b) a[key] = b[key]; // update data
return function(t) {
var a = i(t);
path.attr("d", arc(a));
text.attr("transform", "translate(" + arc.centroid(a) + ")translate(" + w / 2 + "," + h / 2 +")rotate(" + ((a.startAngle + a.endAngle) / 2 + 3 * Math.PI / 2) * 180 / Math.PI + ")");
};
}
}
setTimeout(donutExplode, 2 * duration + delay);
}
*/
function donutExplode() {
var r0a = h / 2 - x.rangeBand() / 2,
r1a = h / 2,
r0b = 2 * h - x.rangeBand() / 2,
r1b = 2 * h,
arc = d3.svg.arc();
svg.selectAll(".symbol path")
.each(transitionExplode);
function transitionExplode(d, i) {
d.innerRadius = r0a;
d.outerRadius = r1a;
d3.select(this).transition()
.duration(duration / 2)
.tween("arc", tweenArc({
innerRadius: r0b,
outerRadius: r1b
}));
}
function tweenArc(b) {
return function(a) {
var path = d3.select(this),
text = d3.select(this.nextSibling),
i = d3.interpolate(a, b);
for (var key in b) a[key] = b[key]; // update data
return function(t) {
var a = i(t);
path.attr("d", arc(a));
text.attr("transform", "translate(" + arc.centroid(a) + ")translate(" + w / 2 + "," + h / 2 +")rotate(" + ((a.startAngle + a.endAngle) / 2 + 3 * Math.PI / 2) * 180 / Math.PI + ")");
};
}
}
}
</script>
</body>
</html>

Просмотреть файл

@ -1,7 +0,0 @@
function cross(a) {
return function(d) {
var c = [];
for (var i = 0, n = a.length; i < n; i++) c.push({x: d, y: a[i]});
return c;
};
}

Просмотреть файл

@ -1,8 +1,49 @@
line {
stroke: #eee;
svg {
font: 10px sans-serif;
}
.axis {
shape-rendering: crispEdges;
}
rect {
cursor: crosshair;
.axis line {
stroke: #ddd;
stroke-width: .5px;
}
.axis path {
display: none;
}
rect.extent {
fill: #000;
fill-opacity: .125;
stroke: #fff;
}
rect.frame {
fill: #fff;
fill-opacity: .7;
stroke: #aaa;
}
circle {
fill: #ccc;
fill-opacity: .5;
}
.cell text {
pointer-events: none;
}
.setosa {
fill: #800;
}
.versicolor {
fill: #080;
}
.virginica {
fill: #008;
}

Просмотреть файл

@ -4,7 +4,6 @@
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Scatterplot Matrix</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="cross.js"></script>
<link type="text/css" rel="stylesheet" href="splom.css"/>
</head>
<body>

Просмотреть файл

@ -2,148 +2,118 @@ d3.json("flowers.json", function(flower) {
// Size parameters.
var size = 150,
padding = 20;
// Color scale.
var color = d3.scale.ordinal().range([
"rgb(50%, 0%, 0%)",
"rgb(0%, 50%, 0%)",
"rgb(0%, 0%, 50%)"
]);
padding = 19.5,
n = flower.traits.length;
// Position scales.
var position = {};
var x = {}, y = {};
flower.traits.forEach(function(trait) {
function value(d) { return d[trait]; }
position[trait] = d3.scale.linear()
.domain([d3.min(flower.values, value), d3.max(flower.values, value)])
.range([padding / 2, size - padding / 2]);
var value = function(d) { return d[trait]; },
domain = [d3.min(flower.values, value), d3.max(flower.values, value)],
range = [padding / 2, size - padding / 2];
x[trait] = d3.scale.linear().domain(domain).range(range);
y[trait] = d3.scale.linear().domain(domain).range(range.reverse());
});
// Root panel.
var svg = d3.select("#chart")
.append("svg:svg")
.attr("width", size * flower.traits.length)
.attr("height", size * flower.traits.length);
// Axes.
var axis = d3.svg.axis()
.ticks(5)
.tickSize(size * n);
// One column per trait.
var column = svg.selectAll("g")
// Brush.
var brush = d3.svg.brush()
.on("brushstart", brushstart)
.on("brush", brush)
.on("brushend", brushend);
// Root panel.
var svg = d3.select("#chart").append("svg:svg")
.attr("width", size * n + padding)
.attr("height", size * n + padding);
// X-axis.
svg.selectAll("g.x.axis")
.data(flower.traits)
.enter().append("svg:g")
.attr("transform", function(d, i) { return "translate(" + i * size + ",0)"; });
.attr("class", "x axis")
.attr("transform", function(d, i) { return "translate(" + i * size + ",0)"; })
.each(function(d) { d3.select(this).call(axis.scale(x[d]).orient("bottom")); });
// One row per trait.
var row = column.selectAll("g")
.data(cross(flower.traits))
// Y-axis.
svg.selectAll("g.y.axis")
.data(flower.traits)
.enter().append("svg:g")
.attr("transform", function(d, i) { return "translate(0," + i * size + ")"; });
.attr("class", "y axis")
.attr("transform", function(d, i) { return "translate(0," + i * size + ")"; })
.each(function(d) { d3.select(this).call(axis.scale(y[d]).orient("right")); });
// X-ticks. TODO Cross the trait into the tick data?
row.selectAll("line.x")
.data(function(d) { return position[d.x].ticks(5).map(position[d.x]); })
.enter().append("svg:line")
.attr("class", "x")
.attr("x1", function(d) { return d; })
.attr("x2", function(d) { return d; })
.attr("y1", padding / 2)
.attr("y2", size - padding / 2);
// Cell and plot.
var cell = svg.selectAll("g.cell")
.data(cross(flower.traits, flower.traits))
.enter().append("svg:g")
.attr("class", "cell")
.attr("transform", function(d) { return "translate(" + d.i * size + "," + d.j * size + ")"; })
.each(plot);
// Y-ticks. TODO Cross the trait into the tick data?
row.selectAll("line.y")
.data(function(d) { return position[d.y].ticks(5).map(position[d.y]); })
.enter().append("svg:line")
.attr("class", "y")
.attr("x1", padding / 2)
.attr("x2", size - padding / 2)
.attr("y1", function(d) { return d; })
.attr("y2", function(d) { return d; });
// Titles for the diagonal.
cell.filter(function(d) { return d.i == d.j; }).append("svg:text")
.attr("x", padding)
.attr("y", padding)
.attr("dy", ".71em")
.text(function(d) { return d.x; });
// Frame.
row.append("svg:rect")
.attr("x", padding / 2)
.attr("y", padding / 2)
.attr("width", size - padding)
.attr("height", size - padding)
.style("fill", "none")
.style("stroke", "#aaa")
.style("stroke-width", 1.5)
.attr("pointer-events", "all")
.on("mousedown", mousedown);
function plot(p) {
var cell = d3.select(this);
// Dot plot.
var dot = row.selectAll("circle")
.data(cross(flower.values))
.enter().append("svg:circle")
.attr("cx", function(d) { return position[d.x.x](d.y[d.x.x]); })
.attr("cy", function(d) { return size - position[d.x.y](d.y[d.x.y]); })
.attr("r", 3)
.style("fill", function(d) { return color(d.y.species); })
.style("fill-opacity", .5)
.attr("pointer-events", "none");
// Plot frame.
cell.append("svg:rect")
.attr("class", "frame")
.attr("x", padding / 2)
.attr("y", padding / 2)
.attr("width", size - padding)
.attr("height", size - padding);
d3.select(window)
.on("mousemove", mousemove)
.on("mouseup", mouseup);
// Plot dots.
cell.selectAll("circle")
.data(flower.values)
.enter().append("svg:circle")
.attr("class", function(d) { return d.species; })
.attr("cx", function(d) { return x[p.x](d[p.x]); })
.attr("cy", function(d) { return y[p.y](d[p.y]); })
.attr("r", 3);
var rect, x0, x1, count;
function mousedown() {
x0 = d3.svg.mouse(this);
count = 0;
rect = d3.select(this.parentNode)
.append("svg:rect")
.style("fill", "#999")
.style("fill-opacity", .5);
d3.event.preventDefault();
// Plot brush.
cell.call(brush.x(x[p.x]).y(y[p.y]));
}
function mousemove() {
if (!rect) return;
x1 = d3.svg.mouse(rect.node());
x1[0] = Math.max(padding / 2, Math.min(size - padding / 2, x1[0]));
x1[1] = Math.max(padding / 2, Math.min(size - padding / 2, x1[1]));
var minx = Math.min(x0[0], x1[0]),
maxx = Math.max(x0[0], x1[0]),
miny = Math.min(x0[1], x1[1]),
maxy = Math.max(x0[1], x1[1]);
rect
.attr("x", minx - .5)
.attr("y", miny - .5)
.attr("width", maxx - minx + 1)
.attr("height", maxy - miny + 1);
var v = rect.node().__data__,
x = position[v.x],
y = position[v.y],
mins = x.invert(minx),
maxs = x.invert(maxx),
mint = y.invert(size - maxy),
maxt = y.invert(size - miny);
count = 0;
svg.selectAll("circle")
.style("fill", function(d) {
return mins <= d.y[v.x] && maxs >= d.y[v.x]
&& mint <= d.y[v.y] && maxt >= d.y[v.y]
? (count++, color(d.y.species))
: "#ccc";
});
// Clear the previously-active brush, if any.
function brushstart(p) {
if (brush.data !== p) {
cell.call(brush.clear());
brush.x(x[p.x]).y(y[p.y]).data = p;
}
}
function mouseup() {
if (!rect) return;
rect.remove();
rect = null;
if (!count) svg.selectAll("circle")
.style("fill", function(d) {
return color(d.y.species);
});
// Highlight the selected circles.
function brush(p) {
var e = brush.extent();
svg.selectAll("circle").attr("class", function(d) {
return e[0][0] <= d[p.x] && d[p.x] <= e[1][0]
&& e[0][1] <= d[p.y] && d[p.y] <= e[1][1]
? d.species : null;
});
}
// If the brush is empty, select all circles.
function brushend() {
if (brush.empty()) svg.selectAll("circle").attr("class", function(d) {
return d.species;
});
}
function cross(a, b) {
var c = [], n = a.length, m = b.length, i, j;
for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j});
return c;
}
});

Просмотреть файл

@ -0,0 +1,85 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Transform Test</title>
<script type="text/javascript" src="../../d3.js"></script>
<style type="text/css">
th, td { border: solid #ccc 1px; }
</style>
</head>
<body>
<script type="text/javascript">
var outcome = d3.select("body").append("p");
var g = d3.select("body").append("svg:svg")
.attr("width", 10)
.attr("height", 10)
.append("svg:g");
var results = d3.select("body").append("table")
.style("display", "none");
results.append("tr").selectAll("th")
.data(["Expected", "Actual", "Expected matrix", "Actual matrix"])
.enter().append("th").text(String);
var el = g[0][0],
v,
m,
a,
b,
failures = 0;
for (var tx = -10; tx <= 10; tx += 5) {
for (var ty = -10; ty <= 10; ty += 5) {
for (var r = -180; r <= 180; r += 15) {
for (var skx = -45; skx <= 45; skx += 45) {
for (var sx = -2; sx <= 2; sx++) {
for (var sy = -2; sy <= 2; sy++) {
v = "translate(" + tx + "," + ty + ")rotate(" + r + ")skewX(" + skx + ")scale(" + sx + "," + sy + ")";
g.attr("transform", v);
a = matrix(el);
g.attr("transform", d3.transform(v));
b = matrix(el);
if (!deepEqual(a, b, 1e-6)) {
failures++;
results
.style("display", null)
.append("tr").selectAll("td")
.data([v, d3.transform(v), a, b])
.enter().append("td").text(String);
}
}
}
}
}
}
}
outcome.text(failures ? failures + " failures" : "Success!");
function matrix(el) {
var t = el.transform.baseVal.consolidate();
if (t) {
var m = t.matrix;
return [m.a, m.b, m.c, m.d, m.e, m.f];
}
return null;
}
function deepEqual(actual, expected, epsilon) {
epsilon = epsilon || 0;
if (actual === expected) return true;
if (actual == null || expected == null) return false;
if (actual.length !== expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (Math.abs(actual[i] - expected[i]) > epsilon) return false;
}
return true;
}
</script>
</body>
</html>

Просмотреть файл

@ -0,0 +1,60 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
<title>Transform Transitions</title>
<script type="text/javascript" src="../../d3.js"></script>
<style type="text/css">
body {
margin: 0;
}
rect {
stroke: #fff;
stroke-width: .05px;
}
</style>
</head>
<body>
<script type="text/javascript">
var w = 960,
h = 500,
z = 20,
x = w / z,
y = h / z;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h);
svg.selectAll("rect")
.data(d3.range(x * y))
.enter().append("svg:rect")
.attr("transform", translate)
.attr("width", z)
.attr("height", z)
.style("fill", d3.scale.linear().domain([0, x * y]).range(["brown", "steelblue"]))
.on("mouseover", mouseover);
function translate(d) {
return "translate(" + (d % x) * z + "," + Math.floor(d / x) * z + ")";
}
function mouseover(d) {
this.parentNode.appendChild(this);
d3.select(this).transition()
.duration(750)
.attr("transform", "translate(480,480)scale(23)rotate(180)")
.transition()
.delay(1500)
.attr("transform", "translate(240,240)scale(0)rotate(180)")
.style("fill-opacity", 0)
.remove();
}
</script>
</body>
</html>

Просмотреть файл

@ -7,13 +7,17 @@
<script type="text/javascript" src="../../d3.layout.js"></script>
<style type="text/css">
circle.node {
.node circle {
cursor: pointer;
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
}
path.link {
fill: none;
stroke: #ccc;
@ -26,28 +30,40 @@ path.link {
<div id="chart"></div>
<script type="text/javascript">
var w = 960,
h = 2000,
var m = [20, 120, 20, 120],
w = 1280 - m[1] - m[3],
h = 800 - m[0] - m[2],
i = 0,
duration = 500,
root;
var tree = d3.layout.tree()
.size([h, w - 160]);
.size([h, w]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h)
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(40,0)");
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");
d3.json("../data/flare.json", function(json) {
json.x0 = 800;
json.y0 = 0;
update(root = json);
root = json;
root.x0 = h / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
root.children.forEach(collapse);
update(root);
});
function update(source) {
@ -55,43 +71,60 @@ function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse();
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });
// Update the nodes…
var node = vis.selectAll("circle.node")
var node = vis.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter any new nodes at the parent's previous position.
node.enter().append("svg:circle")
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.attr("cx", function(d) { return source.y0; })
.attr("cy", function(d) { return source.x0; })
.attr("r", 4.5)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; })
.on("click", click)
.transition()
.duration(duration)
.attr("cx", function(d) { return d.y; })
.attr("cy", function(d) { return d.x; });
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click);
// Transition nodes to their new position.
node.transition()
.duration(duration)
.attr("cx", function(d) { return d.y; })
.attr("cy", function(d) { return d.x; })
nodeEnter.append("svg:circle")
.attr("r", 1e-6)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
// Transition exiting nodes to the parent's new position.
node.exit().transition()
nodeEnter.append("svg:text")
.attr("x", function(d) { return d.children || d._children ? -10 : 10; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.name; })
.style("fill-opacity", 1e-6);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("cx", function(d) { return source.y; })
.attr("cy", function(d) { return source.x; })
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("circle")
.attr("r", 4.5)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
// Update the links…
var link = vis.selectAll("path.link")
.data(tree.links(nodes), function(d) { return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("svg:path", "circle")
link.enter().insert("svg:path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: source.x0, y: source.y0};

Просмотреть файл

@ -8,8 +8,8 @@ var treemap = d3.layout.treemap()
.value(function(d) { return d.size; });
var svg = d3.select("body").append("svg:svg")
.style("width", w)
.style("height", h)
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("transform", "translate(-.5,-.5)");

Просмотреть файл

@ -4,7 +4,6 @@
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Zoom + Pan</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.behavior.js"></script>
<style type="text/css">
svg {
@ -39,7 +38,9 @@ var svg = d3.select("body").append("svg:svg")
.attr("pointer-events", "all")
.append("svg:g")
.attr("transform", "translate(" + padding[3] + "," + padding[0] + ")")
.call(d3.behavior.zoom().on("zoom", redraw))
.call(d3.behavior.zoom()
.extent([[0, size[0]], [0, size[1]], [0, Infinity]])
.on("zoom", redraw))
.append("svg:g");
// Generate x-ticks…

Просмотреть файл

@ -4,7 +4,6 @@
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Zoom + Pan</title>
<script type="text/javascript" src="../../d3.js"></script>
<script type="text/javascript" src="../../d3.behavior.js"></script>
<style type="text/css">
svg {
@ -39,7 +38,9 @@ var svg = d3.select("body").append("svg:svg")
.attr("pointer-events", "all")
.append("svg:g")
.attr("transform", "translate(" + padding[3] + "," + padding[0] + ")")
.call(d3.behavior.zoom().on("zoom", redraw));
.call(d3.behavior.zoom()
.extent([[0, size[0]], [0, size[1]], [0, 3]])
.on("zoom", redraw));
svg.append("svg:rect")
.attr("width", size[0])

Просмотреть файл

@ -1,5 +1,225 @@
(function(){science = {version: "0.0.1"}; // semver
(function(){science = {version: "1.7.0"}; // semver
science.ascending = function(a, b) {
return a - b;
};
// Euler's constant.
science.EULER = .5772156649015329;
// Compute exp(x) - 1 accurately for small x.
science.expm1 = function(x) {
return (x < 1e-5 && x > -1e-5) ? x + .5 * x * x : Math.exp(x) - 1;
};
science.functor = function(v) {
return typeof v === "function" ? v : function() { return v; };
};
// Based on:
// http://www.johndcook.com/blog/2010/06/02/whats-so-hard-about-finding-a-hypotenuse/
science.hypot = function(x, y) {
x = Math.abs(x);
y = Math.abs(y);
var max,
min;
if (x > y) { max = x; min = y; }
else { max = y; min = x; }
var r = min / max;
return max * Math.sqrt(1 + r * r);
};
science.quadratic = function() {
var complex = false;
function quadratic(a, b, c) {
var d = b * b - 4 * a * c;
if (d > 0) {
d = Math.sqrt(d) / (2 * a);
return complex
? [{r: -b - d, i: 0}, {r: -b + d, i: 0}]
: [-b - d, -b + d];
} else if (d === 0) {
d = -b / (2 * a);
return complex ? [{r: d, i: 0}] : [d];
} else {
if (complex) {
d = Math.sqrt(-d) / (2 * a);
return [
{r: -b, i: -d},
{r: -b, i: d}
];
}
return [];
}
}
quadratic.complex = function(x) {
if (!arguments.length) return complex;
complex = x;
return quadratic;
};
return quadratic;
};
// Constructs a multi-dimensional array filled with zeroes.
science.zeroes = function(n) {
var i = -1,
a = [];
if (arguments.length === 1)
while (++i < n)
a[i] = 0;
else
while (++i < n)
a[i] = science.zeroes.apply(
this, Array.prototype.slice.call(arguments, 1));
return a;
};
science.vector = {};
science.vector.cross = function(a, b) {
// TODO how to handle non-3D vectors?
// TODO handle 7D vectors?
return [
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0]
];
};
science.vector.dot = function(a, b) {
var s = 0,
i = -1,
n = Math.min(a.length, b.length);
while (++i < n) s += a[i] * b[i];
return s;
};
science.vector.length = function(p) {
return Math.sqrt(science.vector.dot(p, p));
};
science.vector.normalize = function(p) {
var length = science.vector.length(p);
return p.map(function(d) { return d / length; });
};
// 4x4 matrix determinant.
science.vector.determinant = function(matrix) {
var m = matrix[0].concat(matrix[1]).concat(matrix[2]).concat(matrix[3]);
return (
m[12] * m[9] * m[6] * m[3] - m[8] * m[13] * m[6] * m[3] -
m[12] * m[5] * m[10] * m[3] + m[4] * m[13] * m[10] * m[3] +
m[8] * m[5] * m[14] * m[3] - m[4] * m[9] * m[14] * m[3] -
m[12] * m[9] * m[2] * m[7] + m[8] * m[13] * m[2] * m[7] +
m[12] * m[1] * m[10] * m[7] - m[0] * m[13] * m[10] * m[7] -
m[8] * m[1] * m[14] * m[7] + m[0] * m[9] * m[14] * m[7] +
m[12] * m[5] * m[2] * m[11] - m[4] * m[13] * m[2] * m[11] -
m[12] * m[1] * m[6] * m[11] + m[0] * m[13] * m[6] * m[11] +
m[4] * m[1] * m[14] * m[11] - m[0] * m[5] * m[14] * m[11] -
m[8] * m[5] * m[2] * m[15] + m[4] * m[9] * m[2] * m[15] +
m[8] * m[1] * m[6] * m[15] - m[0] * m[9] * m[6] * m[15] -
m[4] * m[1] * m[10] * m[15] + m[0] * m[5] * m[10] * m[15]);
};
// Performs in-place Gauss-Jordan elimination.
//
// Based on Jarno Elonen's Python version (public domain):
// http://elonen.iki.fi/code/misc-notes/python-gaussj/index.html
science.vector.gaussjordan = function(m, eps) {
if (!eps) eps = 1e-10;
var h = m.length,
w = m[0].length,
y = -1,
y2,
x;
while (++y < h) {
var maxrow = y;
// Find max pivot.
y2 = y; while (++y2 < h) {
if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y]))
maxrow = y2;
}
// Swap.
var tmp = m[y];
m[y] = m[maxrow];
m[maxrow] = tmp;
// Singular?
if (Math.abs(m[y][y]) <= eps) return false;
// Eliminate column y.
y2 = y; while (++y2 < h) {
var c = m[y2][y] / m[y][y];
x = y - 1; while (++x < w) {
m[y2][x] -= m[y][x] * c;
}
}
}
// Backsubstitute.
y = h; while (--y >= 0) {
var c = m[y][y];
y2 = -1; while (++y2 < y) {
x = w; while (--x >= y) {
m[y2][x] -= m[y][x] * m[y2][y] / c;
}
}
m[y][y] /= c;
// Normalize row y.
x = h - 1; while (++x < w) {
m[y][x] /= c;
}
}
return true;
};
// Find matrix inverse using Gauss-Jordan.
science.vector.inverse = function(m) {
var n = m.length
i = -1;
// Check if the matrix is square.
if (n !== m[0].length) return;
// Augment with identity matrix I to get AI.
m = m.map(function(row, i) {
var identity = new Array(n),
j = -1;
while (++j < n) identity[j] = i === j ? 1 : 0;
return row.concat(identity);
});
// Compute IA^-1.
science.vector.gaussjordan(m);
// Remove identity matrix I to get A^-1.
while (++i < n) {
m[i] = m[i].slice(n);
}
return m;
};
science.vector.multiply = function(a, b) {
var m = a.length,
n = b[0].length,
p = b.length,
i = -1,
j,
k;
if (p !== a[0].length) throw {"error": "columns(a) != rows(b); " + a[0].length + " != " + p};
var ab = new Array(m);
while (++i < m) {
ab[i] = new Array(n);
j = -1; while(++j < n) {
var s = 0;
k = -1; while (++k < p) s += a[i][k] * b[k][j];
ab[i][j] = s;
}
}
return ab;
};
science.vector.transpose = function(a) {
var m = a.length,
n = a[0].length,
i = -1,
j,
b = new Array(n);
while (++i < n) {
b[i] = new Array(m);
j = -1; while (++j < m) b[i][j] = a[j][i];
}
return b;
};
})()

Просмотреть файл

@ -0,0 +1,27 @@
(function(){science.lin = {};
/**
* Solves tridiagonal systems of linear equations.
*
* Source: http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
*
* @param {number[]} a
* @param {number[]} b
* @param {number[]} c
* @param {number[]} d
* @param {number[]} x
* @param {number} n
*/
science.lin.tridag = function(a, b, c, d, x, n) {
var i,
m;
for (i = 1; i < n; i++) {
m = a[i] / b[i - 1];
b[i] -= m * c[i - 1];
d[i] -= m * d[i - 1];
}
x[n - 1] = d[n - 1] / b[n - 1];
for (i = n - 2; i >= 0; i--) {
x[i] = (d[i] - c[i] * x[i + 1]) / b[i];
}
};
})()

1
lib/science/science.lin.min.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1 @@
(function(){science.lin={},science.lin.tridag=function(a,b,c,d,e,f){var g,h;for(g=1;g<f;g++)h=a[g]/b[g-1],b[g]-=h*c[g-1],d[g]-=h*d[g-1];e[f-1]=d[f-1]/b[f-1];for(g=f-2;g>=0;g--)e[g]=(d[g]-c[g]*e[g+1])/b[g]}})()

2
lib/science/science.min.js поставляемый
Просмотреть файл

@ -1 +1 @@
(function(){science={version:"0.0.1"},science.functor=function(a){return typeof a=="function"?a:function(){return a}}})()
(function(){science={version:"1.7.0"},science.ascending=function(a,b){return a-b},science.EULER=.5772156649015329,science.expm1=function(a){return a<1e-5&&a>-0.00001?a+.5*a*a:Math.exp(a)-1},science.functor=function(a){return typeof a=="function"?a:function(){return a}},science.hypot=function(a,b){a=Math.abs(a),b=Math.abs(b);var c,d;a>b?(c=a,d=b):(c=b,d=a);var e=d/c;return c*Math.sqrt(1+e*e)},science.quadratic=function(){function b(b,c,d){var e=c*c-4*b*d;if(e>0){e=Math.sqrt(e)/(2*b);return a?[{r:-c-e,i:0},{r:-c+e,i:0}]:[-c-e,-c+e]}if(e===0){e=-c/(2*b);return a?[{r:e,i:0}]:[e]}if(a){e=Math.sqrt(-e)/(2*b);return[{r:-c,i:-e},{r:-c,i:e}]}return[]}var a=!1;b.complex=function(c){if(!arguments.length)return a;a=c;return b};return b},science.zeroes=function(a){var b=-1,c=[];if(arguments.length===1)while(++b<a)c[b]=0;else while(++b<a)c[b]=science.zeroes.apply(this,Array.prototype.slice.call(arguments,1));return c},science.vector={},science.vector.cross=function(a,b){return[a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1]-a[1]*b[0]]},science.vector.dot=function(a,b){var c=0,d=-1,e=Math.min(a.length,b.length);while(++d<e)c+=a[d]*b[d];return c},science.vector.length=function(a){return Math.sqrt(science.vector.dot(a,a))},science.vector.normalize=function(a){var b=science.vector.length(a);return a.map(function(a){return a/b})},science.vector.determinant=function(a){var b=a[0].concat(a[1]).concat(a[2]).concat(a[3]);return b[12]*b[9]*b[6]*b[3]-b[8]*b[13]*b[6]*b[3]-b[12]*b[5]*b[10]*b[3]+b[4]*b[13]*b[10]*b[3]+b[8]*b[5]*b[14]*b[3]-b[4]*b[9]*b[14]*b[3]-b[12]*b[9]*b[2]*b[7]+b[8]*b[13]*b[2]*b[7]+b[12]*b[1]*b[10]*b[7]-b[0]*b[13]*b[10]*b[7]-b[8]*b[1]*b[14]*b[7]+b[0]*b[9]*b[14]*b[7]+b[12]*b[5]*b[2]*b[11]-b[4]*b[13]*b[2]*b[11]-b[12]*b[1]*b[6]*b[11]+b[0]*b[13]*b[6]*b[11]+b[4]*b[1]*b[14]*b[11]-b[0]*b[5]*b[14]*b[11]-b[8]*b[5]*b[2]*b[15]+b[4]*b[9]*b[2]*b[15]+b[8]*b[1]*b[6]*b[15]-b[0]*b[9]*b[6]*b[15]-b[4]*b[1]*b[10]*b[15]+b[0]*b[5]*b[10]*b[15]},science.vector.gaussjordan=function(a,b){b||(b=1e-10);var c=a.length,d=a[0].length,e=-1,f,g;while(++e<c){var h=e;f=e;while(++f<c)Math.abs(a[f][e])>Math.abs(a[h][e])&&(h=f);var i=a[e];a[e]=a[h],a[h]=i;if(Math.abs(a[e][e])<=b)return!1;f=e;while(++f<c){var j=a[f][e]/a[e][e];g=e-1;while(++g<d)a[f][g]-=a[e][g]*j}}e=c;while(--e>=0){var j=a[e][e];f=-1;while(++f<e){g=d;while(--g>=e)a[f][g]-=a[e][g]*a[f][e]/j}a[e][e]/=j,g=c-1;while(++g<d)a[e][g]/=j}return!0},science.vector.inverse=function(a){var b=a.length;i=-1;if(b===a[0].length){a=a.map(function(a,c){var d=Array(b),e=-1;while(++e<b)d[e]=c===e?1:0;return a.concat(d)}),science.vector.gaussjordan(a);while(++i<b)a[i]=a[i].slice(b);return a}},science.vector.multiply=function(a,b){var c=a.length,d=b[0].length,e=b.length,f=-1,g,h;if(e!==a[0].length)throw{error:"columns(a) != rows(b); "+a[0].length+" != "+e};var i=Array(c);while(++f<c){i[f]=Array(d),g=-1;while(++g<d){var j=0;h=-1;while(++h<e)j+=a[f][h]*b[h][g];i[f][g]=j}}return i},science.vector.transpose=function(a){var b=a.length,c=a[0].length,d=-1,e,f=Array(c);while(++d<c){f[d]=Array(b),e=-1;while(++e<b)f[d][e]=a[e][d]}return f}})()

Просмотреть файл

@ -19,6 +19,100 @@ science.stats.bandwidth = {
* Math.pow(x.length, -1/5);
}
};
science.stats.distance = {
euclidean: function(a, b) {
var n = a.length,
i = -1,
s = 0,
x;
while (++i < n) {
x = a[i] - b[i];
s += x * x;
}
return Math.sqrt(s);
},
manhattan: function(a, b) {
var n = a.length,
i = -1,
s = 0;
while (++i < n) s += Math.abs(a[i] - b[i]);
return s;
},
minkowski: function(p) {
return function(a, b) {
var n = a.length,
i = -1,
s = 0;
while (++i < n) s += Math.pow(Math.abs(a[i] - b[i]), p);
return Math.pow(s, 1 / p);
};
},
chebyshev: function(a, b) {
var n = a.length,
i = -1,
max = 0,
x;
while (++i < n) {
x = Math.abs(a[i] - b[i]);
if (x > max) max = x;
}
return max;
},
hamming: function(a, b) {
var n = a.length,
i = -1,
d = 0;
while (++i < n) if (a[i] !== b[i]) d++;
return d;
},
jaccard: function(a, b) {
var n = a.length,
i = -1,
s = 0;
while (++i < n) if (a[i] === b[i]) s++;
return s / n;
},
braycurtis: function(a, b) {
var n = a.length,
i = -1,
s0 = 0,
s1 = 0,
ai,
bi;
while (++i < n) {
ai = a[i];
bi = b[i];
s0 += Math.abs(ai - bi);
s1 += Math.abs(ai + bi);
}
return s0 / s1;
}
};
// Based on implementation in http://picomath.org/.
science.stats.erf = function(x) {
var a1 = 0.254829592,
a2 = -0.284496736,
a3 = 1.421413741,
a4 = -1.453152027,
a5 = 1.061405429,
p = 0.3275911;
// Save the sign of x
var sign = x < 0 ? -1 : 1;
if (x < 0) {
sign = -1;
x = -x;
}
// A&S formula 7.1.26
var t = 1 / (1 + p * x);
return sign * (
1 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1)
* t * Math.exp(-x * x));
};
science.stats.phi = function(x) {
return .5 * (1 + science.stats.erf(x / Math.SQRT2));
};
// See <http://en.wikipedia.org/wiki/Kernel_(statistics)>.
science.stats.kernel = {
uniform: function(u) {
@ -94,10 +188,470 @@ science.stats.kde = function() {
return kde;
};
// Based on figue implementation by Jean-Yves Delort.
// http://code.google.com/p/figue/
science.stats.kmeans = function() {
var distance = science.stats.distance.euclidean,
maxIterations = 1000,
k = 1;
function kmeans(vectors) {
var n = vectors.length,
assignments = [],
clusterSizes = [],
repeat = 1,
iterations = 0,
centroids = science_stats_kmeansRandom(k, vectors),
newCentroids,
i,
j,
x,
d,
min,
best;
while (repeat && iterations < maxIterations) {
// Assignment step.
j = -1; while (++j < k) {
clusterSizes[j] = 0;
}
i = -1; while (++i < n) {
x = vectors[i];
min = Infinity;
j = -1; while (++j < k) {
d = distance.call(this, centroids[j], x);
if (d < min) {
min = d;
best = j;
}
}
clusterSizes[assignments[i] = best]++;
}
// Update centroids step.
newCentroids = [];
i = -1; while (++i < n) {
x = assignments[i];
d = newCentroids[x];
if (d == null) newCentroids[x] = vectors[i].slice();
else {
j = -1; while (++j < d.length) {
d[j] += vectors[i][j];
}
}
}
j = -1; while (++j < k) {
x = newCentroids[j];
d = 1 / clusterSizes[j];
i = -1; while (++i < x.length) x[i] *= d;
}
// Check convergence.
repeat = 0;
j = -1; while (++j < k) {
if (!science_stats_kmeansCompare(newCentroids[j], centroids[j])) {
repeat = 1;
break;
}
}
centroids = newCentroids;
iterations++;
}
return {assignments: assignments, centroids: centroids};
}
kmeans.k = function(x) {
if (!arguments.length) return k;
k = x;
return kmeans;
};
kmeans.distance = function(x) {
if (!arguments.length) return distance;
distance = x;
return kmeans;
};
return kmeans;
};
function science_stats_kmeansCompare(a, b) {
if (!a || !b || a.length !== b.length) return false;
var n = a.length,
i = -1;
while (++i < n) if (a[i] !== b[i]) return false;
return true;
}
// Returns an array of k distinct vectors randomly selected from the input
// array of vectors. Returns null if k > n or if there are less than k distinct
// objects in vectors.
function science_stats_kmeansRandom(k, vectors) {
var n = vectors.length;
if (k > n) return null;
var selected_vectors = [];
var selected_indices = [];
var tested_indices = {};
var tested = 0;
var selected = 0;
var i,
vector,
select;
while (selected < k) {
if (tested === n) return null;
var random_index = Math.floor(Math.random() * n);
if (random_index in tested_indices) continue;
tested_indices[random_index] = 1;
tested++;
vector = vectors[random_index];
select = true;
for (i = 0; i < selected; i++) {
if (science_stats_kmeansCompare(vector, selected_vectors[i])) {
select = false;
break;
}
}
if (select) {
selected_vectors[selected] = vector;
selected_indices[selected] = random_index;
selected++;
}
}
return selected_vectors;
}
science.stats.hcluster = function() {
var distance = science.stats.distance.euclidean,
linkage = "simple"; // simple, complete or average
function hcluster(vectors) {
var n = vectors.length,
dMin = [],
cSize = [],
distMatrix = [],
clusters = [],
c1,
c2,
c1Cluster,
c2Cluster,
p,
root,
i,
j;
// Initialise distance matrix and vector of closest clusters.
i = -1; while (++i < n) {
dMin[i] = 0;
distMatrix[i] = [];
j = -1; while (++j < n) {
distMatrix[i][j] = i === j ? Infinity : distance(vectors[i] , vectors[j]);
if (distMatrix[i][dMin[i]] > distMatrix[i][j]) dMin[i] = j;
}
}
// create leaves of the tree
i = -1; while (++i < n) {
clusters[i] = [];
clusters[i][0] = {
left: null,
right: null,
dist: 0,
centroid: vectors[i],
size: 1,
depth: 0
};
cSize[i] = 1;
}
// Main loop
for (p = 0; p < n-1; p++) {
// find the closest pair of clusters
c1 = 0;
for (i = 0; i < n; i++) {
if (distMatrix[i][dMin[i]] < distMatrix[c1][dMin[c1]]) c1 = i;
}
c2 = dMin[c1];
// create node to store cluster info
c1Cluster = clusters[c1][0];
c2Cluster = clusters[c2][0];
newCluster = {
left: c1Cluster,
right: c2Cluster,
dist: distMatrix[c1][c2],
centroid: calculateCentroid(c1Cluster.size, c1Cluster.centroid,
c2Cluster.size, c2Cluster.centroid),
size: c1Cluster.size + c2Cluster.size,
depth: 1 + Math.max(c1Cluster.depth, c2Cluster.depth)
};
clusters[c1].splice(0, 0, newCluster);
cSize[c1] += cSize[c2];
// overwrite row c1 with respect to the linkage type
for (j = 0; j < n; j++) {
switch (linkage) {
case "single":
if (distMatrix[c1][j] > distMatrix[c2][j])
distMatrix[j][c1] = distMatrix[c1][j] = distMatrix[c2][j];
break;
case "complete":
if (distMatrix[c1][j] < distMatrix[c2][j])
distMatrix[j][c1] = distMatrix[c1][j] = distMatrix[c2][j];
break;
case "average":
distMatrix[j][c1] = distMatrix[c1][j] = (cSize[c1] * distMatrix[c1][j] + cSize[c2] * distMatrix[c2][j]) / (cSize[c1] + cSize[j]);
break;
}
}
distMatrix[c1][c1] = Infinity;
// infinity ­out old row c2 and column c2
for (i = 0; i < n; i++)
distMatrix[i][c2] = distMatrix[c2][i] = Infinity;
// update dmin and replace ones that previous pointed to c2 to point to c1
for (j = 0; j < n; j++) {
if (dMin[j] == c2) dMin[j] = c1;
if (distMatrix[c1][j] < distMatrix[c1][dMin[c1]]) dMin[c1] = j;
}
// keep track of the last added cluster
root = newCluster;
}
return root;
}
hcluster.distance = function(x) {
if (!arguments.length) return distance;
distance = x;
return hcluster;
};
return hcluster;
};
function calculateCentroid(c1Size, c1Centroid, c2Size, c2Centroid) {
var newCentroid = [],
newSize = c1Size + c2Size,
n = c1Centroid.length,
i = -1;
while (++i < n) {
newCentroid[i] = (c1Size * c1Centroid[i] + c2Size * c2Centroid[i]) / newSize;
}
return newCentroid;
}
science.stats.iqr = function(x) {
var quartiles = science.stats.quantiles(x, [.25, .75]);
return quartiles[1] - quartiles[0];
};
// Based on org.apache.commons.math.analysis.interpolation.LoessInterpolator
// from http://commons.apache.org/math/
science.stats.loess = function() {
var bandwidth = .3,
robustnessIters = 2,
accuracy = 1e-12;
function smooth(xval, yval, weights) {
var n = xval.length,
i;
if (n !== yval.length) throw {error: "Mismatched array lengths"};
if (n == 0) throw {error: "At least one point required."};
if (arguments.length < 3) {
weights = [];
i = -1; while (++i < n) weights[i] = 1;
}
science_stats_loessFiniteReal(xval);
science_stats_loessFiniteReal(yval);
science_stats_loessFiniteReal(weights);
science_stats_loessStrictlyIncreasing(xval);
if (n == 1) return [yval[0]];
if (n == 2) return [yval[0], yval[1]];
var bandwidthInPoints = Math.floor(bandwidth * n);
if (bandwidthInPoints < 2) throw {error: "Bandwidth too small."};
var res = [],
residuals = [],
robustnessWeights = [];
// Do an initial fit and 'robustnessIters' robustness iterations.
// This is equivalent to doing 'robustnessIters+1' robustness iterations
// starting with all robustness weights set to 1.
i = -1; while (++i < n) {
res[i] = 0;
residuals[i] = 0;
robustnessWeights[i] = 1;
}
var iter = -1;
while (++iter <= robustnessIters) {
var bandwidthInterval = [0, bandwidthInPoints - 1];
// At each x, compute a local weighted linear regression
var x;
i = -1; while (++i < n) {
x = xval[i];
// Find out the interval of source points on which
// a regression is to be made.
if (i > 0) {
science_stats_loessUpdateBandwidthInterval(xval, weights, i, bandwidthInterval);
}
var ileft = bandwidthInterval[0],
iright = bandwidthInterval[1];
// Compute the point of the bandwidth interval that is
// farthest from x
var edge = (xval[i] - xval[ileft]) > (xval[iright] - xval[i]) ? ileft : iright;
// Compute a least-squares linear fit weighted by
// the product of robustness weights and the tricube
// weight function.
// See http://en.wikipedia.org/wiki/Linear_regression
// (section "Univariate linear case")
// and http://en.wikipedia.org/wiki/Weighted_least_squares
// (section "Weighted least squares")
var sumWeights = 0,
sumX = 0,
sumXSquared = 0,
sumY = 0,
sumXY = 0,
denom = Math.abs(1 / (xval[edge] - x));
for (var k = ileft; k <= iright; ++k) {
var xk = xval[k],
yk = yval[k],
dist = k < i ? x - xk : xk - x,
w = science_stats_loessTricube(dist * denom) * robustnessWeights[k] * weights[k],
xkw = xk * w;
sumWeights += w;
sumX += xkw;
sumXSquared += xk * xkw;
sumY += yk * w;
sumXY += yk * xkw;
}
var meanX = sumX / sumWeights,
meanY = sumY / sumWeights,
meanXY = sumXY / sumWeights,
meanXSquared = sumXSquared / sumWeights;
var beta = (Math.sqrt(Math.abs(meanXSquared - meanX * meanX)) < accuracy)
? 0 : ((meanXY - meanX * meanY) / (meanXSquared - meanX * meanX));
var alpha = meanY - beta * meanX;
res[i] = beta * x + alpha;
residuals[i] = Math.abs(yval[i] - res[i]);
}
// No need to recompute the robustness weights at the last
// iteration, they won't be needed anymore
if (iter === robustnessIters) {
break;
}
// Recompute the robustness weights.
// Find the median residual.
var sortedResiduals = residuals.slice();
sortedResiduals.sort();
var medianResidual = sortedResiduals[Math.floor(n / 2)];
if (Math.abs(medianResidual) < accuracy)
break;
var arg,
w;
i = -1; while (++i < n) {
arg = residuals[i] / (6 * medianResidual);
robustnessWeights[i] = (arg >= 1) ? 0 : ((w = 1 - arg * arg) * w);
}
}
return res;
}
smooth.bandwidth = function(x) {
if (!arguments.length) return x;
bandwidth = x;
return smooth;
};
smooth.robustnessIterations = function(x) {
if (!arguments.length) return x;
robustnessIters = x;
return smooth;
};
smooth.accuracy = function(x) {
if (!arguments.length) return x;
accuracy = x;
return smooth;
};
return smooth;
};
function science_stats_loessFiniteReal(values) {
var n = values.length,
i = -1;
while (++i < n) if (!isFinite(values[i])) return false;
return true;
}
function science_stats_loessStrictlyIncreasing(xval) {
var n = xval.length,
i = 0;
while (++i < n) if (xval[i - 1] >= xval[i]) return false;
return true;
}
// Compute the tricube weight function.
// http://en.wikipedia.org/wiki/Local_regression#Weight_function
function science_stats_loessTricube(x) {
return (x = 1 - x * x * x) * x * x;
}
// Given an index interval into xval that embraces a certain number of
// points closest to xval[i-1], update the interval so that it embraces
// the same number of points closest to xval[i], ignoring zero weights.
function science_stats_loessUpdateBandwidthInterval(
xval, weights, i, bandwidthInterval) {
var left = bandwidthInterval[0],
right = bandwidthInterval[1];
// The right edge should be adjusted if the next point to the right
// is closer to xval[i] than the leftmost point of the current interval
var nextRight = science_stats_loessNextNonzero(weights, right);
if ((nextRight < xval.length) && (xval[nextRight] - xval[i]) < (xval[i] - xval[left])) {
var nextLeft = science_stats_loessNextNonzero(weights, left);
bandwidthInterval[0] = nextLeft;
bandwidthInterval[1] = nextRight;
}
}
function science_stats_loessNextNonzero(weights, i) {
var j = i + 1;
while (j < weights.length && weights[j] === 0) j++;
return j;
}
// Welford's algorithm.
science.stats.mean = function(x) {
var n = x.length;

2
lib/science/science.stats.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,14 +1,28 @@
{
"name": "d3",
"version": "1.29.5",
"version": "2.5.2",
"description": "A small, free JavaScript library for manipulating documents based on data.",
"keywords": ["dom", "w3c", "visualization", "svg", "animation", "canvas"],
"keywords": [
"dom",
"w3c",
"visualization",
"svg",
"animation",
"canvas"
],
"homepage": "http://mbostock.github.com/d3/",
"author": {"name": "Mike Bostock", "url": "http://bost.ocks.org/mike"},
"repository": {"type": "git", "url": "http://github.com/mbostock/d3.git"},
"author": {
"name": "Mike Bostock",
"url": "http://bost.ocks.org/mike"
},
"repository": {
"type": "git",
"url": "http://github.com/mbostock/d3.git"
},
"main": "d3.js",
"dependencies": {
"uglify-js": "1.0.6",
"jsdom": "0.2.3",
"vows": "0.5.10"
"uglify-js": "1.1.1",
"jsdom": "0.2.9",
"vows": "0.5.13"
}
}

Просмотреть файл

@ -17,6 +17,7 @@ d3.behavior.drag = function() {
// snapshot the local context for subsequent dispatch
function start() {
d3_behavior_dragEvent = event;
d3_behavior_dragEventTarget = d3.event.target;
d3_behavior_dragOffset = d3_behavior_dragPoint((d3_behavior_dragTarget = this).parentNode);
d3_behavior_dragMoved = 0;
d3_behavior_dragArguments = arguments;
@ -27,15 +28,11 @@ d3.behavior.drag = function() {
d3_behavior_dragDispatch("dragstart");
}
drag.on = function(type, listener) {
event[type].add(listener);
return drag;
};
return drag;
return d3.rebind(drag, event, "on");
};
var d3_behavior_dragEvent,
d3_behavior_dragEventTarget,
d3_behavior_dragTarget,
d3_behavior_dragArguments,
d3_behavior_dragOffset,
@ -55,7 +52,7 @@ function d3_behavior_dragDispatch(type) {
try {
d3.event = {dx: dx, dy: dy};
d3_behavior_dragEvent[type].dispatch.apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
d3_behavior_dragEvent[type].apply(d3_behavior_dragTarget, d3_behavior_dragArguments);
} finally {
d3.event = o;
}
@ -63,10 +60,10 @@ function d3_behavior_dragDispatch(type) {
o.preventDefault();
}
function d3_behavior_dragPoint(container) {
return d3.event.touches
? d3.svg.touches(container)[0]
: d3.svg.mouse(container);
function d3_behavior_dragPoint(container, type) {
// TODO Track touch points by identifier.
var t = d3.event.changedTouches;
return t ? d3.svg.touches(container, t)[0] : d3.svg.mouse(container);
}
function d3_behavior_dragMove() {
@ -77,7 +74,7 @@ function d3_behavior_dragMove() {
if (!parent) return d3_behavior_dragUp();
d3_behavior_dragDispatch("drag");
d3_behavior_dragCancel();
d3_eventCancel();
}
function d3_behavior_dragUp() {
@ -87,20 +84,16 @@ function d3_behavior_dragUp() {
// If the node was moved, prevent the mouseup from propagating.
// Also prevent the subsequent click from propagating (e.g., for anchors).
if (d3_behavior_dragMoved) {
if (d3_behavior_dragMoved && d3_behavior_dragEventTarget === d3.event.target) {
d3_behavior_dragStopClick = true;
d3_behavior_dragCancel();
d3_eventCancel();
}
}
function d3_behavior_dragClick() {
if (d3_behavior_dragStopClick) {
d3_behavior_dragCancel();
if (d3_behavior_dragStopClick && d3_behavior_dragEventTarget === d3.event.target) {
d3_eventCancel();
d3_behavior_dragStopClick = false;
d3_behavior_dragEventTarget = null;
}
}
function d3_behavior_dragCancel() {
d3.event.stopPropagation();
d3.event.preventDefault();
}

Просмотреть файл

@ -1,8 +1,8 @@
// TODO unbind zoom behavior?
// TODO unbind listener?
d3.behavior.zoom = function() {
var xyz = [0, 0, 0],
event = d3.dispatch("zoom");
event = d3.dispatch("zoom"),
extent = d3_behavior_zoomInfiniteExtent;
function zoom() {
this
@ -23,7 +23,9 @@ d3.behavior.zoom = function() {
// snapshot the local context for subsequent dispatch
function start() {
d3_behavior_zoomXyz = xyz;
d3_behavior_zoomDispatch = event.zoom.dispatch;
d3_behavior_zoomExtent = extent;
d3_behavior_zoomDispatch = event.zoom;
d3_behavior_zoomEventTarget = d3.event.target;
d3_behavior_zoomTarget = this;
d3_behavior_zoomArguments = arguments;
}
@ -61,12 +63,13 @@ d3.behavior.zoom = function() {
d3_behavior_zoomLast = now;
}
zoom.on = function(type, listener) {
event[type].add(listener);
zoom.extent = function(x) {
if (!arguments.length) return extent;
extent = x == null ? d3_behavior_zoomInfiniteExtent : x;
return zoom;
};
return zoom;
return d3.rebind(zoom, event, "on");
};
var d3_behavior_zoomDiv,
@ -75,7 +78,9 @@ var d3_behavior_zoomDiv,
d3_behavior_zoomLocations = {}, // identifier -> location
d3_behavior_zoomLast = 0,
d3_behavior_zoomXyz,
d3_behavior_zoomExtent,
d3_behavior_zoomDispatch,
d3_behavior_zoomEventTarget,
d3_behavior_zoomTarget,
d3_behavior_zoomArguments,
d3_behavior_zoomMoved,
@ -166,40 +171,45 @@ function d3_behavior_zoomMousemove() {
function d3_behavior_zoomMouseup() {
if (d3_behavior_zoomPanning) {
if (d3_behavior_zoomMoved) d3_behavior_zoomStopClick = true;
if (d3_behavior_zoomMoved && d3_behavior_zoomEventTarget === d3.event.target) {
d3_behavior_zoomStopClick = true;
}
d3_behavior_zoomMousemove();
d3_behavior_zoomPanning = null;
}
}
function d3_behavior_zoomClick() {
if (d3_behavior_zoomStopClick) {
if (d3_behavior_zoomStopClick && d3_behavior_zoomEventTarget === d3.event.target) {
d3.event.stopPropagation();
d3.event.preventDefault();
d3_behavior_zoomStopClick = false;
d3_behavior_zoomEventTarget = null;
}
}
function d3_behavior_zoomTo(z, x0, x1) {
var K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]),
x = d3_behavior_zoomXyz[0] = x0[0] - K * x1[0],
y = d3_behavior_zoomXyz[1] = x0[1] - K * x1[1],
o = d3.event, // Events can be reentrant (e.g., focus).
k = Math.pow(2, z);
z = d3_behavior_zoomExtentClamp(z, 2);
var j = Math.pow(2, d3_behavior_zoomXyz[2]),
k = Math.pow(2, z),
K = Math.pow(2, (d3_behavior_zoomXyz[2] = z) - x1[2]),
x_ = d3_behavior_zoomXyz[0],
y_ = d3_behavior_zoomXyz[1],
x = d3_behavior_zoomXyz[0] = d3_behavior_zoomExtentClamp((x0[0] - x1[0] * K), 0, k),
y = d3_behavior_zoomXyz[1] = d3_behavior_zoomExtentClamp((x0[1] - x1[1] * K), 1, k),
o = d3.event; // Events can be reentrant (e.g., focus).
d3.event = {
scale: k,
translate: [x, y],
transform: function(sx, sy) {
if (sx) transform(sx, x);
if (sy) transform(sy, y);
if (sx) transform(sx, x_, x);
if (sy) transform(sy, y_, y);
}
};
function transform(scale, o) {
var domain = scale.__domain || (scale.__domain = scale.domain()),
range = scale.range().map(function(v) { return (v - o) / k; });
scale.domain(domain).domain(range.map(scale.invert));
function transform(scale, a, b) {
scale.domain(scale.range().map(function(v) { return scale.invert(((v - b) * j) / k + a); }));
}
try {
@ -210,3 +220,19 @@ function d3_behavior_zoomTo(z, x0, x1) {
o.preventDefault();
}
var d3_behavior_zoomInfiniteExtent = [
[-Infinity, Infinity],
[-Infinity, Infinity],
[-Infinity, Infinity]
];
function d3_behavior_zoomExtentClamp(x, i, k) {
var range = d3_behavior_zoomExtent[i],
r0 = range[0],
r1 = range[1];
return arguments.length === 3
? Math.max(r1 * (r1 === Infinity ? -Infinity : 1 / k - 1),
Math.min(r0 === -Infinity ? Infinity : r0, x / k)) * k
: Math.max(r0, Math.min(r1, x));
}

Просмотреть файл

9
src/compat/style.js Normal file
Просмотреть файл

@ -0,0 +1,9 @@
try {
document.createElement("div").style.setProperty("opacity", 0, "");
} catch (error) {
var d3_style_prototype = CSSStyleDeclaration.prototype,
d3_style_setProperty = d3_style_prototype.setProperty;
d3_style_prototype.setProperty = function(name, value, priority) {
d3_style_setProperty.call(this, name, value + "", priority);
};
}

Просмотреть файл

@ -1,3 +1,21 @@
var d3_array = d3_arraySlice; // conversion for NodeLists
function d3_arrayCopy(pseudoarray) {
var i = -1, n = pseudoarray.length, array = [];
while (++i < n) array.push(pseudoarray[i]);
return array;
}
function d3_arraySlice(pseudoarray) {
return Array.prototype.slice.call(pseudoarray);
}
try {
d3_array(document.documentElement.childNodes)[0].nodeType;
} catch(e) {
d3_array = d3_arrayCopy;
}
var d3_arraySubclass = [].__proto__?
// Until ECMAScript supports array subclassing, prototype injection works well.

Просмотреть файл

@ -1 +1 @@
d3 = {version: "2.0.4"}; // semver
d3 = {version: "2.5.2"}; // semver

Просмотреть файл

@ -1,45 +1,60 @@
/** @param {...string} types */
d3.dispatch = function(types) {
var dispatch = {},
type;
for (var i = 0, n = arguments.length; i < n; i++) {
type = arguments[i];
dispatch[type] = d3_dispatch(type);
d3.dispatch = function() {
var dispatch = new d3_dispatch(),
i = -1,
n = arguments.length;
while (++i < n) dispatch[arguments[i]] = d3_dispatch_event();
return dispatch;
};
function d3_dispatch() {}
d3_dispatch.prototype.on = function(type, listener) {
var i = type.indexOf("."),
name = "";
// Extract optional namespace, e.g., "click.foo"
if (i > 0) {
name = type.substring(i + 1);
type = type.substring(0, i);
}
return dispatch;
return arguments.length < 2
? this[type].on(name)
: (this[type].on(name, listener), this);
};
function d3_dispatch(type) {
var dispatch = {},
listeners = [];
function d3_dispatch_event() {
var listeners = [],
listenerByName = {};
dispatch.add = function(listener) {
for (var i = 0; i < listeners.length; i++) {
if (listeners[i].listener == listener) return dispatch; // already registered
function dispatch() {
var z = listeners, // defensive reference
i = -1,
n = z.length,
l;
while (++i < n) if (l = z[i].on) l.apply(this, arguments);
}
dispatch.on = function(name, listener) {
var l, i;
// return the current listener, if any
if (arguments.length < 2) return (l = listenerByName[name]) && l.on;
// remove the old listener, if any (with copy-on-write)
if (l = listenerByName[name]) {
l.on = null;
listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
delete listenerByName[name];
}
listeners.push({listener: listener, on: true});
// add the new listener, if any
if (listener) {
listeners.push(listenerByName[name] = {on: listener});
}
return dispatch;
};
dispatch.remove = function(listener) {
for (var i = 0; i < listeners.length; i++) {
var l = listeners[i];
if (l.listener == listener) {
l.on = false;
listeners = listeners.slice(0, i).concat(listeners.slice(i + 1));
break;
}
}
return dispatch;
};
dispatch.dispatch = function() {
var ls = listeners; // defensive reference
for (var i = 0, n = ls.length; i < n; i++) {
var l = ls[i];
if (l.on) l.listener.apply(this, arguments);
}
};
return dispatch;
};

Просмотреть файл

@ -60,9 +60,15 @@ d3.ease = function(name) {
var i = name.indexOf("-"),
t = i >= 0 ? name.substring(0, i) : name,
m = i >= 0 ? name.substring(i + 1) : "in";
return d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1)));
return d3_ease_clamp(d3_ease_mode[m](d3_ease[t].apply(null, Array.prototype.slice.call(arguments, 1))));
};
function d3_ease_clamp(f) {
return function(t) {
return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
};
}
function d3_ease_reverse(f) {
return function(t) {
return 1 - f(1 - t);

Просмотреть файл

@ -1 +1,6 @@
d3.event = null;
function d3_eventCancel() {
d3.event.stopPropagation();
d3.event.preventDefault();
}

21
src/core/extent.js Normal file
Просмотреть файл

@ -0,0 +1,21 @@
d3.extent = function(array, f) {
var i = -1,
n = array.length,
a,
b,
c;
if (arguments.length === 1) {
while (++i < n && ((a = c = array[i]) == null || a != a)) a = c = undefined;
while (++i < n) if ((b = array[i]) != null) {
if (a > b) a = b;
if (c < b) c = b;
}
} else {
while (++i < n && ((a = c = f.call(array, array[i], i)) == null || a != a)) a = undefined;
while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
if (a > b) a = b;
if (c < b) c = b;
}
}
return [a, c];
};

Просмотреть файл

@ -8,10 +8,11 @@ d3.format = function(specifier) {
comma = match[7],
precision = match[8],
type = match[9],
percentage = false,
scale = 1,
suffix = "",
integer = false;
if (precision) precision = precision.substring(1);
if (precision) precision = +precision.substring(1);
if (zfill) {
fill = "0"; // TODO align = "=";
@ -20,22 +21,36 @@ d3.format = function(specifier) {
switch (type) {
case "n": comma = true; type = "g"; break;
case "%": percentage = true; type = "f"; break;
case "p": percentage = true; type = "r"; break;
case "d": integer = true; precision = "0"; break;
case "%": scale = 100; suffix = "%"; type = "f"; break;
case "p": scale = 100; suffix = "%"; type = "r"; break;
case "d": integer = true; precision = 0; break;
case "s": scale = -1; type = "r"; break;
}
// If no precision is specified for r, fallback to general notation.
if (type == "r" && !precision) type = "g";
type = d3_format_types[type] || d3_format_typeDefault;
return function(value) {
var number = percentage ? value * 100 : +value,
negative = (number < 0) && (number = -number) ? "\u2212" : sign;
// Return the empty string for floats formatted as ints.
if (integer && (number % 1)) return "";
if (integer && (value % 1)) return "";
// Convert the input value to the desired precision.
value = type(number, precision);
// Convert negative to positive, and record the sign prefix.
var negative = (value < 0) && (value = -value) ? "\u2212" : sign;
// Apply the scale, computing it from the value's exponent for si format.
if (scale < 0) {
var prefix = d3.formatPrefix(value, precision);
value *= prefix.scale;
suffix = prefix.symbol;
} else {
value *= scale;
}
// Convert to the desired precision.
value = type(value, precision);
// If the fill character is 0, the sign and group is applied after the fill.
if (zfill) {
@ -52,9 +67,8 @@ d3.format = function(specifier) {
var length = value.length;
if (length < width) value = new Array(width - length + 1).join(fill) + value;
}
if (percentage) value += "%";
return value;
return value + suffix;
};
};
@ -65,12 +79,13 @@ var d3_format_types = {
g: function(x, p) { return x.toPrecision(p); },
e: function(x, p) { return x.toExponential(p); },
f: function(x, p) { return x.toFixed(p); },
r: function(x, p) {
var n = 1 + Math.floor(1e-15 + Math.log(x) / Math.LN10);
return d3.round(x, p - n).toFixed(Math.max(0, Math.min(20, p - n)));
}
r: function(x, p) { return d3.round(x, p = d3_format_precision(x, p)).toFixed(Math.max(0, Math.min(20, p))); }
};
function d3_format_precision(x, p) {
return p - (x ? 1 + Math.floor(Math.log(x + Math.pow(10, 1 + Math.floor(Math.log(x) / Math.LN10) - p)) / Math.LN10) : 1);
}
function d3_format_typeDefault(x) {
return x + "";
}

20
src/core/formatPrefix.js Normal file
Просмотреть файл

@ -0,0 +1,20 @@
var d3_formatPrefixes = ["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(d3_formatPrefix);
d3.formatPrefix = function(value, precision) {
var i = 0;
if (value) {
if (value < 0) value *= -1;
if (precision) value = d3.round(value, d3_format_precision(value, precision));
i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
i = Math.max(-24, Math.min(24, Math.floor((i <= 0 ? i + 1 : i - 1) / 3) * 3));
}
return d3_formatPrefixes[8 + i / 3];
};
function d3_formatPrefix(d, i) {
return {
scale: Math.pow(10, (8 - i) * 3),
symbol: d
};
}

Просмотреть файл

@ -1,6 +1,7 @@
d3.hsl = function(h, s, l) {
return arguments.length === 1
? d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl)
? (h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l)
: d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
: d3_hsl(+h, +s, +l);
};
@ -29,7 +30,7 @@ d3_Hsl.prototype.rgb = function() {
};
d3_Hsl.prototype.toString = function() {
return "hsl(" + this.h + "," + this.s * 100 + "%," + this.l * 100 + "%)";
return this.rgb().toString();
};
function d3_hsl_rgb(h, s, l) {

Просмотреть файл

@ -92,6 +92,10 @@ d3.interpolateString = function(a, b) {
};
};
d3.interpolateTransform = function(a, b) {
return d3.interpolateString(d3.transform(a) + "", d3.transform(b) + "");
};
d3.interpolateRgb = function(a, b) {
a = d3.rgb(a);
b = d3.rgb(b);
@ -102,10 +106,10 @@ d3.interpolateRgb = function(a, b) {
bg = b.g - ag,
bb = b.b - ab;
return function(t) {
return "rgb(" + Math.round(ar + br * t)
+ "," + Math.round(ag + bg * t)
+ "," + Math.round(ab + bb * t)
+ ")";
return "#"
+ d3_rgb_hex(Math.round(ar + br * t))
+ d3_rgb_hex(Math.round(ag + bg * t))
+ d3_rgb_hex(Math.round(ab + bb * t));
};
};
@ -162,19 +166,18 @@ d3.interpolateObject = function(a, b) {
};
}
var d3_interpolate_number = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g,
d3_interpolate_rgb = {background: 1, fill: 1, stroke: 1};
var d3_interpolate_number = /[-+]?(?:\d*\.?\d+)(?:[eE][-+]?\d+)?/g;
function d3_interpolateByName(n) {
return n in d3_interpolate_rgb || /\bcolor\b/.test(n)
? d3.interpolateRgb
return n == "transform"
? d3.interpolateTransform
: d3.interpolate;
}
d3.interpolators = [
d3.interpolateObject,
function(a, b) { return (b instanceof Array) && d3.interpolateArray(a, b); },
function(a, b) { return (typeof b === "string") && d3.interpolateString(String(a), b); },
function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(String(a), b); },
function(a, b) { return (typeof b === "string") && d3.interpolateString(a + "", b); },
function(a, b) { return (typeof b === "string" ? b in d3_rgb_names || /^(#|rgb\(|hsl\()/.test(b) : b instanceof d3_Rgb || b instanceof d3_Hsl) && d3.interpolateRgb(a + "", b); },
function(a, b) { return (typeof b === "number") && d3.interpolateNumber(+a, b); }
];

13
src/core/mean.js Normal file
Просмотреть файл

@ -0,0 +1,13 @@
d3.mean = function(array, f) {
var n = array.length,
a,
m = 0,
i = -1,
j = 0;
if (arguments.length === 1) {
while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
} else {
while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
}
return j ? m : undefined;
};

5
src/core/median.js Normal file
Просмотреть файл

@ -0,0 +1,5 @@
d3.median = function(array, f) {
if (arguments.length > 1) array = array.map(f);
array = array.filter(d3_number);
return array.length ? d3.quantile(array.sort(d3.ascending), .5) : undefined;
};

3
src/core/number.js Normal file
Просмотреть файл

@ -0,0 +1,3 @@
function d3_number(x) {
return x != null && !isNaN(x);
}

Просмотреть файл

@ -1,5 +0,0 @@
if (!Object.create) Object.create = function(o) {
/** @constructor */ function f() {}
f.prototype = o;
return new f;
};

15
src/core/random.js Normal file
Просмотреть файл

@ -0,0 +1,15 @@
d3.random = {
normal: function(mean, deviation) {
if (arguments.length < 2) deviation = 1;
if (arguments.length < 1) mean = 0;
return function() {
var x, y, r;
do {
x = Math.random() * 2 - 1;
y = Math.random() * 2 - 1;
r = x * x + y * y;
} while (!r || r > 1);
return mean + deviation * x * Math.sqrt(-2 * Math.log(r) / r);
};
}
};

Просмотреть файл

@ -1,7 +1,16 @@
// A getter-setter method that preserves the appropriate `this` context.
d3.rebind = function(object, method) {
return function() {
var x = method.apply(object, arguments);
return arguments.length ? object : x;
};
// Copies a variable number of methods from source to target.
d3.rebind = function(target, source) {
var i = 1, n = arguments.length, method;
while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
return target;
};
// Method is assumed to be a standard D3 getter-setter:
// If passed with no arguments, gets the value.
// If passed with arguments, sets the value and returns the target.
function d3_rebind(target, source, method) {
return function() {
var value = method.apply(source, arguments);
return arguments.length ? target : value;
};
}

Просмотреть файл

@ -1,6 +1,7 @@
d3.rgb = function(r, g, b) {
return arguments.length === 1
? d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb)
? (r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b)
: d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
: d3_rgb(~~r, ~~g, ~~b);
};
@ -25,17 +26,17 @@ d3_Rgb.prototype.brighter = function(k) {
if (g && g < i) g = i;
if (b && b < i) b = i;
return d3_rgb(
Math.min(255, Math.floor(r / k)),
Math.min(255, Math.floor(g / k)),
Math.min(255, Math.floor(b / k)));
Math.min(255, Math.floor(r / k)),
Math.min(255, Math.floor(g / k)),
Math.min(255, Math.floor(b / k)));
};
d3_Rgb.prototype.darker = function(k) {
k = Math.pow(0.7, arguments.length ? k : 1);
return d3_rgb(
Math.max(0, Math.floor(k * this.r)),
Math.max(0, Math.floor(k * this.g)),
Math.max(0, Math.floor(k * this.b)));
Math.floor(k * this.r),
Math.floor(k * this.g),
Math.floor(k * this.b));
};
d3_Rgb.prototype.hsl = function() {
@ -47,7 +48,9 @@ d3_Rgb.prototype.toString = function() {
};
function d3_rgb_hex(v) {
return v < 0x10 ? "0" + v.toString(16) : v.toString(16);
return v < 0x10
? "0" + Math.max(0, v).toString(16)
: Math.min(255, v).toString(16);
}
function d3_rgb_parse(format, rgb, hsl) {

Просмотреть файл

@ -1,4 +1,19 @@
d3_selectionPrototype.classed = function(name, value) {
var names = name.split(d3_selection_classedWhitespace),
n = names.length,
i = -1;
if (arguments.length > 1) {
while (++i < n) d3_selection_classed.call(this, names[i], value);
return this;
} else {
while (++i < n) if (!d3_selection_classed.call(this, names[i])) return false;
return true;
}
};
var d3_selection_classedWhitespace = /\s+/g;
function d3_selection_classed(name, value) {
var re = new RegExp("(^|\\s+)" + d3.requote(name) + "(\\s+|$)", "g");
// If no value is specified, return the first value.
@ -43,4 +58,4 @@ d3_selectionPrototype.classed = function(name, value) {
? classedFunction : value
? classedAdd
: classedRemove);
};
}

Просмотреть файл

@ -8,3 +8,4 @@ var d3_selection_enterPrototype = [];
d3_selection_enterPrototype.append = d3_selectionPrototype.append;
d3_selection_enterPrototype.insert = d3_selectionPrototype.insert;
d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
d3_selection_enterPrototype.node = d3_selectionPrototype.node;

Просмотреть файл

@ -3,14 +3,16 @@ var d3_selectionRoot = d3_selection([[document]]);
d3_selectionRoot[0].parentNode = document.documentElement;
// TODO fast singleton implementation!
// TODO select(function)
d3.select = function(selector) {
return typeof selector === "string"
? d3_selectionRoot.select(selector)
: d3_selection([[selector]]); // assume node
};
// TODO selectAll(function)
d3.selectAll = function(selector) {
return typeof selector === "string"
? d3_selectionRoot.selectAll(selector)
: d3_selection([selector]); // assume node[]
: d3_selection([d3_array(selector)]); // assume node[]
};

Просмотреть файл

@ -8,7 +8,7 @@ d3_selectionPrototype.selectAll = function(selector) {
for (var j = -1, m = this.length; ++j < m;) {
for (var group = this[j], i = -1, n = group.length; ++i < n;) {
if (node = group[i]) {
subgroups.push(subgroup = selector.call(node, node.__data__, i));
subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i)));
subgroup.parentNode = node;
}
}

Просмотреть файл

@ -10,5 +10,5 @@ d3_selectionPrototype.transition = function() {
}
}
return d3_transition(subgroups, d3_transitionInheritId || ++d3_transitionId);
return d3_transition(subgroups, d3_transitionInheritId || ++d3_transitionId, Date.now());
};

58
src/core/transform.js Normal file
Просмотреть файл

@ -0,0 +1,58 @@
d3.transform = function(string) {
d3_transformG.setAttribute("transform", string);
var t = d3_transformG.transform.baseVal.consolidate();
return new d3_transform(t ? t.matrix : d3_transformIdentity);
};
// Compute x-scale and normalize the first row.
// Compute shear and make second row orthogonal to first.
// Compute y-scale and normalize the second row.
// Finally, compute the rotation.
function d3_transform(m) {
var r0 = [m.a, m.b],
r1 = [m.c, m.d],
kx = d3_transformNormalize(r0),
kz = d3_transformDot(r0, r1),
ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
if (r0[0] * r1[1] < r1[0] * r0[1]) {
r0[0] *= -1;
r0[1] *= -1;
kx *= -1;
kz *= -1;
}
this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_transformDegrees;
this.translate = [m.e, m.f];
this.scale = [kx, ky];
this.skew = ky ? Math.atan2(kz, ky) * d3_transformDegrees : 0;
};
d3_transform.prototype.toString = function() {
return "translate(" + this.translate
+ ")rotate(" + this.rotate
+ ")skewX(" + this.skew
+ ")scale(" + this.scale
+ ")";
};
function d3_transformDot(a, b) {
return a[0] * b[0] + a[1] * b[1];
}
function d3_transformNormalize(a) {
var k = Math.sqrt(d3_transformDot(a, a));
if (k) {
a[0] /= k;
a[1] /= k;
}
return k;
}
function d3_transformCombine(a, b, k) {
a[0] += k * b[0];
a[1] += k * b[1];
return a;
}
var d3_transformG = document.createElementNS(d3.ns.prefix.svg, "g"),
d3_transformIdentity = {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0},
d3_transformDegrees = 180 / Math.PI;

Просмотреть файл

@ -1,23 +1,23 @@
d3_transitionPrototype.attr = function(name, value) {
return this.attrTween(name, d3_transitionTween(value));
return this.attrTween(name, d3_transitionTween(name, value));
};
d3_transitionPrototype.attrTween = function(name, tween) {
name = d3.ns.qualify(name);
d3_transitionPrototype.attrTween = function(nameNS, tween) {
var name = d3.ns.qualify(nameNS);
function attrTween(d, i) {
var f = tween.call(this, d, i, this.getAttribute(name));
return f && function(t) {
this.setAttribute(name, f(t));
};
return f === d3_transitionRemove
? (this.removeAttribute(name), null)
: f && function(t) { this.setAttribute(name, f(t)); };
}
function attrTweenNS(d, i) {
var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
return f && function(t) {
this.setAttributeNS(name.space, name.local, f(t));
};
return f === d3_transitionRemove
? (this.removeAttributeNS(name.space, name.local), null)
: f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); };
}
return this.tween("attr." + name, name.local ? attrTweenNS : attrTween);
return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
};

Просмотреть файл

@ -18,5 +18,5 @@ d3_transitionPrototype.select = function(selector) {
}
}
return d3_transition(subgroups, this.id).ease(this.ease());
return d3_transition(subgroups, this.id, this.time).ease(this.ease());
};

Просмотреть файл

@ -1,6 +1,7 @@
d3_transitionPrototype.selectAll = function(selector) {
var subgroups = [],
subgroup,
subnodes,
node;
if (typeof selector !== "function") selector = d3_selection_selectorAll(selector);
@ -8,13 +9,14 @@ d3_transitionPrototype.selectAll = function(selector) {
for (var j = -1, m = this.length; ++j < m;) {
for (var group = this[j], i = -1, n = group.length; ++i < n;) {
if (node = group[i]) {
subgroups.push(subgroup = selector.call(node.node, node.node.__data__, i));
for (var k = -1, o = subgroup.length; ++k < o;) {
subgroup[k] = {node: subgroup[k], delay: node.delay, duration: node.duration};
subnodes = selector.call(node.node, node.node.__data__, i);
subgroups.push(subgroup = []);
for (var k = -1, o = subnodes.length; ++k < o;) {
subgroup.push({node: subnodes[k], delay: node.delay, duration: node.duration});
}
}
}
}
return d3_transition(subgroups, this.id).ease(this.ease());
return d3_transition(subgroups, this.id, this.time).ease(this.ease());
};

Просмотреть файл

@ -1,14 +1,14 @@
d3_transitionPrototype.style = function(name, value, priority) {
if (arguments.length < 3) priority = null;
return this.styleTween(name, d3_transitionTween(value), priority);
if (arguments.length < 3) priority = "";
return this.styleTween(name, d3_transitionTween(name, value), priority);
};
d3_transitionPrototype.styleTween = function(name, tween, priority) {
if (arguments.length < 3) priority = null;
if (arguments.length < 3) priority = "";
return this.tween("style." + name, function(d, i) {
var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name));
return f && function(t) {
this.style.setProperty(name, f(t), priority);
};
return f === d3_transitionRemove
? (this.style.removeProperty(name), null)
: f && function(t) { this.style.setProperty(name, f(t), priority); };
});
};

Просмотреть файл

@ -1,13 +1,14 @@
function d3_transition(groups, id) {
function d3_transition(groups, id, time) {
d3_arraySubclass(groups, d3_transitionPrototype);
var tweens = {},
event = d3.dispatch("start", "end"),
ease = d3_transitionEase,
then = Date.now();
ease = d3_transitionEase;
groups.id = id;
groups.time = time;
groups.tween = function(name, tween) {
if (arguments.length < 2) return tweens[name];
if (tween == null) delete tweens[name];
@ -23,7 +24,7 @@ function d3_transition(groups, id) {
groups.each = function(type, listener) {
if (arguments.length < 2) return d3_transition_each.call(groups, type);
event[type].add(listener);
event.on(type, listener);
return groups;
};
@ -37,9 +38,9 @@ function d3_transition(groups, id) {
++lock.count;
delay <= elapsed ? start() : d3.timer(start, delay, then);
delay <= elapsed ? start(elapsed) : d3.timer(start, delay, time);
function start() {
function start(elapsed) {
if (lock.active > id) return stop();
lock.active = id;
@ -49,15 +50,15 @@ function d3_transition(groups, id) {
}
}
event.start.dispatch.call(node, d, i);
d3.timer(tick, 0, then);
event.start.call(node, d, i);
if (!tick(elapsed)) d3.timer(tick, 0, time);
return 1;
}
function tick(elapsed) {
if (lock.active !== id) return stop();
var t = Math.min(1, (elapsed - delay) / duration),
var t = (elapsed - delay) / duration,
e = ease(t),
n = tweened.length;
@ -65,10 +66,10 @@ function d3_transition(groups, id) {
tweened[--n].call(node, e);
}
if (t === 1) {
if (t >= 1) {
stop();
d3_transitionInheritId = id;
event.end.dispatch.call(node, d, i);
event.end.call(node, d, i);
d3_transitionInheritId = 0;
return 1;
}
@ -80,15 +81,34 @@ function d3_transition(groups, id) {
}
});
return 1;
}, 0, then);
}, 0, time);
return groups;
}
function d3_transitionTween(b) {
return typeof b === "function"
? function(d, i, a) { var v = b.call(this, d, i) + ""; return a != v && d3.interpolate(a, v); }
: (b = b + "", function(d, i, a) { return a != b && d3.interpolate(a, b); });
var d3_transitionRemove = {};
function d3_transitionNull(d, i, a) {
return a != "" && d3_transitionRemove;
}
function d3_transitionTween(name, b) {
var interpolate = d3_interpolateByName(name);
function transitionFunction(d, i, a) {
var v = b.call(this, d, i);
return v == null
? a != "" && d3_transitionRemove
: a != v && interpolate(a, v);
}
function transitionString(d, i, a) {
return a != b && interpolate(a, b);
}
return typeof b === "function" ? transitionFunction
: b == null ? d3_transitionNull
: (b += "", transitionString);
}
var d3_transitionPrototype = [],

Просмотреть файл

@ -7,27 +7,39 @@ d3.geo.albers = function() {
parallels = [29.5, 45.5],
scale = 1000,
translate = [480, 250],
lng0, // d3_radians * origin[0]
lng0, // d3_geo_radians * origin[0]
n,
C,
p0;
function albers(coordinates) {
var t = n * (d3_radians * coordinates[0] - lng0),
p = Math.sqrt(C - 2 * n * Math.sin(d3_radians * coordinates[1])) / n;
var t = n * (d3_geo_radians * coordinates[0] - lng0),
p = Math.sqrt(C - 2 * n * Math.sin(d3_geo_radians * coordinates[1])) / n;
return [
scale * p * Math.sin(t) + translate[0],
scale * (p * Math.cos(t) - p0) + translate[1]
];
}
albers.invert = function(coordinates) {
var x = (coordinates[0] - translate[0]) / scale,
y = (coordinates[1] - translate[1]) / scale,
p0y = p0 + y,
t = Math.atan2(x, p0y),
p = Math.sqrt(x * x + p0y * p0y);
return [
(lng0 + t / n) / d3_geo_radians,
Math.asin((C - p * p * n * n) / (2 * n)) / d3_geo_radians
];
};
function reload() {
var phi1 = d3_radians * parallels[0],
phi2 = d3_radians * parallels[1],
lat0 = d3_radians * origin[1],
var phi1 = d3_geo_radians * parallels[0],
phi2 = d3_geo_radians * parallels[1],
lat0 = d3_geo_radians * origin[1],
s = Math.sin(phi1),
c = Math.cos(phi1);
lng0 = d3_radians * origin[0];
lng0 = d3_geo_radians * origin[0];
n = .5 * (s + Math.sin(phi2));
C = c * c + 2 * n * s;
p0 = Math.sqrt(C - 2 * n * Math.sin(lat0)) / n;
@ -112,5 +124,3 @@ d3.geo.albersUsa = function() {
return albersUsa.scale(lower48.scale());
};
var d3_radians = Math.PI / 180;

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше