Как правильно установить значения оси X на график D3 - PullRequest
0 голосов
/ 05 ноября 2018

Я реализовал линейную диаграмму, используя D3, и она должна показывать количество сотрудников в каждой стране за 5 лет. Я прикрепил JSFiddle ниже. На оси X диаграммы мне нужно иметь Годы в качестве метки. (Год исходит из набора данных) Но проблема в том, что у оси X есть некоторые дополнительные значения в качестве меток, и я не мог понять, почему это происходит. Я также довольно новичок в использовании D3. Может кто-нибудь сказать мне, что здесь не так?

Скрипка: https://jsfiddle.net/yasirunilan/e01L3uvt/1/

var data = [
        {
            name: "USA",
            values: [
                {date: "2000", price: "100"},
                {date: "2001", price: "110"},
                {date: "2002", price: "145"},
                {date: "2003", price: "241"},
                {date: "2004", price: "101"}
            ]
        },
        {
            name: "UK",
            values: [
                {date: "2000", price: "200"},
                {date: "2001", price: "120"},
                {date: "2002", price: "33"},
                {date: "2003", price: "21"},
                {date: "2004", price: "51"}
            ]
        },
        {
            name: "UAE",
            values: [
                {date: "2000", price: "50"},
                {date: "2001", price: "10"},
                {date: "2002", price: "5"},
                {date: "2003", price: "71"},
                {date: "2004", price: "20"}
            ]
        },
        {
            name: "Australia",
            values: [
                {date: "2000", price: "20"},
                {date: "2001", price: "40"},
                {date: "2002", price: "25"},
                {date: "2003", price: "75"},
                {date: "2004", price: "19"}
            ]
        },
        {
            name: "India",
            values: [
                {date: "2000", price: "200"},
                {date: "2001", price: "150"},
                {date: "2002", price: "170"},
                {date: "2003", price: "150"},
                {date: "2004", price: "130"}
            ]
        },
        {
            name: "Orange Department F",
            values: [
                {date: "2000", price: "75"},
                {date: "2001", price: "100"},
                {date: "2002", price: "120"},
                {date: "2003", price: "140"},
                {date: "2004", price: "190"}
            ]
        }
    ];

    const margin = 80;
    const width = 1000 - 2 * margin;
    const height = 550 - 2 * margin;

    var duration = 250;

    var lineOpacity = "0.25";
    var lineOpacityHover = "0.85";
    var otherLinesOpacityHover = "0.1";
    var lineStroke = "1.5px";
    var lineStrokeHover = "2.5px";

    var circleOpacity = '0.85';
    var circleOpacityOnLineHover = "0.25"
    var circleRadius = 3;
    var circleRadiusHover = 6;


    /* Format Data */
    var parseDate = d3.time.format("%Y");
    data.forEach(function(d) {
        d.values.forEach(function(d) {
            d.date = parseDate.parse(d.date);
            d.price = +d.price;
        });
    });

    /* Scale */
    var xScale = d3.time.scale()
        .domain(d3.extent(data[0].values, d => d.date))
        .range([0, width-margin]);
    var yScale = d3.scale.linear()
        .domain([0, d3.max(data[0].values, d => d.price)])
        .range([height-margin, 0]);

    // var color = d3.scale.ordinal(d3.schemeCategory10);
    var color = d3.scale.category10();

    /* Add SVG */
    var svg = d3.select("svg")
        .attr("width", (width+margin)+"px")
        .attr("height", (height+margin)+"px")
        .append('g')
        .attr("transform", `translate(${margin}, ${margin})`);


    /* Add line into SVG */
    var line = d3.svg.line()
        .x(d => xScale(d.date))
        .y(d => yScale(d.price));

    let lines = svg.append('g')
        .attr('class', 'lines');

    lines.selectAll('.line-group')
        .data(data).enter()
        .append('g')
        .attr('class', 'line-group')
        .on("mouseover", function(d, i) {
            svg.append("text")
                .attr("class", "title-text")
                .style("fill", color(i))
                .text(d.name)
                .attr("text-anchor", "middle")
                .attr("x", (width-margin)/2)
                .attr("y", 5);
        })
        .on("mouseout", function(d) {
            svg.select(".title-text").remove();
        })
        .append('path')
        .attr('class', 'line')
        .attr('d', d => line(d.values))
        .style('stroke', (d, i) => color(i))
        .style('opacity', lineOpacity)
        .on("mouseover", function(d) {
            d3.selectAll('.line')
                .style('opacity', otherLinesOpacityHover);
            d3.selectAll('.circle')
                .style('opacity', circleOpacityOnLineHover);
            d3.select(this)
                .style('opacity', lineOpacityHover)
                .style("stroke-width", lineStrokeHover)
                .style("cursor", "pointer");
        })
        .on("mouseout", function(d) {
            d3.selectAll(".line")
                .style('opacity', lineOpacity);
            d3.selectAll('.circle')
                .style('opacity', circleOpacity);
            d3.select(this)
                .style("stroke-width", lineStroke)
                .style("cursor", "none");
        });


    /* Add circles in the line */
    lines.selectAll("circle-group")
        .data(data).enter()
        .append("g")
        .style("fill", (d, i) => color(i))
        .selectAll("circle")
        .data(d => d.values).enter()
        .append("g")
        .attr("class", "circle")
        .on("mouseover", function(d) {
            d3.select(this)
                .style("cursor", "pointer")
                .append("text")
                .attr("class", "text")
                .text(`${d.price}`)
                .attr("x", d => xScale(d.date) + 5)
                .attr("y", d => yScale(d.price) - 10);
        })
        .on("mouseout", function(d) {
            d3.select(this)
                .style("cursor", "none")
                .transition()
                .duration(duration)
                .selectAll(".text").remove();
        })
        .append("circle")
        .attr("cx", d => xScale(d.date))
        .attr("cy", d => yScale(d.price))
        .attr("r", circleRadius)
        .style('opacity', circleOpacity)
        .on("mouseover", function(d) {
            d3.select(this)
                .transition()
                .duration(duration)
                .attr("r", circleRadiusHover);
        })
        .on("mouseout", function(d) {
            d3.select(this)
                .transition()
                .duration(duration)
                .attr("r", circleRadius);
        });

    /* Add Axis into SVG */
    var xAxis = d3.svg.axis().scale(xScale)
        .orient("bottom").tickSize(1);

    var yAxis = d3.svg.axis().scale(yScale)
        .orient("left").tickSize(1);
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", `translate(0, ${height-margin})`)
        .call(xAxis);

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append('text')
        .attr("y", 15)
        .attr("transform", "rotate(-90)")
        .attr("fill", "#000")
        .attr('text-anchor', 'middle')
        .text("No. of Employees");

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Для этого я нашел решение, изменив форматирование тиков. Теперь это работает как задумано. Следующий код показывает пример кода с правильным поведением.

Скрипка: https://jsfiddle.net/yasirunilan/tz57wc29/13/

var data = [
        {
            name: "USA",
            values: [
                {date: "2000", price: "100"},
                {date: "2001", price: "110"},
                {date: "2002", price: "145"},
                {date: "2003", price: "241"},
                {date: "2004", price: "101"}
            ]
        },
        {
            name: "UK",
            values: [
                {date: "2000", price: "200"},
                {date: "2001", price: "120"},
                {date: "2002", price: "33"},
                {date: "2003", price: "21"},
                {date: "2004", price: "51"}
            ]
        },
        {
            name: "India",
            values: [
                {date: "2000", price: "50"},
                {date: "2001", price: "10"},
                {date: "2002", price: "5"},
                {date: "2003", price: "71"},
                {date: "2004", price: "20"}
            ]
        },
        {
            name: "Australia",
            values: [
                {date: "2000", price: "20"},
                {date: "2001", price: "40"},
                {date: "2002", price: "25"},
                {date: "2003", price: "75"},
                {date: "2004", price: "19"}
            ]
        },
        {
            name: "UAE",
            values: [
                {date: "2000", price: "200"},
                {date: "2001", price: "150"},
                {date: "2002", price: "170"},
                {date: "2003", price: "150"},
                {date: "2004", price: "130"}
            ]
        },
        {
            name: "China",
            values: [
                {date: "2000", price: "75"},
                {date: "2001", price: "100"},
                {date: "2002", price: "120"},
                {date: "2003", price: "140"},
                {date: "2004", price: "190"}
            ]
        }
    ];

    const margin = 80;
    const width = 1000 - 2 * margin;
    const height = 550 - 2 * margin;

    var duration = 250;

    var lineOpacity = "0.25";
    var lineOpacityHover = "0.85";
    var otherLinesOpacityHover = "0.1";
    var lineStroke = "1.5px";
    var lineStrokeHover = "2.5px";

    var circleOpacity = '0.85';
    var circleOpacityOnLineHover = "0.25"
    var circleRadius = 3;
    var circleRadiusHover = 6;


    /* Format Data */
    var parseDate = d3.time.format("%Y");
    data.forEach(function(d) {
        d.values.forEach(function(d) {
            d.date = parseDate.parse(d.date);
            d.price = +d.price;
        });
    });

    /* Scale */
    var xScale = d3.time.scale()
        .domain(d3.extent(data[0].values, d => d.date))
        .range([0, width-margin]);
    var yScale = d3.scale.linear()
        .domain([0, d3.max(data[0].values, d => d.price)])
        .range([height-margin, 0]);

    // var color = d3.scale.ordinal(d3.schemeCategory10);
    var color = d3.scale.category10();

    /* Add SVG */
    var svg = d3.select("svg")
        .attr("width", (width+margin)+"px")
        .attr("height", (height+margin)+"px")
        .append('g')
        .attr("transform", `translate(${margin}, ${margin})`);


    /* Add line into SVG */
    var line = d3.svg.line()
        .x(d => xScale(d.date))
        .y(d => yScale(d.price));

    let lines = svg.append('g')
        .attr('class', 'lines');

    lines.selectAll('.line-group')
        .data(data).enter()
        .append('g')
        .attr('class', 'line-group')
        .on("mouseover", function(d, i) {
            svg.append("text")
                .attr("class", "title-text")
                .style("fill", color(i))
                .text(d.name)
                .attr("text-anchor", "middle")
                .attr("x", (width-margin)/2)
                .attr("y", 5);
        })
        .on("mouseout", function(d) {
            svg.select(".title-text").remove();
        })
        .append('path')
        .attr('class', 'line')
        .attr('d', d => line(d.values))
        .style('stroke', (d, i) => color(i))
        .style('opacity', lineOpacity)
        .on("mouseover", function(d) {
            d3.selectAll('.line')
                .style('opacity', otherLinesOpacityHover);
            d3.selectAll('.circle')
                .style('opacity', circleOpacityOnLineHover);
            d3.select(this)
                .style('opacity', lineOpacityHover)
                .style("stroke-width", lineStrokeHover)
                .style("cursor", "pointer");
        })
        .on("mouseout", function(d) {
            d3.selectAll(".line")
                .style('opacity', lineOpacity);
            d3.selectAll('.circle')
                .style('opacity', circleOpacity);
            d3.select(this)
                .style("stroke-width", lineStroke)
                .style("cursor", "none");
        });


    /* Add circles in the line */
    lines.selectAll("circle-group")
        .data(data).enter()
        .append("g")
        .style("fill", (d, i) => color(i))
        .selectAll("circle")
        .data(d => d.values).enter()
        .append("g")
        .attr("class", "circle")
        .on("mouseover", function(d) {
            d3.select(this)
                .style("cursor", "pointer")
                .append("text")
                .attr("class", "text")
                .text(`${d.price}`)
                .attr("x", d => xScale(d.date) + 5)
                .attr("y", d => yScale(d.price) - 10);
        })
        .on("mouseout", function(d) {
            d3.select(this)
                .style("cursor", "none")
                .transition()
                .duration(duration)
                .selectAll(".text").remove();
        })
        .append("circle")
        .attr("cx", d => xScale(d.date))
        .attr("cy", d => yScale(d.price))
        .attr("r", circleRadius)
        .style('opacity', circleOpacity)
        .on("mouseover", function(d) {
            d3.select(this)
                .transition()
                .duration(duration)
                .attr("r", circleRadiusHover);
        })
        .on("mouseout", function(d) {
            d3.select(this)
                .transition()
                .duration(duration)
                .attr("r", circleRadius);
        });



    var xAxis = d3.svg.axis().scale(xScale)
        .orient("bottom").tickFormat(d3.time.format("%Y")).tickSize(1);

    var yAxis = d3.svg.axis().scale(yScale)
        .orient("left").tickSize(1);

    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", `translate(0, ${height-margin})`)
        .call(xAxis.ticks(d3.time.year));

    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
        .append('text')
        .attr("y", 15)
        .attr("transform", "rotate(-90)")
        .attr("fill", "#000")
        .attr('text-anchor', 'middle')
        .text("No. of Employees");
0 голосов
/ 05 ноября 2018

Здесь я изменил tickFormat xAxis на

var xAxis = d3.svg.axis().scale(xScale)
            .orient("bottom").ticks(5).tickFormat(function(d) {
              if (d % 1 == 0) {
                return d3.format('.f')(d)
              } else {
                return ""
              }
            }).tickSize(1);

Ниже приведена полная рабочая демонстрация исходного кода, и она сработала. Надеюсь, это поможет вам.

var data = [
            {
                name: "USA",
                values: [
                    {date: "2000", price: "100"},
                    {date: "2001", price: "110"},
                    {date: "2002", price: "145"},
                    {date: "2003", price: "241"},
                    {date: "2004", price: "101"}
                ]
            },
            {
                name: "UK",
                values: [
                    {date: "2000", price: "200"},
                    {date: "2001", price: "120"},
                    {date: "2002", price: "33"},
                    {date: "2003", price: "21"},
                    {date: "2004", price: "51"}
                ]
            },
            {
                name: "UAE",
                values: [
                    {date: "2000", price: "50"},
                    {date: "2001", price: "10"},
                    {date: "2002", price: "5"},
                    {date: "2003", price: "71"},
                    {date: "2004", price: "20"}
                ]
            },
            {
                name: "Australia",
                values: [
                    {date: "2000", price: "20"},
                    {date: "2001", price: "40"},
                    {date: "2002", price: "25"},
                    {date: "2003", price: "75"},
                    {date: "2004", price: "19"}
                ]
            },
            {
                name: "India",
                values: [
                    {date: "2000", price: "200"},
                    {date: "2001", price: "150"},
                    {date: "2002", price: "170"},
                    {date: "2003", price: "150"},
                    {date: "2004", price: "130"}
                ]
            },
            {
                name: "Orange Department F",
                values: [
                    {date: "2000", price: "75"},
                    {date: "2001", price: "100"},
                    {date: "2002", price: "120"},
                    {date: "2003", price: "140"},
                    {date: "2004", price: "190"}
                ]
            }
        ];

        const margin = 80;
        const width = 1000 - 2 * margin;
        const height = 550 - 2 * margin;

        var duration = 250;

        var lineOpacity = "0.25";
        var lineOpacityHover = "0.85";
        var otherLinesOpacityHover = "0.1";
        var lineStroke = "1.5px";
        var lineStrokeHover = "2.5px";

        var circleOpacity = '0.85';
        var circleOpacityOnLineHover = "0.25"
        var circleRadius = 3;
        var circleRadiusHover = 6;


        /* Format Data */
        var parseDate = d3.time.format("%Y");
        data.forEach(function(d) {
            d.values.forEach(function(d) {
               // d.date = parseDate.parse(d.date);
                d.price = +d.price;
            });
        });

			//console.log(data);

				//console.log(d3.extent(data[0].values, d => d.date));
        /* Scale */
        var xScale = d3.scale.linear()
            .domain(d3.extent(data[0].values, d => d.date))
            .range([0, width-margin]);
            
        var yScale = d3.scale.linear()
            .domain([0, d3.max(data[0].values, d => d.price)])
            .range([height-margin, 0]);

        // var color = d3.scale.ordinal(d3.schemeCategory10);
        var color = d3.scale.category10();

        /* Add SVG */
        var svg = d3.select("svg")
            .attr("width", (width+margin)+"px")
            .attr("height", (height+margin)+"px")
            .append('g')
            .attr("transform", `translate(${margin}, ${margin})`);


        /* Add line into SVG */
        var line = d3.svg.line()
            .x(d => xScale(d.date))
            .y(d => yScale(d.price));

        let lines = svg.append('g')
            .attr('class', 'lines');

        lines.selectAll('.line-group')
            .data(data).enter()
            .append('g')
            .attr('class', 'line-group')
            .on("mouseover", function(d, i) {
                svg.append("text")
                    .attr("class", "title-text")
                    .style("fill", color(i))
                    .text(d.name)
                    .attr("text-anchor", "middle")
                    .attr("x", (width-margin)/2)
                    .attr("y", 5);
            })
            .on("mouseout", function(d) {
                svg.select(".title-text").remove();
            })
            .append('path')
            .attr('class', 'line')
            .attr('d', d => line(d.values))
            .style('stroke', (d, i) => color(i))
            .style('opacity', lineOpacity)
            .on("mouseover", function(d) {
                d3.selectAll('.line')
                    .style('opacity', otherLinesOpacityHover);
                d3.selectAll('.circle')
                    .style('opacity', circleOpacityOnLineHover);
                d3.select(this)
                    .style('opacity', lineOpacityHover)
                    .style("stroke-width", lineStrokeHover)
                    .style("cursor", "pointer");
            })
            .on("mouseout", function(d) {
                d3.selectAll(".line")
                    .style('opacity', lineOpacity);
                d3.selectAll('.circle')
                    .style('opacity', circleOpacity);
                d3.select(this)
                    .style("stroke-width", lineStroke)
                    .style("cursor", "none");
            });


        /* Add circles in the line */
        lines.selectAll("circle-group")
            .data(data).enter()
            .append("g")
            .style("fill", (d, i) => color(i))
            .selectAll("circle")
            .data(d => d.values).enter()
            .append("g")
            .attr("class", "circle")
            .on("mouseover", function(d) {
                d3.select(this)
                    .style("cursor", "pointer")
                    .append("text")
                    .attr("class", "text")
                    .text(`${d.price}`)
                    .attr("x", d => xScale(d.date) + 5)
                    .attr("y", d => yScale(d.price) - 10);
            })
            .on("mouseout", function(d) {
                d3.select(this)
                    .style("cursor", "none")
                    .transition()
                    .duration(duration)
                    .selectAll(".text").remove();
            })
            .append("circle")
            .attr("cx", d => xScale(d.date))
            .attr("cy", d => yScale(d.price))
            .attr("r", circleRadius)
            .style('opacity', circleOpacity)
            .on("mouseover", function(d) {
                d3.select(this)
                    .transition()
                    .duration(duration)
                    .attr("r", circleRadiusHover);
            })
            .on("mouseout", function(d) {
                d3.select(this)
                    .transition()
                    .duration(duration)
                    .attr("r", circleRadius);
            });

        /* Add Axis into SVG */
        var xAxis = d3.svg.axis().scale(xScale)
            .orient("bottom").ticks(5).tickFormat(function(d) {
              if (d % 1 == 0) {
                return d3.format('.f')(d)
              } else {
                return ""
              }
            }).tickSize(1);

        var yAxis = d3.svg.axis().scale(yScale)
            .orient("left").tickSize(1);
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", `translate(0, ${height-margin})`)
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append('text')
            .attr("y", 15)
            .attr("transform", "rotate(-90)")
            .attr("fill", "#000")
            .attr('text-anchor', 'middle')
            .text("No. of Employees");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.10/d3.min.js"></script>
<html>
  <head>
  </head>
  <body>
    <svg/>
  </body>
</html>
...