最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - Change color on a map D3 - Stack Overflow

matteradmin9PV0评论

I'm a beginner in Js and I'm trying to change the color of a specific country (function colorCountry) by its Id using D3.js. However, doesn't matter what color I choose. The result will always show the map highlighted in orange. What could I do to solve this?

My code follows below.

Thanks.

The json file can be downloaded here - .json

<!DOCTYPE html>
<meta charset="utf-8">
<style>

    body {
        background: #fcfcfa;
    }

    .stroke {
        fill: none;
        stroke: #000;
        stroke-width: 3px;
    }

    .fill {
        fill: #fff;
    }

    .graticule {
        fill: none;
        stroke: #777;
        stroke-width: .5px;
        stroke-opacity: .5;
    }

    .land {
        fill: #888;
    }

    .boundary {
        fill: none;
        stroke: #fff;
        stroke-width: .5px;
    }

</style>
<body>
<script src="//d3js/d3.v3.min.js"></script>
<script src="//d3js/topojson.v1.min.js"></script>
<script>

    var countryCode = 840;   //36: AUSTRALIA * 643: RUSSIA * 76: BRAZIL * 840: USA

    var width = 960,
            height = 580;

    var color = d3.scale.category10();

    var projection = d3.geo.mercator()
            .scale(170)
            .translate([width / 2, height / 2])
            .precision(.1);

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

    var graticule = d3.geo.graticule();

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

    svg.append("defs").append("path")
            .datum({type: "Sphere"})
            .attr("id", "sphere")
            .attr("d", path);

    svg.append("use")
            .attr("class", "stroke")
            .attr("xlink:href", "#sphere");

    svg.append("use")
            .attr("class", "fill")
            .attr("xlink:href", "#sphere");

    svg.append("path")
            .datum(graticule)
            .attr("class", "graticule")
            .attr("d", path);



    d3.json("world-110m2.json", function(error, world) {
        if (error) throw error;

        var countries = topojson.feature(world, world.objects.countries).features,
                neighbors = topojson.neighbors(world.objects.countries.geometries);
        svg.selectAll(".country")
                .data(countries)
                .enter().insert("path", ".graticule")
                .attr("class", "country")
                .attr("d", path)
                .style("fill", function(d) { if (d.id == countryCode) { return color(colorCountry(d, d.id));} });

        svg.insert("path", ".graticule")
                .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
                .attr("class", "boundary")
                .attr("d", path);

        console.log("value : " + countries[99].id);
        console.log("value : " + countries[12].id);
        console.log("value : " + countries[108].color);

    });

    /*HERE*/
    function colorCountry(country, countryId) {
        if (country.id == countryId) {
            return color(country.color = "#FF0000");
        }
    }

    d3.select(self.frameElement).style("height", height + "px");

</script>

I'm a beginner in Js and I'm trying to change the color of a specific country (function colorCountry) by its Id using D3.js. However, doesn't matter what color I choose. The result will always show the map highlighted in orange. What could I do to solve this?

My code follows below.

Thanks.

The json file can be downloaded here - https://gist.githubusercontent./d3noob/5193723/raw/6e1434b2c2de24aedde9bcfe35f6a267bd2c04f5/world-110m2.json

<!DOCTYPE html>
<meta charset="utf-8">
<style>

    body {
        background: #fcfcfa;
    }

    .stroke {
        fill: none;
        stroke: #000;
        stroke-width: 3px;
    }

    .fill {
        fill: #fff;
    }

    .graticule {
        fill: none;
        stroke: #777;
        stroke-width: .5px;
        stroke-opacity: .5;
    }

    .land {
        fill: #888;
    }

    .boundary {
        fill: none;
        stroke: #fff;
        stroke-width: .5px;
    }

</style>
<body>
<script src="//d3js/d3.v3.min.js"></script>
<script src="//d3js/topojson.v1.min.js"></script>
<script>

    var countryCode = 840;   //36: AUSTRALIA * 643: RUSSIA * 76: BRAZIL * 840: USA

    var width = 960,
            height = 580;

    var color = d3.scale.category10();

    var projection = d3.geo.mercator()
            .scale(170)
            .translate([width / 2, height / 2])
            .precision(.1);

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

    var graticule = d3.geo.graticule();

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

    svg.append("defs").append("path")
            .datum({type: "Sphere"})
            .attr("id", "sphere")
            .attr("d", path);

    svg.append("use")
            .attr("class", "stroke")
            .attr("xlink:href", "#sphere");

    svg.append("use")
            .attr("class", "fill")
            .attr("xlink:href", "#sphere");

    svg.append("path")
            .datum(graticule)
            .attr("class", "graticule")
            .attr("d", path);



    d3.json("world-110m2.json", function(error, world) {
        if (error) throw error;

        var countries = topojson.feature(world, world.objects.countries).features,
                neighbors = topojson.neighbors(world.objects.countries.geometries);
        svg.selectAll(".country")
                .data(countries)
                .enter().insert("path", ".graticule")
                .attr("class", "country")
                .attr("d", path)
                .style("fill", function(d) { if (d.id == countryCode) { return color(colorCountry(d, d.id));} });

        svg.insert("path", ".graticule")
                .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
                .attr("class", "boundary")
                .attr("d", path);

        console.log("value : " + countries[99].id);
        console.log("value : " + countries[12].id);
        console.log("value : " + countries[108].color);

    });

    /*HERE*/
    function colorCountry(country, countryId) {
        if (country.id == countryId) {
            return color(country.color = "#FF0000");
        }
    }

    d3.select(self.frameElement).style("height", height + "px");

</script>
Share Improve this question asked Apr 17, 2016 at 4:38 JasJas 4158 silver badges23 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 2

Instead of doing this to country path:

.style("fill", function(d) {
    if (d.id == countryCode) { //there is no need for a condition.
        return color(colorCountry(d, d.id));//this is buggy, not clear what you trying to achieve. Color scale already return a color for the country id.
    }
}); 

Do this

.style("fill", function(d) {return color( d.id); });

Working code here.

I am not very familiar with d3, but there seem to be too many ifs in this line:

.style("fill", function(d) { if (d.id == countryCode) { return color(colorCountry(d, d.id));} });

would be simpler if you just do this:

.style("fill", colorCountry);

and change your colorCountry function to

function colorCountry(country) {
    if (country.id == countryCode) {
        return '#FF0000';
    } else {
        return color(country.id);
    }
}

or simply get rid of the colorCountry function all together and use this

.style("fill", function(d) {
    return (d.id == countryCode) ? '#FF0000' : color(d.id);
});

But why wouldn't you just update the JSON data?

Post a comment

comment list (0)

  1. No comments so far