2015-04-09 6 views
0

Я пытался проецировать карту тепла с данными, загруженными из csv, на ортогональную проекцию на D3. При вращении земли (т. Е. D3, ортогональная проекция) точки/окружности остаются статическими. Я пробовал много комбинаций, но не смог понять, чего не хватает.вращать точки из csv на ортогональном проекторе d3

В принципе, мне нужны маленькие круги, перемещающиеся по дорогам стран.

Вот полный код:

<script> 

    var width = 600, 
    height = 500, 
    sens = 0.25, 
    focused; 

    //Setting projection 

    var projection = d3.geo.orthographic() 
    .scale(245) 
    .rotate([0,0]) 
    .translate([width/2, height/2]) 
    .clipAngle(90); 

    var path = d3.geo.path() 
    .projection(projection); 

    //SVG container 

    var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

    // Define the gradient 
    var gradient = svg.append("svg:defs") 
    .append("svg:linearGradient") 
    .attr("id", "gradient") 
    .attr("x1", "0%") 
    .attr("y1", "0%") 
    .attr("x2", "100%") 
    .attr("y2", "100%") 
    .attr("spreadMethod", "pad"); 

    // Define the gradient colors 
    gradient.append("svg:stop") 
    .attr("offset", "0%") 
    .attr("stop-color", "#FFFF00") 
    .attr("stop-opacity", 0); 

    gradient.append("svg:stop") 
    .attr("offset", "100%") 
    .attr("stop-color", "#FF0000") 
    .attr("stop-opacity", 1); 



    //Adding water 
    svg.append("path") 
    .datum({type: "Sphere"}) 
    .attr("class", "water") 
    .attr("d", path) 


    var countryTooltip = d3.select("body").append("div").attr("class", "countryTooltip"), 
    countryList = d3.select("body").append("select").attr("name", "countries"); 

    queue() 
    .defer(d3.json, "world-110m.json") 
    .defer(d3.tsv, "world-110m-country-names.tsv") 
    .await(ready); 

    //Main function 

    function ready(error, world, countryData) { 

    var countryById = {}, 
    countries = topojson.feature(world, world.objects.countries).features; 


    //Adding countries to select 

    countryData.forEach(function(d) { 
     countryById[d.id] = d.name; 
     option = countryList.append("option"); 
     option.text(d.name); 
     option.property("value", d.id); 
    }); 

    //circles for heatmap are coming from the csv below 

    d3.csv("cities.csv", function(error, data) { 
     svg.selectAll("circle") 
     .data(data) 
     .enter() 
     .append("a") 
      .attr("xlink:href", function(d) { 
      return "https://www.google.com/search?q="+d.city;} 
     ) 
     .append("circle") 
     .attr("cx", function(d) { 
       return projection([d.lon, d.lat])[0]; 
     }) 
     .attr("cy", function(d) { 
       return projection([d.lon, d.lat])[1]; 
     }) 
     .attr("r", 5.5) 
     .attr('fill', 'url(#gradient)'); 



    var world = svg.selectAll("path.circle") 
    .data(countries) //countries from the tsc file is used to populate the names 
    .enter().append("path") 
    .attr("class", "land") 
    .attr("d", path) 
    //.attr('fill', 'url(#gradient)') 

    //Drag event 

    .call(d3.behavior.drag() 
     .origin(function() { var r = projection.rotate(); return {x: r[0]/sens, y: -r[1]/sens}; }) 
     .on("drag", function() { 
     var rotate = projection.rotate(); 
     projection.rotate([d3.event.x * sens, -d3.event.y * sens, rotate[2]]); 
     svg.selectAll("path.land").attr("d", path); 
     svg.selectAll(".focused").classed("focused", focused = false); 
     })) 

    //Mouse events 

    .on("mouseover", function(d) { 
     countryTooltip.text(countryById[d.id]) 
     .style("left", (d3.event.pageX + 7) + "px") 
     .style("top", (d3.event.pageY - 15) + "px") 
     .style("display", "block") 
     .style("opacity", 1); 
    }) 
    .on("mouseout", function(d) { 
     countryTooltip.style("opacity", 0) 
     .style("display", "none"); 
    }) 
    .on("mousemove", function(d) { 
     countryTooltip.style("left", (d3.event.pageX + 7) + "px") 
     .style("top", (d3.event.pageY - 15) + "px"); 
    }); 
    });//closing d3.csv here 

    //Country focus on option select 

    d3.select("select").on("change", function() { 

     var rotate = projection.rotate(), 
     focusedCountry = country(countries, this), 
     p = d3.geo.centroid(focusedCountry); 

     svg.selectAll(".focused").classed("focused", focused = false); 

    //Globe rotating 

    (function transition() { 


     d3.transition() 
     .duration(2500) 
     .tween("rotate", function() { 
     var r = d3.interpolate(projection.rotate(), [-p[0], -p[1]]); 
     return function(t) { 
      projection.rotate(r(t)); 
      svg.selectAll("path").attr("d", path) 
      .classed("focused", function(d, i) { return d.id == focusedCountry.id ? focused = d : false; }); 
      //svg.selectAll("circle").attr("d", data) 
      //.classed("focused", function(d, i) { return d.id == focusedCountry.id ? focused = d : false; }); 
     }; 
     }) 

     })(); 
    }); 

    function country(cnt, sel) { 
     for(var i = 0, l = cnt.length; i < l; i++) { 
     if(cnt[i].id == sel.value) {return cnt[i];} 
     } 
    }; 

    }; 
    </script> 

Пожалуйста, помогите.

Спасибо заранее

ответ

0

Вот вариант, с помощью точечных геометрий:

.enter().append('path') 
    .attr('class', 'circle_el') 
    .attr('fill', function(d) {return d.fill; }) 
    .datum(function(d) { 
    return {type: 'Point', coordinates: [d.lon, d.lat], radius: some_radius}; 
    }) 
    .attr('d', path); 

Это здорово, потому что вы будете обновлять круги одновременно с пути перерисовывать. И кроме того, он будет учитывать проекцию как сферу, не отображая круги, которые должны находиться на невидимой стороне сферы. Я получил идею от этого post от Джейсона Дэвиса.

 Смежные вопросы

  • Нет связанных вопросов^_^