D3.js绘制基本图形

d3.js 绘制基本图形

最近开始学习d3.js 主要是,初步认识d3.js,并且运行D3.jsD3.js数据可视化(data visualization)环境.
因为之前没有接触郭d3,因为业务需求,需要绘制一系列的图表,所以上来直接学习绘制,刚开始经过一天的简单了解,懂得了d3绘制代码的基本格式,然后开始搜索自己需要的图形的基本模板,然后根据自己的 实际业务需求来进行基本的更改,这样就需要我们对自己需要使用的代码,全程了解,这样我们就可以更加便捷的进行修改。下面是我最近三天自己绘制一些基本图形的代码:
这里注意:因为没有认真的学习过d3知识,在绘制时,因为不同版本的方法使用不同,所以我在引入d3的时候,会同时插入两个版本的d3,使用方法,

 <script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://npmcdn.com/@turf/turf/turf.min.js"></script>

1、条形图

    首先贴上完整的代码进行展示:因为是是刚开始学习d3,所以代码里都做了基本的注释。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>条形图</title>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script src="https://npmcdn.com/@turf/turf/turf.min.js"></script>
    <style>
            .axis path,
            .axis line{
                fill: none;
                stroke: black;
                shape-rendering: crispEdges;
            }
            .axis text {
                font-family: sans-serif;
                font-size: 15px;
            }
    </style>
</head>
<body>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <script type="text/javascript">

            //1、定义宽高
            var height = 600;
            var width = 600;

            //2、添加数据
            var dataset= [30,20,45,12,21,28,46,64,73,78,54];

            // var num = 15;

            //设置刷新事件,当没刷新一次数据变化一次,条形图也随之变化
            // for(var i = 0; i < 4; i++){ 
            //     var tempnum = Math.floor(Math.random() * 50);
            //     dataset.push(tempnum);
            // }
            // console.log(dataset);
    
            var svg = d3.select("body").append("svg")
                    .attr("width", width)
                    .attr("height", height);
    
            var xAxisScale = d3.scale.ordinal()
                    .domain(d3.range(dataset.length))
                    .rangeRoundBands([0, 500]);
    
            var yAxisScale = d3.scale.linear()
                    .domain([0, d3.max(dataset)])
                    .range([500, 0]);
    
            var xAxis = d3.svg.axis().scale(xAxisScale).orient("bottom");
            var yAxis = d3.svg.axis().scale(yAxisScale).orient("left");
    
            var xScale = d3.scale.ordinal()
                    .domain(d3.range(dataset.length))
                    .rangeRoundBands([0,500],0.05);
    
            var yScale = d3.scale.linear()
                    .domain([0,d3.max(dataset)])
                    .range([0,500]);
    
            // 绘制矩形
            svg.selectAll("rect")
                    .data(dataset)
                    .enter()
                    .append("rect")
                    // .on("click",  function(){
                    //     d3.select(this).attr("fill","black");
                    // }) // 添加点击事件
                    .attr("x", function(d,i){
                        return 100 + xScale(i);
                    } )
                    .attr("y",function(d,i){
                        return 50 + 500 - yScale(d) ;
                    })
                    .attr("width", function(d,i){
                        return xScale.rangeBand();
                    })
                    .attr("height",yScale)
                    .attr("fill", "steelblue")
                    .transition()
                    .duration(2000)
                    .ease("bounce")
                    .delay(1000)
                    .attr("fill","red");
    
            // 绘制文字标签
            svg.selectAll("text")
                    .data(dataset)
                    .enter().append("text")
                    .attr("x", function(d,i){
                        return 100 + xScale(i);
                    } )
                    .attr("y",function(d,i){
                        return 50 + 500 - yScale(d) ;
                    })
                    .attr("dx", function(d,i){
                        return xScale.rangeBand()/3;
                    })
                    .attr("dy", 15)
                    .attr("text-anchor", "begin")
                    .attr("font-size", 14)
                    .attr("fill","white")
                    .text(function(d,i){
                        return d;
                    });
    
            //      在<svg>中添加元素<g>,g是svg标准中定义的元素,是分组的意思,用于把相关的元素进行组合的容器元素
            //      将包含坐标轴的元素组合在一个group里call(xAxis),调用函数xAxis并设置执行上下文为元素<g>。
            //      attr("transform","translate(100, 550)")表示将x轴右移100px,并下移550px 
            svg.append("g")
                    .attr("class","axis")
                    .attr("transform","translate(100,550)")
                    .call(xAxis);
    
            svg.append("g")
                    .attr("class","axis")
                    .attr("transform","translate(100,50)")
                    .call(yAxis);
        </script>
</body>
</html>

下面是图形展示:大家可以根据自己的需求,来进行代码的更改。
在这里插入图片描述
2、折线图
代码展示:

<!DOCTYPE html>
<meta charset="utf-8">
<style type="text/css">
.line {
    fill: none;
    stroke: #ffab00;
    stroke-width: 3;
}
/* .dot {
    fill: #ffab00;
    stroke: #fff;
} */
</style>

<body>
    <script src="https://d3js.org/d3.v4.min.js"></script>
    <script>
            //1、定义宽高
            var margin = {top: 50, right: 50, bottom: 50, left: 50};
                // var width = window.innerWidth - margin.left - margin.right ; // Use the window's width 
                // var height = window.innerHeight - margin.top - margin.bottom ;
            var width = 400 - margin.left - margin.right ; 
            var height = 400 - margin.top - margin.bottom ;

               // 把svg添加到页面并使用
            var svg = d3.select("body").append("svg")
                        .attr("width", width + margin.left + margin.right)
                        .attr("height", height + margin.top + margin.bottom)
                        .append("g")
                        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            //2、初始化数据
            var dataset = [{'y':0.2},{'y':0.2},{'y':0.4},{'y':0.5},{'y':0.55},{'y':0.5}] //d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } })
            
            // 3、比例尺
            var xScale = d3.scaleLinear()
                        .domain([0, dataset.length-1]) 
                        .range([0, width]); 
            
            var yScale = d3.scaleLinear()
                        .domain([0, 1]) 
                        .range([height, 0]); 

            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(xScale)); // 使用d3.axisBottom创建axis组件
            
            svg.append("g")
                .attr("class", "y axis")
                .call(d3.axisLeft(yScale)); // 创建一个带有d3.axisLeft的axis组件
            
            //4、绘制直线
            var line = d3.line()
                        .x(function(d, i) { return xScale(i); }) 
                        .y(function(d) { return yScale(d.y); }) 
                        // .curve(d3.curveBasis) // 对折线进行平滑处理
            
            
            
            // 5. 追加路径、绑定数据并调用行生成器
            svg.append("path")
                .datum(dataset) // 10. Binds data to the line 
                .attr("class", "line") // Assign a class for styling 
                .attr("d", line); // 11. Calls the line generator 
            
            //6. 为每个数据点追加一个圆
            svg.selectAll("circle")
                .data(dataset)
                .enter()
                .append("circle") 
                .attr("class", "dot") // 为样式分配一个类
                .attr("cx", function(d, i) { return xScale(i) })
                .attr("cy", function(d) { return yScale(d.y) })
                .attr("r", 4)
                .attr("stroke", "#5E5E5E")
                .attr("stroke-width", 2)
                .attr('fill',"none");
            
    </script>
</body>





效果图展示:
在这里插入图片描述
3、散点图
代码展示:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>D3-coordinate-test</title>
  <script src="http://d3js.org/d3.v3.min.js"></script>
  <style>
    /* .cocoordinate-div {
      margin: 100px 500px 100px;
      border: 2px solid blue;
    } */
    .title {
      font-size: 26px;
      font-family: 'Microsoft YaHei';
      fill: red;
    }
    .axis path,
    .axis line {
      fill: none;
      stroke: black;
      shape-rendering: crispEdges;
    }
    .axis text {
      font-family: 'Microsoft YaHei';
      font-size: 12px;
    }
  </style>
</head>
<body>
  <script>

    //1、设置宽高
    var Width = 800;
    var Height = 400;
    var padding =  60;
 
    //2、数据初始化
    var dataset = [
      [0, 0], [65.66, 420], [520, 260], [360, 320], [200, 200],
      [130, 623], [652, 52], [333, 666], [729, 656], [134, 352],
      [120, 56], [905, 177], [777, 888], [1200, 1000]
    ];
 
    var svg = d3.select('body')   //创建SVG
            .append('svg')
            .attr('width', Width)
            .attr('height', Height);
 
    // 3、设置标题
    svg.append('text')
        .attr('x', Width / 2 - 120)
        .attr('y', 30)
        .attr('class', 'title') //title定义样式属性
        .text('这是一个用d3画的简略坐标轴');
 
    // 4、创建比例尺
    var xScale = d3.scale.linear()
                .domain([0, d3.max(dataset, function(d) {
                    return d[0]; })])
                .range([padding, Width - padding * 2]);
 
    var yScale = d3.scale.linear()
                .domain([0, d3.max(dataset, function(d) {
                        return d[1]; })])
                .range([Height - padding, padding]);
 
    var rScale = d3.scale.linear()
                .domain([0, d3.max(dataset, function(d) {
                    return d[1];    })])
                .range([2, 4]);
 
    // 5、设置散点的坐标, 半径
    svg.selectAll('circle')
            .data(dataset)
            .enter().append('circle')
            .attr('cx', function(d) {
                 return xScale(d[0]); })
            .attr('cy', function(d) {
                return yScale(d[1]);    })
            .attr('r', function(d) {
                return rScale(d[1]);
            });
 
    // 6、设置文本
    svg.selectAll('text')
        .data(dataset)
        .enter().append('text')
        .text(function(d) {
           return '(' + d[0] + ', ' + d[1] + ')'; })
        .attr('x', function(d) {
          // 设置偏移量,让文本位于上方
          return xScale(d[0]) - 20; })
        .attr('y', function(d) {
          return yScale(d[1]) - 10; })
        .attr('font-family', 'Microsoft YaHei')
        .attr('font-size', '12px')
        .attr('fill', '#9400D3');
 
    
 
    //7、绘制坐标轴

        // 设置精度和样式
    var formatPrecision = d3.format('$');
   
    var xAxis = d3.svg.axis()  // 定义X轴
      .scale(xScale)
      .ticks(7) // 粗略的设置刻度线的数量,包括原点
      .orient('bottom')
      .tickFormat(formatPrecision);
 
   
    var yAxis = d3.svg.axis()  // 定义Y轴
            .scale(yScale)
            .orient('left')
            .ticks(7)
            .tickFormat(formatPrecision);
 
   
    svg.append('g') // svg中: g元素是一个分组元素 创建X轴, 
      .attr('class', 'axis')
      .attr('transform', 'translate(0, ' + (Height - padding) + ')')// 设置据下边界的距离
      .call(xAxis);

    svg.append('g')  // 创建Y轴
      .attr('class', 'axis')
      .attr('transform', 'translate(' + padding + ', 0)') // Y轴离左边界的距离
      .call(yAxis);
 
  </script>
</body>
</html>

在这里插入图片描述
4、简单堆栈图
完整代码展示:

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
  <style>
    .tick text {
      font-size: 10px; 
    }
  </style>
</head>
<body>
  <script>

      //1、定义宽高
    const width = 500;
    const height = 450;
    const margin = { top: 25, right: 35, bottom: 100, left: 50 };

    //2、确定初始数据
    const data = [
      {year:2005, value1:3000 ,value2:200 ,value3:0.06},
      {year:2006, value1:1400 ,value2:40,value3:0.02},
      {year:2007, value1:3800 ,value2:100,value3:0.03},
      {year:2008, value1:4900 ,value2:70,value3:0.01},
      {year:2009, value1:2000 ,value2:80,value3:0.04}
    ];

    //3、堆栈图颜色设置
	const colors = ['orange', 'red'];  //颜色分组
    const groups = ['value1', 'value2']; //类别分组

    const layout = d3.stack().keys(groups)(data);//用来生成一个以0到groups.length-1为主键的堆栈生成器

    const svg = d3.select('body')                    //选择body元素
                  .append('svg')                     //在body元素中添加svg
                  .attr('width', width + margin.left + margin.right) //设定<svg>的宽度属性
                  .attr('height', height + margin.top + margin.bottom) //设定<svg>的高度属性
                  .append('g')
                  .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
    
    //4、绘制坐标轴比例尺
    const xScale = d3.scaleBand()
    	             .padding(0.4)  //设置条形图的间隔
    	             .domain(data.map(d => d.year))  //对条形图的横坐标进行映射
    	             .range([0, width]);
    

    const yMax = 6000;
    const yScale = d3.scaleLinear()
    	            .domain([0, yMax])
    	            .range([height, 0]);
    
    const xAxis = d3.axisBottom(xScale);
    const yAxis = d3.axisLeft(yScale).ticks(10);
   
    svg.append('g')
    	.attr('transform', `translate(0, ${height})`)
        .call(xAxis)
    	.selectAll('text')
    	// .attr('transform', 'rotate(-45)')  //这是一个控制横坐标字体斜体;
    svg.append('g').call(yAxis);

    
    // 5、开始绘制堆栈图
        //堆栈图
    svg
    	.selectAll('.group')
    	.data(layout)
    	.enter()
    	.append('g')
    	.attr('year', ({key}) => key)
    	.attr('fill', (d, i) => colors[i])
        .selectAll('body')
    	.data(d => d)
    	.enter()
    	.append('rect')
    	.attr('x', ({data: {year}}) => xScale(year))
    	.attr('y', ([y, h]) => yScale(h))
        .attr('width', xScale.bandwidth())
        .attr('height', ([y, h]) => height - yScale(h - y));
  </script>
</body>

运行结果展示:
在这里插入图片描述
5、带有折线图的堆栈图:
完整代码展示:

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
  <style>
    .tick text {
      font-size: 10px; 
    }
    .axis path,
    .axis line{
        fill: none;
        stroke: black;
        shape-rendering: crispEdges;
        }
    .axis text {
        font-family: sans-serif;
        font-size: 8px;
        }
  </style>
</head>
<body>
  <script>
      //1、定义宽高
    const margin = { top: 25, right: 35, bottom: 100, left: 50 };
    const width = 500;
    const height = 450;

    //2、确定初始数据
    const data = [
      {year:2005, value1:3000 ,value2:200 ,value3:0.06},
      {year:2006, value1:1400 ,value2:40,value3:0.02},
      {year:2007, value1:3800 ,value2:100,value3:0.03},
      {year:2008, value1:4900 ,value2:70,value3:0.01},
      {year:2009, value1:2000 ,value2:80,value3:0.04}
    ];

    const svg = d3.select('body')                    //选择body元素
                  .append('svg')                     //在body元素中添加svg
                  .attr('width', width + margin.left + margin.right) //设定<svg>的宽度属性
                  .attr('height', height + margin.top + margin.bottom) //设定<svg>的高度属性
                  .append('g')
                  .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');

    //3、堆栈图颜色设置
	const colors = ['#ff6633', '#CDAF95'];  //颜色分组
    const groups = ['value1', 'value2']; //类别分组

    const layout = d3.stack().keys(groups)(data);//用来生成一个以0到groups.length-1为主键的堆栈生成器
    
    //4、绘制坐标轴比例尺
      //设置刻度格式
    var formatAsPercentage = d3.format(".1%")

    const xScale = d3.scaleBand()
    	             .padding(0.4)  //设置条形图的间隔
    	             .domain(data.map(d => d.year))  //对条形图的横坐标进行映射
    	             .range([0, width]);

    const yMax = 6000;
    const yScale = d3.scaleLinear()
    	.domain([0, yMax])
    	.range([height, 0]);

    const zMax=0.06;
    const zScale = d3.scaleLinear()
                    .domain([0,zMax])
                    .range([height,0]);
        
    const xAxis = d3.axisBottom(xScale);
    const yAxis = d3.axisLeft(yScale).ticks(10);
    const zAxis= d3.axisRight(zScale).ticks(10).tickFormat(formatAsPercentage);

    svg.append('g')  //横坐标的显示
    	.attr('transform', `translate(0, ${height})`)
        .call(xAxis)
    	.selectAll('text')
    	// .attr('transform', 'rotate(-45)')  //这是一个控制横坐标字体斜体;
    svg.append('g').call(yAxis);
    svg.append('g').call(zAxis).attr("transform","translate("+width+",0)");

    
    // 5、开始绘制堆栈图
        //堆栈图
    svg
    	.selectAll('.group')
    	.data(layout)
    	.enter()
    	.append('g')
    	.attr('year', ({key}) => key)
    	.attr('fill', (d, i) => colors[i])
        .selectAll('body')
    	.data(d => d)
    	.enter()
    	.append('rect')
    	.attr('x', ({data: {year}}) => xScale(year))
    	.attr('y', ([y, h]) => yScale(h))
        .attr('width', xScale.bandwidth())
        .attr('height', ([y, h]) => height - yScale(h - y));

    //6、开始绘制折线图
      
    var lineGen = d3.svg.line()
                .x(function(d) {
                    //设置折线图的偏移量,使折线点居中
                     return xScale(d.year)+xScale.bandwidth()/2;
                })
                .y(function(d) {
                     return zScale(d.value3);
                });
        svg.append('path')
                .attr('d', lineGen(data))
                .attr('stroke', '#ffcc33')
                .attr('stroke-width', 3)
                .attr('fill', 'none');
       
        //为折线图每个点坐标添加透明圆圈
        svg.selectAll('circle')
            .data(data)
            .enter()
            .append('circle')
            .attr('cx', function(d) {
              return xScale(d.year)+xScale.bandwidth()/2+0.5;
            })
            .attr('cy', function(d) {
              return zScale(d.value3)-1;
            })
            .attr('r', 3.5)
            .attr('fill',"none")
            .attr("stroke", "#5E5E5E")
            .attr("stroke-width", 1);

  </script>
</body>

运行结果展示:
在这里插入图片描述
这是在上一个堆栈图的基础上进行的修改,因为日常的需求中是需要我们对堆栈图中的数据,通过折线图的形式进行更加直观的展示,折线图可以看出数据的变化,这里这一横坐标是年,年作为两个图形形式的同一个横坐标,是我们在绘制双图形时,需要特别注意的地方。

猜你喜欢

转载自blog.csdn.net/qq_39355295/article/details/87477442