D3.js繪制基本圖形


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>

運行結果展示:
在這里插入圖片描述
這是在上一個堆棧圖的基礎上進行的修改,因為日常的需求中是需要我們對堆棧圖中的數據,通過折線圖的形式進行更加直觀的展示,折線圖可以看出數據的變化,這里這一橫坐標是年,年作為兩個圖形形式的同一個橫坐標,是我們在繪制雙圖形時,需要特別注意的地方。

 
https://blog.csdn.net/qq_39355295/article/details/87477442


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM