SetUp: Я создаю приложение-глобус, чтобы лучше визуально представлять данные регионов мира.Он построен на d3.js с использованием topojson для построения геометрии.
В настоящее время я реализую перетаскивание, которое было достигнуто ivyywang здесь .(не заблудитесь в математических функциях, если у вас нет статуса: "математический гуру")
Мой проект в настоящее время здесь .
Проблема: Я спроецировал глобус на орфографию и успешно реализовал функцию перетаскивания ... кроме.Я могу только щелкнуть и перетащить глобус, пока мой курсор находится за пределами страны.Как я могу проецировать SVG так, чтобы весь холст реагировал на мое событие перетаскивания?
Соответствующий код:
Сначала я получаю некоторые данные из запроса MySQL и сохраняю их.в стране статистика.И я запускаю его с помощью следующей функции, чтобы лучше индексировать ее.
var countryStatistics = (returned from mySQL query)
//this function build dataById[] setting data keyed to idTopo
function keyIdToData(d){
countryStatistics.forEach(function(d) {
dataById[d.idTopo] = d;
});
}
function visualize(statisticalData, mapType){
//pass arguments each function call to decide what data to viasually display, and what map type to use
var margin = {top: 100, left: 100, right: 100, bottom:100},
height = 800 - margin.top - margin.bottom,
width = 1200 - margin.left - margin.right;
//a simple color scale to correlate to data
var colorScale = d3.scaleLinear()
.domain([0, 100])
.range(["#646464", "#ffff00"])
//create svg
var svg = d3.select("#map")
.append("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
//here I attmpt to fill the svg with a different color. but it is unresponsive
.attr("fill", "blue")
Как вы можете видеть в конце этого блока кода, я вызываю .attr ("fill" ... для элемента SVG, ноне удается получить цвет для рендеринга. Возможно, это связано с тем, что мой курсор не отвечает в этом пространстве.
продолжение ...
//set projection type to 2D map or 3d globe dependinding on argument passed see function below
var projection = setMapType(mapType, width, height);
//a function to call on visualize() to set projection type for map style.
function setMapType(mapType, width, height) {
if(mapType === "mercator") {
let projection = d3.geoMercator()
.translate([ width / 2, height / 2 ])
.scale(180)
return projection;
}else if (mapType === "orthographic"){
let projection = d3.geoOrthographic()
.clipAngle(90)
.scale(240);
return projection;
}
//pass path lines to projections
var path = d3.geoPath()
.projection(projection);
//here I create and call the drag function only when globe projection is displayed elected
if(mapType == "orthographic"){
var drag = d3.drag()
.on("start", dragstarted)
.on("drag", dragged);
svg.call(drag);
}
//coordinate variables
var gpos0,
o0;
function dragstarted(){
gpos0 = projection.invert(d3.mouse(this));
o0 = projection.rotate();
}
function dragged(){
var gpos1 = projection.invert(d3.mouse(this));
o0 = projection.rotate();
var o1 = eulerAngles(gpos0, gpos1, o0);
projection.rotate(o1);
svg.selectAll("path").attr("d", path);
}
//load in the topojson file
d3.queue()
.defer(d3.json, "world110m.json")
.await(ready)
Вышеуказанные функции относятся к необходимым математическим функциям.вычислить орфографическое вращение. Вы можете увидеть их в блоке кода по ivyywang в первой ссылке, вверху.
function ready (error, data){
if (error) throw error;
//output data to see what is happening
console.log("topojson data: ")
console.log(data);
//I suspect there may be an issue with this code.
countries = topojson.feature(data, data.objects.countries)
//bind dataById data into countries topojson variable
.features.map(function(d) {
d.properties = dataById[d.id];
return d
});
console.log("countries:")
console.log(countries)
Я подозреваю, что переменная стран чуть выше может быть виновником, в основном потому, что я неЯ не совсем понимаю этот код. В этой переменной я связываю свои данные countryStatistics, обработанные keyIdToData()
, как «свойства» вложенного объекта с моими данными topojson. Я консоль регистрирую их, чтобы увидеть данные.
svg.selectAll(".country")
.data(countries)
.enter().append("path")
.attr("class", "country")
.attr("d", path)
//make fill gradient depend on data
.attr("fill", function(countries){
//if no data, country is grey
if(countries.properties == undefined){
return "rgb(100 100 100)";
}
//else pass data to colorScale()
return colorScale(countries.properties.literacy)
})
.on('mouseover', function(d) {
//on hover set class hovered which simply changes color with a transition time
d3.select(this).classed("hovered", true)
})
.on('mouseout', function(d) {
d3.select(this).classed("hovered", false)
})
}
};
наконец, у нас есть эта маленькая функция, которая
//this function build dataById[] setting data keyed to idTopo
function keyIdToData(d){
countryStatistics.forEach(function(d) {
dataById[d.idTopo] = d;
});
}
Возможности: Кажется, что мой рендеринг SVG исключает мою пустую (не страновую) область. Может быть проблема смоя конструкция SVG?Или, возможно, я вмешиваюсь в конструкцию SVG, когда я изменяю данные и добавляю свой dataById в мой топойсон?
Спасибо за то, что сделали эту далекую клавиатуру ниндзя.Есть идеи?