Edg*_*jak 5 javascript svg d3.js
我正在尝试用面积图形状将线上的点拟合,但是不适合。我认为这是由于.curve使用d3.curveBasis。
data = [
  {
    "login_date": "2017-09-24",
    "unique_user_count": 2,
    "total_login_count": 2
  },
  {
    "login_date": "2017-09-25",
    "unique_user_count": 25,
    "total_login_count": 46
  },
  {
    "login_date": "2017-09-26",
    "unique_user_count": 31,
    "total_login_count": 74
  },
  {
    "login_date": "2017-09-27",
    "unique_user_count": 29,
    "total_login_count": 58
  },
  {
    "login_date": "2017-09-28",
    "unique_user_count": 29,
    "total_login_count": 60
  },
  {
    "login_date": "2017-09-29",
    "unique_user_count": 31,
    "total_login_count": 71
  },
  {
    "login_date": "2017-09-30",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-01",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-02",
    "unique_user_count": 41,
    "total_login_count": 71
  },
  {
    "login_date": "2017-10-03",
    "unique_user_count": 30,
    "total_login_count": 67
  },
  {
    "login_date": "2017-10-04",
    "unique_user_count": 28,
    "total_login_count": 45
  },
  {
    "login_date": "2017-10-05",
    "unique_user_count": 32,
    "total_login_count": 48
  },
  {
    "login_date": "2017-10-06",
    "unique_user_count": 30,
    "total_login_count": 50
  },
  {
    "login_date": "2017-10-07",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-08",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-09",
    "unique_user_count": 35,
    "total_login_count": 76
  },
  {
    "login_date": "2017-10-10",
    "unique_user_count": 37,
    "total_login_count": 63
  },
  {
    "login_date": "2017-10-11",
    "unique_user_count": 41,
    "total_login_count": 76
  },
  {
    "login_date": "2017-10-12",
    "unique_user_count": 42,
    "total_login_count": 83
  },
  {
    "login_date": "2017-10-13",
    "unique_user_count": 41,
    "total_login_count": 68
  },
  {
    "login_date": "2017-10-15",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-16",
    "unique_user_count": 48,
    "total_login_count": 84
  },
  {
    "login_date": "2017-10-17",
    "unique_user_count": 50,
    "total_login_count": 98
  },
  {
    "login_date": "2017-10-18",
    "unique_user_count": 38,
    "total_login_count": 56
  },
  {
    "login_date": "2017-10-19",
    "unique_user_count": 38,
    "total_login_count": 98
  },
  {
    "login_date": "2017-10-20",
    "unique_user_count": 40,
    "total_login_count": 71
  },
  {
    "login_date": "2017-10-22",
    "unique_user_count": 2,
    "total_login_count": 2
  }];
  
 //Define SVG container full width and height
const fullWidth = 600;
const fullHeight = 200;
//Define bar chart area  widht and height
const margin = {
    top: 10,
    bottom: 10,
    left: 20,
    right: 20
}
const chartWidth = fullWidth - margin.left - margin.right;
const chartHeight = fullHeight - margin.top - margin.bottom;
//Draw SVG container
let svg = d3.select('body')
    .append('svg')
    .attr('width', fullWidth)
    .attr('height', fullHeight);
//Define xand y scale range of the bar chart
const xScale = d3.scaleBand()
    .range([0, chartWidth]);
const yScale = d3.scaleLinear()
    .range([chartHeight, 0]);
const yScale2 = d3.scaleLinear()
    .range([chartHeight, 0]);
    console.log('Data received from an API:', data)
    //defiene x and y scale domain
    yScale
        .domain([0, d3.max(data, d => +d.total_login_count)]);
    yScale2
        .domain([0, d3.max(data, d => +d.unique_user_count)]);
    xScale
        .domain(data.map(d => d.login_date));
    //Generate total login area chart
    let area = d3.area()
        .curve(d3.curveBasis)
        .x(function (d) {
            return xScale(d.login_date);
        })
        .y0(fullHeight)
        .y1(function (d) {
            return yScale(+d.total_login_count)
        });
    //Generate unique user count area chart
    let area2 = d3.area()
        .curve(d3.curveBasis)
        .x(function (d) {
            return xScale(d.login_date);
        })
        .y0(fullHeight)
        .y1(function (d) {
            return yScale2(+d.unique_user_count)
        });
    //Draw bar chart
    let group = svg.selectAll('g')
        .data([data])
        .enter()
        .append('g');
    //Draw area for total login count
    group
        .append('path')
        .attr('class', 'area')
        .attr('d', area);
    //Draw area for unique user count 
    group
        .append('path')
        .attr('class', 'area2')
        .attr('d', area2);
    //Dot points
    let points = group.selectAll('circle')
        .data(data)
        .enter()
        .append('circle');
    //Dot points
    let points2 = group.select('circle')
        .data(data)
        .enter()
        .append('circle');
    points.attrs({
            "cx": d => xScale(d.login_date),
            "cy": d => yScale(+d.total_login_count) + 10,
            "r": 5
        })
        .style("opacity", 1)
        .style('fill', '#F9A2CB');
    points2.attrs({
            "cx": d => xScale(d.login_date),
            "cy": d => yScale2(+d.unique_user_count) + 5,
            "r": 5
        })
        .style("opacity", 1)
        .style('fill', '#8BDBCE');<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bar chart</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://d3js.org/d3-fetch.v1.min.js"></script>
    <script src='https://d3js.org/d3-selection-multi.v0.4.min.js'></script>
</head>
<style>
    .line {
        fill: none;
        stroke: orange;
        stroke-width: 1px;
    }
    .area {
        fill: #F9A2CB;
        stroke: none;
        opacity: 0.6;
        }
    
    .area2 {
        fill: #8BDBCE;
        stroke: none;
        opacity: 0.6;
        }
</style>
<body>
    <script type="text/javascript" src="main.js"></script>
</body>
</html>这是我的方法:
//define x and y scale domain
    yScale
        .domain([0, d3.max(data, d => +d.total_login_count)]);
    yScale2
        .domain([0, d3.max(data, d => +d.unique_user_count)]);
    xScale
        .domain(data.map(d => d.login_date));
    //Generate total login area chart
    let area = d3.area()
        .curve(d3.curveBasis)
        .x(function (d) {
            return xScale(d.login_date);
        })
        .y0(fullHeight)
        .y1(function (d) {
            return yScale(+d.total_login_count)
        });
    //Generate unique user count area chart
    let area2 = d3.area()
        .curve(d3.curveBasis)
        .x(function (d) {
            return xScale(d.login_date);
        })
        .y0(fullHeight)
        .y1(function (d) {
            return yScale2(+d.unique_user_count)
        });
    //Draw bar chart
    let group = svg.selectAll('g')
        .data([data])
        .enter()
        .append('g');
    //Draw area for total login count
    group
        .append('path')
        .attr('class', 'area')
        .attr('d', area);
    //Draw area for unique user count 
    group
        .append('path')
        .attr('class', 'area2')
        .attr('d', area2);
    //Dot points
    let points = group.selectAll('circle')
        .data(data)
        .enter()
        .append('circle');
    //Dot points
    let points2 = group.select('circle')
        .data(data)
        .enter()
        .append('circle');
    points.attrs({
            "cx": d => xScale(d.login_date),
            "cy": d => yScale(+d.total_login_count) + 10,
            "r": 5
        })
        .style("opacity", 1)
        .style('fill', '#F9A2CB');
    points2.attrs({
            "cx": d => xScale(d.login_date),
            "cy": d => yScale2(+d.unique_user_count) + 5,
            "r": 5
        })
        .style("opacity", 1)
        .style('fill', '#8BDBCE');
你说得对,问题d3.curveBasis确实存在。
正如您所看到的,d3.curveBasis是一个插值器,它生成的路径不会完全通过控制点:
我的建议是使用插值器来生成经过控制点的路径,例如d3.curveCatmullRom:
这是经过更改的代码:
data = [
  {
    "login_date": "2017-09-24",
    "unique_user_count": 2,
    "total_login_count": 2
  },
  {
    "login_date": "2017-09-25",
    "unique_user_count": 25,
    "total_login_count": 46
  },
  {
    "login_date": "2017-09-26",
    "unique_user_count": 31,
    "total_login_count": 74
  },
  {
    "login_date": "2017-09-27",
    "unique_user_count": 29,
    "total_login_count": 58
  },
  {
    "login_date": "2017-09-28",
    "unique_user_count": 29,
    "total_login_count": 60
  },
  {
    "login_date": "2017-09-29",
    "unique_user_count": 31,
    "total_login_count": 71
  },
  {
    "login_date": "2017-09-30",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-01",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-02",
    "unique_user_count": 41,
    "total_login_count": 71
  },
  {
    "login_date": "2017-10-03",
    "unique_user_count": 30,
    "total_login_count": 67
  },
  {
    "login_date": "2017-10-04",
    "unique_user_count": 28,
    "total_login_count": 45
  },
  {
    "login_date": "2017-10-05",
    "unique_user_count": 32,
    "total_login_count": 48
  },
  {
    "login_date": "2017-10-06",
    "unique_user_count": 30,
    "total_login_count": 50
  },
  {
    "login_date": "2017-10-07",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-08",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-09",
    "unique_user_count": 35,
    "total_login_count": 76
  },
  {
    "login_date": "2017-10-10",
    "unique_user_count": 37,
    "total_login_count": 63
  },
  {
    "login_date": "2017-10-11",
    "unique_user_count": 41,
    "total_login_count": 76
  },
  {
    "login_date": "2017-10-12",
    "unique_user_count": 42,
    "total_login_count": 83
  },
  {
    "login_date": "2017-10-13",
    "unique_user_count": 41,
    "total_login_count": 68
  },
  {
    "login_date": "2017-10-15",
    "unique_user_count": 1,
    "total_login_count": 1
  },
  {
    "login_date": "2017-10-16",
    "unique_user_count": 48,
    "total_login_count": 84
  },
  {
    "login_date": "2017-10-17",
    "unique_user_count": 50,
    "total_login_count": 98
  },
  {
    "login_date": "2017-10-18",
    "unique_user_count": 38,
    "total_login_count": 56
  },
  {
    "login_date": "2017-10-19",
    "unique_user_count": 38,
    "total_login_count": 98
  },
  {
    "login_date": "2017-10-20",
    "unique_user_count": 40,
    "total_login_count": 71
  },
  {
    "login_date": "2017-10-22",
    "unique_user_count": 2,
    "total_login_count": 2
  }];
  
 //Define SVG container full width and height
const fullWidth = 600;
const fullHeight = 200;
//Define bar chart area  widht and height
const margin = {
    top: 10,
    bottom: 10,
    left: 20,
    right: 20
}
const chartWidth = fullWidth - margin.left - margin.right;
const chartHeight = fullHeight - margin.top - margin.bottom;
//Draw SVG container
let svg = d3.select('body')
    .append('svg')
    .attr('width', fullWidth)
    .attr('height', fullHeight);
//Define xand y scale range of the bar chart
const xScale = d3.scaleBand()
    .range([0, chartWidth]);
const yScale = d3.scaleLinear()
    .range([chartHeight, 0]);
const yScale2 = d3.scaleLinear()
    .range([chartHeight, 0]);
    console.log('Data received from an API:', data)
    //defiene x and y scale domain
    yScale
        .domain([0, d3.max(data, d => +d.total_login_count)]);
    yScale2
        .domain([0, d3.max(data, d => +d.unique_user_count)]);
    xScale
        .domain(data.map(d => d.login_date));
    //Generate total login area chart
    let area = d3.area()
        .curve(d3.curveCatmullRom)
        .x(function (d) {
            return xScale(d.login_date);
        })
        .y0(fullHeight)
        .y1(function (d) {
            return yScale(+d.total_login_count)
        });
    //Generate unique user count area chart
    let area2 = d3.area()
        .curve(d3.curveCatmullRom)
        .x(function (d) {
            return xScale(d.login_date);
        })
        .y0(fullHeight)
        .y1(function (d) {
            return yScale2(+d.unique_user_count)
        });
    //Draw bar chart
    let group = svg.selectAll('g')
        .data([data])
        .enter()
        .append('g');
    //Draw area for total login count
    group
        .append('path')
        .attr('class', 'area')
        .attr('d', area);
    //Draw area for unique user count 
    group
        .append('path')
        .attr('class', 'area2')
        .attr('d', area2);
    //Dot points
    let points = group.selectAll('circle')
        .data(data)
        .enter()
        .append('circle');
    //Dot points
    let points2 = group.select('circle')
        .data(data)
        .enter()
        .append('circle');
    points.attrs({
            "cx": d => xScale(d.login_date),
            "cy": d => yScale(+d.total_login_count),
            "r": 5
        })
        .style("opacity", 1)
        .style('fill', '#F9A2CB');
    points2.attrs({
            "cx": d => xScale(d.login_date),
            "cy": d => yScale2(+d.unique_user_count),
            "r": 5
        })
        .style("opacity", 1)
        .style('fill', '#8BDBCE');<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bar chart</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://d3js.org/d3-fetch.v1.min.js"></script>
    <script src='https://d3js.org/d3-selection-multi.v0.4.min.js'></script>
</head>
<style>
    .line {
        fill: none;
        stroke: orange;
        stroke-width: 1px;
    }
    .area {
        fill: #F9A2CB;
        stroke: none;
        opacity: 0.6;
        }
    
    .area2 {
        fill: #8BDBCE;
        stroke: none;
        opacity: 0.6;
        }
</style>
<body>
    <script type="text/javascript" src="main.js"></script>
</body>
</html>| 归档时间: | 
 | 
| 查看次数: | 56 次 | 
| 最近记录: |