mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Cleaning up misconceptions with d3
This commit is contained in:
parent
d3debd1f09
commit
88609fbe87
@ -1,6 +1,7 @@
|
||||
|
||||
function displayBinning(scope, dimensions, projection, path) {
|
||||
|
||||
|
||||
/**
|
||||
* Hexbin-specific setup
|
||||
*/
|
||||
@ -9,40 +10,51 @@ function displayBinning(scope, dimensions, projection, path) {
|
||||
.radius(scope.panel.display.binning.hexagonSize);
|
||||
|
||||
|
||||
var binPoints = [];
|
||||
var binPoints = [],
|
||||
binnedPoints = [],
|
||||
binRange = 0;
|
||||
|
||||
//primary field is just binning raw counts
|
||||
//secondary field is binning some metric like mean/median/total. Hexbins doesn't support that,
|
||||
//so we cheat a little and just add more points to compensate.
|
||||
//However, we don't want to add a million points, so normalize against the largest value
|
||||
if (scope.panel.display.binning.areaEncodingField === 'secondary') {
|
||||
var max = Math.max.apply(Math, _.map(scope.data, function(k,v){return k;})),
|
||||
scale = 50/max;
|
||||
|
||||
_.map(scope.data, function (k, v) {
|
||||
var decoded = geohash.decode(v);
|
||||
return _.map(_.range(0, k*scale), function(a,b) {
|
||||
binPoints.push(projection([decoded.longitude, decoded.latitude]));
|
||||
})
|
||||
});
|
||||
if (scope.panel.display.binning.enabled) {
|
||||
//primary field is just binning raw counts
|
||||
//secondary field is binning some metric like mean/median/total. Hexbins doesn't support that,
|
||||
//so we cheat a little and just add more points to compensate.
|
||||
//However, we don't want to add a million points, so normalize against the largest value
|
||||
if (scope.panel.display.binning.areaEncodingField === 'secondary') {
|
||||
var max = Math.max.apply(Math, _.map(scope.data, function(k,v){return k;})),
|
||||
scale = 50/max;
|
||||
|
||||
_.map(scope.data, function (k, v) {
|
||||
var decoded = geohash.decode(v);
|
||||
return _.map(_.range(0, k*scale), function(a,b) {
|
||||
binPoints.push(projection([decoded.longitude, decoded.latitude]));
|
||||
})
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
binPoints = scope.projectedPoints;
|
||||
}
|
||||
|
||||
//bin and sort the points, so we can set the various ranges appropriately
|
||||
binnedPoints = hexbin(binPoints).sort(function(a, b) { return b.length - a.length; });
|
||||
binRange = binnedPoints[0].length;
|
||||
|
||||
//clean up some memory
|
||||
binPoints = [];
|
||||
} else {
|
||||
|
||||
binPoints = scope.projectedPoints;
|
||||
binnedPoints = [];
|
||||
binRange = 0;
|
||||
}
|
||||
|
||||
//bin and sort the points, so we can set the various ranges appropriately
|
||||
var binnedPoints = hexbin(binPoints).sort(function(a, b) { return b.length - a.length; });;
|
||||
|
||||
//clean up some memory
|
||||
binPoints = [];
|
||||
|
||||
var radius = d3.scale.sqrt()
|
||||
.domain([0, binnedPoints[0].length])
|
||||
.domain([0, binRange])
|
||||
.range([0, scope.panel.display.binning.hexagonSize]);
|
||||
|
||||
var color = d3.scale.linear()
|
||||
.domain([0,binnedPoints[0].length])
|
||||
.domain([0,binRange])
|
||||
.range(["white", "steelblue"])
|
||||
.interpolate(d3.interpolateLab);
|
||||
|
||||
@ -51,10 +63,10 @@ function displayBinning(scope, dimensions, projection, path) {
|
||||
* D3 Drawing
|
||||
*/
|
||||
|
||||
var hex = scope.g.selectAll(".hexagon")
|
||||
.data(binnedPoints);
|
||||
|
||||
scope.g.selectAll("hexagon")
|
||||
.data(binnedPoints)
|
||||
.enter().append("path")
|
||||
hex.enter().append("path")
|
||||
.attr("d", function (d) {
|
||||
if (scope.panel.display.binning.areaEncoding === false) {
|
||||
return hexbin.hexagon();
|
||||
@ -74,4 +86,6 @@ function displayBinning(scope, dimensions, projection, path) {
|
||||
}
|
||||
})
|
||||
.attr("opacity", scope.panel.display.binning.hexagonAlpha);
|
||||
}
|
||||
|
||||
hex.exit().remove();
|
||||
}
|
||||
|
@ -5,30 +5,27 @@ function displayBullseye(scope, projection, path) {
|
||||
|
||||
var circle = d3.geo.circle();
|
||||
|
||||
var data = [
|
||||
{lat: parseFloat(scope.panel.display.bullseye.coord.lat), lon: parseFloat(scope.panel.display.bullseye.coord.lon)}
|
||||
];
|
||||
var data = [];
|
||||
|
||||
scope.g.selectAll("arc")
|
||||
.data(data)
|
||||
.enter().append("path")
|
||||
if (scope.panel.display.bullseye.enabled) {
|
||||
data = [
|
||||
{lat: parseFloat(scope.panel.display.bullseye.coord.lat), lon: parseFloat(scope.panel.display.bullseye.coord.lon)}
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
var arcs = scope.g.selectAll(".arc")
|
||||
.data(data);
|
||||
|
||||
|
||||
arcs.enter().append("path")
|
||||
.datum(function(d) {
|
||||
return circle.origin([d.lon, d.lat]).angle(1000 / 6371 * degrees)();
|
||||
})
|
||||
.attr("d", path)
|
||||
.attr("class", "arc");
|
||||
|
||||
arcs.exit().remove();
|
||||
|
||||
/*
|
||||
scope.g.append("path")
|
||||
.attr("d", arc)
|
||||
.attr("transform", "translate(" + coords[0] + "," + coords[1] + ")");
|
||||
|
||||
scope.g
|
||||
.append("circle")
|
||||
.attr("r", 1)
|
||||
.attr("opacity", 1)
|
||||
.attr("transform", "translate(" + coords[0] + "," + coords[1] + ")");
|
||||
*/
|
||||
|
||||
}
|
@ -1,29 +1,48 @@
|
||||
function displayGeopoints(scope, path) {
|
||||
|
||||
/*
|
||||
scope.g.selectAll("circles.points")
|
||||
.data(points)
|
||||
.enter()
|
||||
.append("circle")
|
||||
.attr("r", scope.panel.display.geopoints.pointSize)
|
||||
.attr("opacity", scope.panel.display.geopoints.pointAlpha)
|
||||
.attr("transform", function (d) {
|
||||
return "translate(" + d[0] + "," + d[1] + ")";
|
||||
});
|
||||
var points = {};
|
||||
var circle = d3.geo.circle();
|
||||
var degrees = 180 / Math.PI;
|
||||
|
||||
*/
|
||||
if (scope.panel.display.geopoints.enabled) {
|
||||
//points = scope.points;
|
||||
|
||||
var features = _.map(scope.points, function(coords) {
|
||||
return {
|
||||
feature: circle.origin(scope.projection([coords[0], coords[1]]))
|
||||
.angle(scope.panel.display.geopoints.pointSize / 6371 * degrees)()
|
||||
};
|
||||
});
|
||||
|
||||
console.log("features", features);
|
||||
points = {
|
||||
type: "FeatureCollection",
|
||||
features: features
|
||||
};
|
||||
console.log("points", points);
|
||||
|
||||
}
|
||||
|
||||
console.log("points2", points);
|
||||
scope.svg.append("path")
|
||||
.datum(points)
|
||||
.attr("d", d3.geo.path());
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var points = []
|
||||
if (scope.panel.display.bullseye.enabled) {
|
||||
if (scope.panel.display.geopoints.enabled) {
|
||||
points = scope.points;
|
||||
}
|
||||
|
||||
var circle = d3.geo.circle();
|
||||
var degrees = 180 / Math.PI
|
||||
|
||||
var geopoints = scope.g.selectAll("geopoints")
|
||||
var geopoints = scope.g.selectAll(".geopoint")
|
||||
.data(points);
|
||||
|
||||
geopoints.enter().append("path")
|
||||
|
@ -122,6 +122,7 @@ angular.module('kibana.map2', [])
|
||||
|
||||
_.each(results.facets.map.terms, function (v) {
|
||||
|
||||
|
||||
var metric = 'count';
|
||||
|
||||
//If it is a Term facet, use count, otherwise use Total
|
||||
@ -190,7 +191,7 @@ angular.module('kibana.map2', [])
|
||||
|
||||
|
||||
//elem.html('')
|
||||
|
||||
scope.initializing = false;
|
||||
scope.worldData = null;
|
||||
scope.worldNames = null;
|
||||
|
||||
@ -228,39 +229,38 @@ angular.module('kibana.map2', [])
|
||||
|
||||
|
||||
|
||||
scope.init_or_render = function() {
|
||||
if (typeof scope.svg === 'undefined') {
|
||||
console.log("init");
|
||||
|
||||
//prevent duplicate initialization steps, if render is called again
|
||||
//before the svg is setup
|
||||
if (!scope.initializing) {
|
||||
init_panel();
|
||||
}
|
||||
} else {
|
||||
console.log("render");
|
||||
render_panel();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Receive render events
|
||||
scope.$on('render', function () {
|
||||
console.log("$on render");
|
||||
|
||||
if (typeof scope.svg === 'undefined') {
|
||||
console.log("init");
|
||||
init_panel();
|
||||
} else {
|
||||
console.log("render");
|
||||
render_panel();
|
||||
}
|
||||
scope.init_or_render();
|
||||
});
|
||||
|
||||
// Or if the window is resized
|
||||
angular.element(window).bind('resize', function () {
|
||||
console.log("resize render");
|
||||
|
||||
if (typeof scope.svg === 'undefined') {
|
||||
console.log("init");
|
||||
init_panel();
|
||||
} else {
|
||||
console.log("render");
|
||||
render_panel();
|
||||
}
|
||||
|
||||
|
||||
scope.init_or_render();
|
||||
});
|
||||
|
||||
|
||||
function init_panel() {
|
||||
|
||||
scope.initializing = true;
|
||||
// Using LABjs, wait until all scripts are loaded before rendering panel
|
||||
var scripts = $LAB.script("panels/map2/lib/d3.v3.min.js?rand="+Math.floor(Math.random()*10000))
|
||||
.script("panels/map2/lib/topojson.v1.min.js?rand="+Math.floor(Math.random()*10000))
|
||||
@ -334,16 +334,11 @@ angular.module('kibana.map2', [])
|
||||
|
||||
scope.g = scope.svg.append("g");
|
||||
|
||||
//Overlay is used so that the entire map is draggable, not just the locations
|
||||
//where countries are
|
||||
scope.svg.append("rect")
|
||||
.attr("class", "overlay")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||
|
||||
|
||||
|
||||
console.log("finished initing");
|
||||
scope.initializing = false;
|
||||
render_panel();
|
||||
});
|
||||
|
||||
@ -399,8 +394,8 @@ angular.module('kibana.map2', [])
|
||||
var decoded = geohash.decode(v);
|
||||
return [decoded.longitude, decoded.latitude];
|
||||
});
|
||||
scope.projectedPoints = _.map(scope.points, function (k, v) {
|
||||
return scope.projection(v);
|
||||
scope.projectedPoints = _.map(scope.points, function (coords) {
|
||||
return scope.projection(coords);
|
||||
});
|
||||
|
||||
|
||||
@ -410,14 +405,29 @@ angular.module('kibana.map2', [])
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//set up listener for ctrl key
|
||||
//scope.svg
|
||||
|
||||
//Overlay is used so that the entire map is draggable, not just the locations
|
||||
//where countries are
|
||||
|
||||
scope.svg.select(".overlay").remove();
|
||||
|
||||
scope.svg.append("rect")
|
||||
.attr("class", "overlay")
|
||||
.attr("width", width)
|
||||
.attr("height", height)
|
||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
||||
|
||||
//Draw the countries, if this is a choropleth, draw with fancy colors
|
||||
scope.g.selectAll("countries")
|
||||
.data(scope.countries)
|
||||
.enter().append("path")
|
||||
var countryPath = scope.g.selectAll(".land")
|
||||
.data(scope.countries);
|
||||
|
||||
|
||||
|
||||
countryPath.enter().append("path")
|
||||
.attr("class", function(d) {
|
||||
if (scope.panel.display.choropleth.enabled) {
|
||||
return 'land ' + scope.quantize(scope.data[d.short]);
|
||||
@ -427,11 +437,16 @@ angular.module('kibana.map2', [])
|
||||
})
|
||||
.attr("d", path);
|
||||
|
||||
countryPath.exit().remove();
|
||||
|
||||
|
||||
/*
|
||||
//draw boundaries
|
||||
scope.g.selectAll("land").append("path")
|
||||
.datum(topojson.mesh(scope.worldData, scope.worldData.objects.land, function(a, b) { return a !== b; }))
|
||||
.attr("class", "land boundary")
|
||||
.attr("d", path);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@ -465,20 +480,13 @@ angular.module('kibana.map2', [])
|
||||
*/
|
||||
|
||||
//Hexagonal Binning
|
||||
if (scope.panel.display.binning.enabled) {
|
||||
//@todo fix this
|
||||
var dimensions = [width, height];
|
||||
displayBinning(scope, dimensions, scope.projection, path);
|
||||
}
|
||||
|
||||
//Raw geopoints
|
||||
//if (scope.panel.display.geopoints.enabled) {
|
||||
displayGeopoints(scope, path);
|
||||
//}
|
||||
//@todo fix this
|
||||
var dimensions = [width, height];
|
||||
displayBinning(scope, dimensions, scope.projection, path);
|
||||
displayGeopoints(scope, path);
|
||||
displayBullseye(scope, scope.projection, path);
|
||||
|
||||
//if (scope.panel.display.bullseye.enabled) {
|
||||
displayBullseye(scope, scope.projection, path);
|
||||
//}
|
||||
|
||||
//d3.select(elem[0]).select(".loading").remove();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user