通过光标拖动使 d3.js 数据图旋转
make d3.js datamap rotate by dragging with cursor
我做了this map using datamaps by @markmarkoh
我喜欢它的结果,但我希望当你用光标拖动它时我可以让它旋转,这样你就可以看到所有的大陆。喜欢示例 here and here.
这是我的代码片段:
//basic map config with custom fills, mercator projection
var series = [
["USA",36.2],["GBR",7.4],["CAN",6.2],["DEU",5.7],["FRA", 4.1],["ESP",4.1],["ITA",3.3],["MEX",3.0],["AUS",2.5],["NLD",2.4],
["IND",2.1],["BRA",2.0],["GRC",1.4],["AUT",1.2],["ROU",1.2],["SRB",1.0],["COL",0.8],["POL",0.8],["ZAF",0.7],["SWE",0.7],
["DNK",0.6],["VEN",0.6],["JPN",0.6],["KOR",0.6],["BEL",0.5],["RUS",0.5],["PRT",0.5]
];
var dataset = {};
// We need to colorize every country based on "percent"
// colors should be uniq for every value.
// For this purpose we create palette(using min/max series-value)
var onlyValues = series.map(function(obj){ return obj[1]; });
var minValue = Math.min.apply(null, onlyValues),
maxValue = Math.max.apply(null, onlyValues);
// create color palette function
// color can be whatever you wish
var paletteScale = d3.scale.linear()
.domain([minValue,maxValue])
.range(["rgb(0,0,0)","rgb(219,219,219)"]); // color
// fill dataset in appropriate format
series.forEach(function(item){ //
// item example value ["USA", 36.2]
var iso = item[0],
value = item[1];
dataset[iso] = { percent: value, fillColor: paletteScale(value) };
});
var map = new Datamap({
scope: 'world',
element: document.getElementById('world'),
projection: 'orthographic',
projectionConfig: {
rotation: [90,-30]
},
fills: {defaultFill: 'rgba(30,30,30,0.1)'},
data: dataset,
geographyConfig: {
borderColor: 'rgba(222,222,222,0.2)',
highlightBorderWidth: 1,
// don't change color on mouse hover
highlightFillColor: function(geo) {
return geo['fillColor'] || 'rgba(30,30,30,0.5)';
},
// only change border
highlightBorderColor: 'rgba(222,222,222,0.5)',
// show desired information in tooltip
popupTemplate: function(geo, data) {
// don't show tooltip if country don't present in dataset
if (!data) { return ; }
// tooltip content
return ['',
'<div style="opacity:0.7;" class="hoverinfo">% of visitors in ' + geo.properties.name,
': ' + data.percent,
''].join('');
}
}
});
//draw a legend for this map
map.legend();
map.graticule();
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script>
<script src="http://unilogue.github.io/js/map/datamaps.world.min.js"></script>
<div id="world" style="fill-opacity:0.7; height: 600px; width: 500px; margin-top:-100px;"></div>
编辑:显然 done 回调允许您使用事件,我创建了这个 zoom/pan 函数作为测试,但我如何使用它以 d3.behavior.drag 和欧拉角旋转我的地图?
var map = new Datamap({
done: function(datamap) {
datamap.svg.call(d3.behavior.zoom().on("zoom", redraw));
function redraw() {
datamap.svg.selectAll("g").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
},
编辑 2:这看起来可行!摘自 here.
我试过copying它进入一个完成的回调但是没有任何反应,有什么想法吗?
var dragBehaviour = d3.behavior.drag()
.on('drag', function(){
var dx = d3.event.dx;
var dy = d3.event.dy;
var rotation = projection.rotate();
var radius = projection.scale();
var scale = d3.scale.linear()
.domain([-1 * radius, radius])
.range([-90, 90]);
var degX = scale(dx);
var degY = scale(dy);
rotation[0] += degX;
rotation[1] -= degY;
if (rotation[1] > 90) rotation[1] = 90;
if (rotation[1] < -90) rotation[1] = -90;
if (rotation[0] >= 180) rotation[0] -= 360;
projection.rotate(rotation);
redraw();
})
var livemap;
scope.rotation = [97, -30];
function redraw() {
d3.select("#map-wrapper").html('');
init();
}// redraw
function init() {
livemap = new Datamap({...})
var drag = d3.behavior.drag().on('drag', function() {
var dx = d3.event.dx;
var dy = d3.event.dy;
var rotation = livemap.projection.rotate();
var radius = livemap.projection.scale();
var scale = d3.scale.linear().domain([-1 * radius, radius]).range([-90, 90]);
var degX = scale(dx);
var degY = scale(dy);
rotation[0] += degX;
rotation[1] -= degY;
if (rotation[1] > 90) rotation[1] = 90;
if (rotation[1] < -90) rotation[1] = -90;
if (rotation[0] >= 180) rotation[0] -= 360;
scope.rotation = rotation;
redraw();
})
d3.select("#map-wrapper").select("svg").call(drag);
}// init
我做了this map using datamaps by @markmarkoh
我喜欢它的结果,但我希望当你用光标拖动它时我可以让它旋转,这样你就可以看到所有的大陆。喜欢示例 here and here.
这是我的代码片段:
//basic map config with custom fills, mercator projection
var series = [
["USA",36.2],["GBR",7.4],["CAN",6.2],["DEU",5.7],["FRA", 4.1],["ESP",4.1],["ITA",3.3],["MEX",3.0],["AUS",2.5],["NLD",2.4],
["IND",2.1],["BRA",2.0],["GRC",1.4],["AUT",1.2],["ROU",1.2],["SRB",1.0],["COL",0.8],["POL",0.8],["ZAF",0.7],["SWE",0.7],
["DNK",0.6],["VEN",0.6],["JPN",0.6],["KOR",0.6],["BEL",0.5],["RUS",0.5],["PRT",0.5]
];
var dataset = {};
// We need to colorize every country based on "percent"
// colors should be uniq for every value.
// For this purpose we create palette(using min/max series-value)
var onlyValues = series.map(function(obj){ return obj[1]; });
var minValue = Math.min.apply(null, onlyValues),
maxValue = Math.max.apply(null, onlyValues);
// create color palette function
// color can be whatever you wish
var paletteScale = d3.scale.linear()
.domain([minValue,maxValue])
.range(["rgb(0,0,0)","rgb(219,219,219)"]); // color
// fill dataset in appropriate format
series.forEach(function(item){ //
// item example value ["USA", 36.2]
var iso = item[0],
value = item[1];
dataset[iso] = { percent: value, fillColor: paletteScale(value) };
});
var map = new Datamap({
scope: 'world',
element: document.getElementById('world'),
projection: 'orthographic',
projectionConfig: {
rotation: [90,-30]
},
fills: {defaultFill: 'rgba(30,30,30,0.1)'},
data: dataset,
geographyConfig: {
borderColor: 'rgba(222,222,222,0.2)',
highlightBorderWidth: 1,
// don't change color on mouse hover
highlightFillColor: function(geo) {
return geo['fillColor'] || 'rgba(30,30,30,0.5)';
},
// only change border
highlightBorderColor: 'rgba(222,222,222,0.5)',
// show desired information in tooltip
popupTemplate: function(geo, data) {
// don't show tooltip if country don't present in dataset
if (!data) { return ; }
// tooltip content
return ['',
'<div style="opacity:0.7;" class="hoverinfo">% of visitors in ' + geo.properties.name,
': ' + data.percent,
''].join('');
}
}
});
//draw a legend for this map
map.legend();
map.graticule();
<script src="http://cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.9/topojson.min.js"></script>
<script src="http://unilogue.github.io/js/map/datamaps.world.min.js"></script>
<div id="world" style="fill-opacity:0.7; height: 600px; width: 500px; margin-top:-100px;"></div>
编辑:显然 done 回调允许您使用事件,我创建了这个 zoom/pan 函数作为测试,但我如何使用它以 d3.behavior.drag 和欧拉角旋转我的地图?
var map = new Datamap({
done: function(datamap) {
datamap.svg.call(d3.behavior.zoom().on("zoom", redraw));
function redraw() {
datamap.svg.selectAll("g").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
},
编辑 2:这看起来可行!摘自 here.
我试过copying它进入一个完成的回调但是没有任何反应,有什么想法吗?
var dragBehaviour = d3.behavior.drag()
.on('drag', function(){
var dx = d3.event.dx;
var dy = d3.event.dy;
var rotation = projection.rotate();
var radius = projection.scale();
var scale = d3.scale.linear()
.domain([-1 * radius, radius])
.range([-90, 90]);
var degX = scale(dx);
var degY = scale(dy);
rotation[0] += degX;
rotation[1] -= degY;
if (rotation[1] > 90) rotation[1] = 90;
if (rotation[1] < -90) rotation[1] = -90;
if (rotation[0] >= 180) rotation[0] -= 360;
projection.rotate(rotation);
redraw();
})
var livemap;
scope.rotation = [97, -30];
function redraw() {
d3.select("#map-wrapper").html('');
init();
}// redraw
function init() {
livemap = new Datamap({...})
var drag = d3.behavior.drag().on('drag', function() {
var dx = d3.event.dx;
var dy = d3.event.dy;
var rotation = livemap.projection.rotate();
var radius = livemap.projection.scale();
var scale = d3.scale.linear().domain([-1 * radius, radius]).range([-90, 90]);
var degX = scale(dx);
var degY = scale(dy);
rotation[0] += degX;
rotation[1] -= degY;
if (rotation[1] > 90) rotation[1] = 90;
if (rotation[1] < -90) rotation[1] = -90;
if (rotation[0] >= 180) rotation[0] -= 360;
scope.rotation = rotation;
redraw();
})
d3.select("#map-wrapper").select("svg").call(drag);
}// init