HTML5-数据可视化学习笔记-进阶之路

数据可视化

点、线、柱、饼...
简单地说,数据可视化就是以图形的方式表示数据

数据可视化的技术

echartshighcharts、百度地图chartjsD3.js

第3方的可视化库依赖两个东西
Echarts.js 依赖于canvas  图片放大会失真  市面上用的比较多, 现有的图形非常丰富。
D3.js 依赖于svg 不会失真 图形非常少,擅长定制各种图形

canvas原生技术

快速入门

canvas是html5新增的一个标签,后续所有的操作都使用js脚本 。
canvas就是一个画板或画布。
css3 + js的运动 + 定时器
更准确的说是 html5新增的js_api  /  video  ( play ,pause )  localstorage

Canvas标签、画笔对象、基本的图形( 矩形 、圆、线、其它特殊图形【正方形、三角形】 )
路径的概念( 开启路径、关闭路径 )
绘制图像(现有的图形放置到canvas中)
绘制文字
图形【画布】的转换,放大、旋转、位移

canvas的基本概念

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>canvas基础-绘制矩形</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        #canvas{
            border: 1px solid rebeccapurple;
            /* width: 500px;
            height: 500px; */
        }
    </style>
</head>
<body>
    <!-- 
        默认透明,
        默认宽300 高150  像素,
        新增的标签:兼容
        注意事项:不要使用css设置canvas的宽和高。
        同时画布是透明的png,默认画布上的点、线、文字色 都是黑色
        坐标系:下和右是坐标系正方向 。
        canvas 是画布,所以也是图片
        width
        height
        也可以使用js指定画布的宽和高
        canvas画板有了,接下来需要一个画笔对象
     -->
    <canvas id="canvas"  width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
 
    <script>
        // 获取元素
        let canvas = document.getElementById('canvas');
        // 可以用js设置 但不要加style.width 这样又成css了
        // canvas.width = 500;
        // canvas.height = 500;
        //获取画笔对象( 画布的上下文环境对象 )
        let ctx = canvas.getContext('2d');
        console.log(canvas.getContext,ctx);
        //绘制一个矩形  画笔对象上肯定有一个绘制矩形的功能函数   fillRect() 填充一个矩形  strokeRect 描边一个矩形
        // fillRect(x,y,width,height)
 
        ctx.fillRect(10,10,100,150); //填充一个矩形
 
        ctx.strokeRect(120,10,50,200); //描边一个矩形
 
        // 45°的斜线
        ctx.moveTo(10,10);
        ctx.lineTo(200,200);
        ctx.lineWidth = 2;
        ctx.strokeStyle = 'red';
        ctx.stroke();
 
    </script>
</body>
</html>

绘制图形步骤

创建canvas标签
获取canvas对象
获取ctx画笔对象
使用画笔中的各种方法和路径绘制各种各样的图形

路径

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>路径 - 画线</title>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        #canvas{
            border: 1px solid red;
        }
    </style>
</head>
<body>
    <canvas id="canvas"  width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');
        //圆 /椭圆和矩形有现成的方法就代表 圆和矩形  arc| 描绘一个圆的路径  rect|描绘一个矩形路径
        //然后使用 fill或rect进行填充
 
        // 绘制一个矩形
        // ctx.rect(20,20,100,150);
        // ctx.fill();// 填充 图形
        // ctx.stroke();// 描边 图形
 
        // 错误的画线方法 高度为 0
        // ctx.rect(10,10,100,0);
        // ctx.stroke();
 
         //真确的画线方法先moveTo(x,y)到起始点  然后使用lineTo(x,y)到各个点,实现折线图
        ctx.moveTo(10,10);//确定起始点
 
        ctx.lineTo(200,200);//到点 1
        ctx.lineTo(200,60);//到点 2...
        ctx.lineTo(400,300);
        ctx.stroke();//描边
        // ctx.fill();//填充
 
 
    </script>
</body>
</html>

颜色的处理

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>颜色的处理</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');
        /*
            ctx.fillStyle = '颜色值|单词、十六进制、rgba'  填充颜色,默认是黑色
            ctx.strokeStyle = '颜色值|单词、十六进制、rgba'  描边颜色,默认是黑色
            一定是在填充或描边之前进行设定
         */
        // 绘制矩形
        ctx.rect(10, 10, 300, 300);
        // ctx.fillStyle = 'red';
        // ctx.fillStyle = 'rgba(0,0,255,.6)';
        ctx.fillStyle = 'rgb(0,0,255)';
        
        ctx.fill();//填充 前处理
 
        ctx.lineWidth = 5;//宽度 不带单位
        // ctx.strokeStyle = 'rgba(255,0,0,.4)';
        ctx.strokeStyle = 'red';
        /*
            bevel	创建斜角。
            round	创建圆角。
            miter	默认。创建尖角。
        */ 
       ctx.lineJoin = 'round';
 
        ctx.stroke();//描边 前处理
 
    </script>
</body>
 
</html>

线的处理-开启路径-闭合路径

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>路径 开启-闭合</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');
        /*
            在整ctx画笔对象的上下文环境中
            fillStyle、strokeStyle、文字大小等都是全局的。所以如果不开启路径,那么后面的会覆盖掉前面的。
        */ 
        // 在不开启路径的情况下 用的是公共的 是有问题的 会出现相互影响的情况
        // 总结:以后绘制这种路径图形,一定要先开启路径( 独立的空间 )
        ctx.beginPath();//开启路径 (拥有独立的空间)
        
        ctx.moveTo(100,10);
        ctx.lineTo(200,100);
        ctx.lineWidth = 5;
        ctx.strokeStyle = 'red';
        ctx.stroke();//描边
 
        ctx.beginPath();//开启路径 (拥有独立的空间)
        ctx.moveTo(200,10); //起点
        ctx.lineTo(300,100); //定义点
        ctx.lineWidth = 10; //线条的宽度
        ctx.strokeStyle = 'blue'; //描边颜色
        ctx.stroke();
 
        // 绘制三角形 没有使用闭合路径
        ctx.beginPath();//开启路径 (拥有独立的空间)
        ctx.moveTo(80,180);// 一个路径中moveTo只能使用一次
        ctx.lineTo(200,150);
        ctx.lineTo(100,80);
        
        // ctx.lineTo(80,180); //不使用闭合路径 需要手动闭合
        ctx.closePath();//闭合路径,起点和结束的会自动闭合
 
        ctx.lineWidth = 2;
        ctx.strokeStyle = 'red';
        ctx.lineJoin = 'round';
        ctx.stroke();//描边
 
    </script>
</body>
</html>

画圆-太极图案

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>圆</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');
        //arc    先描述一个路径  
        //fill  stroke
        //画圆、画圆弧
        // 参数 ( x,y,r,startAngle,endAngle ,顺|逆)  是弧度制  true 顺时针 | false 逆时针   (角度 / 180 * Math.PI)
        //200,200    r= 150
 
        // 画圆
        ctx.beginPath();//开启路径
        ctx.moveTo(200,200);//移动到圆心的位置  如果画一个360度圆不需要使用moveTo
        // ctx.arc(200,200,150,0, 360 / 180 * Math.PI);//描述一个圆弧路径
        ctx.arc(200,200,150,0, 2 * Math.PI);//描述一个圆弧路径
        // ctx.fill();//填充
        ctx.stroke();//描边
 
        // 画扇形
        ctx.beginPath();//开启路径
        ctx.moveTo(300,200);//扇形必须指定起点
        ctx.arc(300,200,150,0, Math.PI);//描述一个圆弧路径
 
        ctx.closePath();//闭合路径
 
        // ctx.fill();//填充
        ctx.stroke();//描边
 
        // 绘制椭圆 其中一种
        ctx.beginPath();
        // ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise)
        // (起点x.起点y,半径x,半径y,旋转的角度,起始角,结果角,顺时针还是逆时针)
        ctx.ellipse(200,100,100,40,0,0,Math.PI*2);
        ctx.fillStyle="#058";
        ctx.strokeStyle="#000";
        ctx.fill();
        ctx.stroke();
    </script>
</body>
 
</html>

缩放-变形-状态

缩放、位移、旋转(弧度制)、 Save和restore
这些操作,影响整个画布,也就是意味着后面的图形都会有影响

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>变形缩放-save-resrore</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');//获取画笔对象
        //ctx.beginPath()  //主要是操作属性的状态
        
        //画布的状态 scale(1,1)  translate(0,0)  rotate(0)
 
        // 缩放
        // ctx.scale(x,y) 1,1 缩小 是小数
 
        ctx.scale(.6,2);
        ctx.rect(0,0,50,50);//矩形
        ctx.fill();//填充
 
        // 旋转
        ctx.rotate( -30/180*Math.PI);
        ctx.rect(50,50,100,50);
        ctx.fill();
 
        // 移动原点 x,y  会影响所有的原点
        ctx.translate(100,100);
        ctx.rect(0,0,50,100);
        ctx.fill();
        
        // 他受到了原点的影响
        ctx.rect(0,0,90,20);
        ctx.stroke();
 
        // 解决上述问题
        ctx.save();//操作之前 把画布之前的状态保存一下
        ctx.translate(100,100);//改变原点坐标
        ctx.rect(0,0,50,50);//绘制矩形
        ctx.fill();//填充
 
        ctx.restore();//恢复状态
        ctx.rect(100,0,150,50);
        ctx.fill();
        
    </script>
</body>
</html>

线性-径向渐变

不要使用大量的渐变,需要很多色彩,而且计算机还需要计算位置。会影响性能。
当ui设计图中有渐变的素材,可以直接使用切换裁下来。然后使用drawImage

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>渐变</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');//获取画笔对象
    
        //线性渐变
        // createLinearGradient( x0,y0,x1,y1 )返回一个对象
        // addColorStop( 小数,颜色 )
 
        // let linearGradient = ctx.createLinearGradient(0,0,300,300);//对角线
        // let linearGradient = ctx.createLinearGradient(0,0,300,0); //垂直
        // 渐变过程的颜色点
        // linearGradient.addColorStop(0.3,'red');
        // linearGradient.addColorStop(0.6,'green');
        // linearGradient.addColorStop(1,'#fff');
 
        //为fillStyle设置为渐变色
        // ctx.fillStyle = linearGradient;
        // ctx.rect(0,0,300,300);
        // ctx.fill();
 
        // 径向渐变
        //ctx.createRadialGradient( x0,y0,r0,x1,y1,r1 )
        let radialGradient = ctx.createRadialGradient(100,100,10,100,100,150);
        radialGradient.addColorStop(0.2,'red');
        radialGradient.addColorStop(0.8,'green');
        radialGradient.addColorStop(1,'blue');
 
        ctx.fillStyle = radialGradient;
        ctx.rect(0,0,200,200);
        ctx.fill();
 
    </script>
</body>
</html>

阴影

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>阴影</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');//获取画笔对象
    
        // shadowOffsetX 偏移值
        // shadowOffsetY 
        // shandowColor //阴影颜色
        // shandowBlur //模糊
 
        // 第一种方式 开启路径
 
        ctx.beginPath();//1 开启路径
 
        ctx.shadowOffsetX = 10;
        ctx.shadowOffsetY = 10;
        ctx.shadowColor = 'red';
        ctx.shadowBlur = 10;
 
        ctx.rect(10,10,100,40);
        ctx.fill();//填充
 
        // 会影响到
        ctx.beginPath();
 
        ctx.rect(150,150,150,50);
        // 从设置 覆盖
        ctx.shadowOffsetX = 0;
        ctx.shadowOffsetY = 0;
        ctx.shadowBlur = 0;
 
        ctx.fill();
 
        // 第二种方式 保存状态
        ctx.save();//2 保存操作之前的状态
 
        ctx.shadowOffsetX = 10;
        ctx.shadowOffsetY = 10;
        ctx.shadowColor = 'blue';
        ctx.shadowBlur = 10;
 
        ctx.rect(140,10,100,40);
        ctx.fill();//填充
 
        // 会影响到
        ctx.restore();//恢复状态
 
        ctx.rect(340,150,150,50);
 
        ctx.fill();
 
    </script>
</body>
</html>

文本-清除画布

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文本-清除画布</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');//获取画笔对象
         /*
            fillText( 绘制的字符,x,y ) | strokeText()
            font = '字号 字体'
            textBaseline = '' 对齐方式 默认为:alphabetic  "alphabetic|top|hanging|middle|ideographic|bottom";
            textAlign = start end
        */
       ctx.font = '60px 宋体';
       ctx.textBaseline = 'top';
       ctx.fillStyle = 'blue';
       ctx.fillText('阿豪',10,0);
    //    ctx.strokeText('阿豪',10,0);
 
    // 清空给定矩形内的指定像素
    ctx.clearRect(0,0,100,40)
        
    </script>
</body>
</html>

Canvas画时钟

刻度对象( 短 60、长12 )
罗马数字( 数学: sin、cos )
时针、分针、秒针对象
圆点对象
品牌文字

绘制图片drawImage

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            padding: 0;
            margin: 0;
        }
 
        #canvas {
            border: 1px solid red;
        }
    </style>
</head>
 
<body>
    <!-- <img src="https://www.runoob.com/try/demo_source/img_the_scream.jpg" alt="t"> -->
    <canvas id="canvas" width="500" height="400">您的浏览器不支持canvas,请升级</canvas>
    <script>
        let canvas = document.getElementById('canvas');
        let ctx = canvas.getContext('2d');//获取画笔对象
        /*
            drawImage
            基础版 3个参数   把图片放置到canvas中,无需设定width、height
            尊享版 5个参数  可以指定width和height
            至尊版 9个参数  可以裁切图片,放置到canvas中同时也可以指定width和height
        */
        //图片必须加载成功以后,触发图片的onLoad事件。才可以使用drawImage方法
        //1. 使用js的Image构造函数创建一个图片对象
        let imgObj = new Image();
 
        imgObj.src = 'https://www.runoob.com/try/demo_source/img_the_scream.jpg';
        // console.log(imgObj);
        imgObj.onload = function () {
            //1 基础版 3个参数   把图片放置到canvas中,无需设定width、height
            //drawImage( img,x,y )
            ctx.drawImage(imgObj, 10, 10);//设置图片放置的位置
 
            // 2 尊享版  5个参数  可以指定width和height
            //ctx.drawImage( img,x,y,w,h )
            //放置到x30y30的位置,并且指定图片为width 100 height 150
            ctx.drawImage(imgObj,30,30,100,150);
 
            //3 至尊版  9个参数  可以裁切图片,放置到canvas中同时也可以指定width和height
            //drawImage( img,sx,sy,swidth,sheight,x,y,width,height )
            // sx,sy ,swidth,sheight 裁切的 起始位置 和 裁切大小 关系
            //x,y,width,height和放置到canvas画布上 起始位置 和 宽高大小 关系
            ctx.drawImage(imgObj,90,130,50,60,50,10,100,160)
 
        }
        
    </script>
</body>
 
</html>

运动的小方框见博客

svg

可缩放的矢量图,不会失真。使用的是xml语法 。
Canvas可以做一些游戏,但是svg不适合做游戏,svg比较适合做一些图表的项目
通过xml标签形式的语法来描述一些基本图形,矩形、线、圆、渐变

使用步骤

1. 定义svg容器。为容器指定xmlns命名空间 ;http://www.w3.org/2000/svg
2. 画图形、矩形、线、圆

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>svg基础</title>
    <style>
        .svg{
            border: 1px solid red;
            /* display: block; */
        }
    </style>
</head>
<body>
     <!-- 
        画布:
            svg,我们需要指定svg的命名空间,同时svg也有宽和高的属性
                                namespace
            rect:x,y,width,height   填充色,描边色 线宽
     -->
     <svg class="svg" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
        
        <!--rect 矩形 -->
        <!-- x y 起始点 width height 宽高 fill 填充颜色 stroke 描边颜色 rx ry:  radius( 设置圆角的半径 ) -->
         <!-- <rect x='20' y='20' width='100' height='50' fill='rgba(255,0,0,0.3)' stroke='blue' stroke-width='5' rx="5" ry="5"></rect> -->
        <!-- circle 圆心( cx,cy )圆心 r 半径 -->
        <!-- <circle id="c1" cx="100" cy="100" r="50" fill="red" stroke="blue" stroke-width="5"></circle> -->

        <!-- 椭圆 ellipse: cx cy ( 圆心 ) 半径 rx ry 水平和竖直的半径-->
        <ellipse cx='100' cy='100' rx='80' ry='40'></ellipse>

     </svg>

     <svg class="svg" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
         <!-- 画线条
            line
                x1 y1 起始点
                x2 y2 结束点
         -->
         <line x1='20' y1='20' x2='80' y2='90' stroke='blue' stroke-width='5'></line>
     </svg>

     <svg class="svg" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
         <!-- 
            polyline:
                points="x1 y1,x2 y2,x3 y3..."
                transparent 透明
         -->
         <polyline fill='transparent' stroke='black' points='30 80,60 150,120 60,150 140'></polyline>
     </svg>

     <svg class="svg" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
         <!-- 
            渐变:
                定义渐变
                <defs>:  
                    <linearGradient id="渐变的标识"> x1 y1 x2 y2 
                                                 如果 x1和x2相同  纵向
                                                 如果 y1和y2相同  水平
                                                 如果 x不同y不同  斜角
                            
                    <stop>  offset="百分比" stop-color
         -->
         <defs>
            <!-- <linearGradient id="lg_1" x1="0%" y1="0%" x2="0%" y2="100%"> -->
            <!-- <linearGradient id="lg_1" x1="0%" y1="0%" x2="100%" y2="0%"> -->
                <linearGradient id="lg_1" x1="0%" y1="0%" x2="100%" y2="100%">
                    <stop offset="0%" stop-color='red'></stop>
                    <stop offset="100%" stop-color="yellow"></stop>
                </linearGradient>
         </defs>

         <rect x='20' y='20' width='100' height='50' fill='url(#lg_1'></rect>
     </svg>

     <svg class="svg" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
         <!-- 
                径向(放射性)渐变
                    defs
                        :radialGradient ( id,cx,cy[ 圆心 :百分比 ],r[半径 :百分比] )
                            : stop ( offset="百分比" stop-color="颜色" )
             -->
             <defs>
                <radialGradient id="rg_1" cx="50%" cy="50%" r="50%">
                        <stop offset="0" stop-color="pink"></stop>
                        <stop offset="50%" stop-color="yellow"></stop>
                        <stop offset="100%" stop-color="blue"></stop>
                </radialGradient>
            </defs>

            <circle cx="100" cy="100" r="100" fill="url(#rg_1)"></circle>
     </svg>

     <svg class="svg" width="400" height="400" xmlns="http://www.w3.org/2000/svg">
         <!-- 
            文本
                text: x,y
         -->
         <text x="50" y="80" fill="red" font-size="20">HEllo World</text>
         <text x="150" y="180" stroke='blue' stroke-width='2' font-size="20">HEllo World</text>
     </svg>

     <script>
        //  svg 方便添加事件 操作DOM
        //  let c1 = document.getElementById('c1');
        //  c1.onclick = function(){
        //      console.log('ok111');
        //  }
     </script>
</body>
</html>

D3.js

基于svg的一个数据驱动框架

所需要的基础:html、css、js+ svg

对比echarts、d3和canvas、svg的区别和关系

canvas和svg不需要引入任何库和脚本 。
而echarts和d3是第3方组织人家开源出来的框架
Echarts:使用svg+canvas技术 + js封装出来的百度框架( 开源到apache协议 )
D3国外的 svg+js技术  最新是5的版本。

使用方式

1.使用cdn引入到网页中
互联网上的一个d3.js网址
<script src=”http://cdn.org/d3.min.js”></script>
2.下载下来,然后d3.js随着你的项目上传到你自己的服务器
<script src=”./d3.min.js”></script>
3.使用webpack脚手架下载d3
npm i d3@3
npm i echarts

import d3 from ‘d3’
import echarts from ‘echarts’

D3借鉴了jquery很多特性。
比如:
选择元素 select selectAll  参考css选择器 或者 jquery的选择器
元素的添加、修改、删除  append insert  remove
为元素设置属性attr
设置样式 style
datum和data方法进行元素和数据的绑定
设置比例尺
坐标轴体系

d3js基础

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>d3js基础</title>
</head>
<body>
    <p></p>
    <p></p>
    <p id="p1"></p>
    <p id="p2"></p>
    <!-- 引入d3js 对象 -->
    <script src="./d3.v3.min.js"></script>
    <script>
        console.log(d3,'d3对象');
        // 1 选择元素
        //select 选择符合的第1个元素  selectAll是选择一个结果集
        //借鉴jquery的链式风格( 只要是一个对象【jquery】d3 就能够点下去 )
        d3.selectAll('p').text('hello 全部选中');
        d3.select('#p1').text('hello world');//选择第1个p容器设置文本

        // 2 绑定数据 datum \ data
        let txt = 'hell d3';
        // let pNodes = d3.selectAll('p').datum( txt );
        let pNodes = d3.selectAll('p')
        pNodes.datum( txt );

        // pNodes.text("dyh d3");
        pNodes.text((value,index)=>{
            // console.log(value,index);
            return index + value;
        })

        let txt1 = ['dyh01','dyh02','dyh03','dyh04','dyh05'];
        let pNodes1 = d3.selectAll('p');
        pNodes1.data( txt1 ).text((value,index)=>{
            // console.log(value,index);
            return index + value;
        })

        // 3 数据多于元素对象
        let p1 = d3.select('#p1');
        p1.selectAll('p').data(txt1).enter().append('p').text((value,index)=>{
            console.log(value,index);
            return value;
        })

        // 4 添加属性 attr(attributename,value)
        d3.select('#p1').attr('dyh','自定义属性');

        // 5 追加 向父元素内进行追加 参考父级append
        //往某个元素前面 进行追加  参考父级中某个子元素 insert
        d3.select("#p1").append('h1').text("我是追加的h1标签").style('color','red');

        //选择父容器, 调用 insert( 要追加的元素, 参考哪个元素 )
        d3.select('body').insert('h1','#p1').text('我是追加到#p1前的h1').style('color','blue');

        // 6 删除 指定
        d3.select('#p1').remove();

        // 7 遍历 添加内容 自定义属性
        let txt2 = ['dd','yy','hh'];
        // d3.select('#p2').data( txt1 ).attr('a','sss')
        // d3.select('#p2').data( txt1 ).enter().append('p').attr('a',val=>{return val});

        let p = d3.select('#p2').selectAll('h1');
        p.data(txt2).enter().append('h1').text(val=>val).attr('dyh',(val,idx)=>{
            // console.log(val,idx);
            return val;
        })

        // 8 事件绑定
        d3.selectAll('p').on('click',function(){
            console.log(this,d3.select(this),'事件触发了');
            d3.select(this).style('background','red');//将this转换成d3 this
        })

    </script>

</body>
</html>

基础柱状图

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>基础柱状图</title>
</head>

<body>
    <div id="container">

    </div>

    <script src="./d3.v3.min.js"></script>
    <script>
        //定义初始化的数据
        let dataset = [100, 50, 33, 80, 110, 60]
        let width = 300 //svg的宽
        let height = 300 //svg的高

        let padding = { left: 40, right: 40, top: 40, bottom: 40 }  //距离svg四周的间距
        let rectWidth = 30
        let rectPadding = 10

        let svg = d3
            .select('#container')//选中标签
            .append('svg')//添加svg
            .attr('width', width)//设置宽高属性
            .attr('height', height)
            .style('border', '1px solid blue')

        svg.selectAll('rect')
            .data(dataset)//为rect集合绑定数据
            .enter()
            .append('rect')//绑定数据以后,还需要执行enter和append保证集合对象和数据统一
            .attr('width', rectWidth)
            .attr('height', (value, index) => {
                return value
            })
            .attr('x', (value, index) => {
                //console.log(value,index)
                //console.log( index * ( rectWidth + rectPadding ) )
                return index * (rectWidth + rectPadding)
            })
            .attr('y', (value, index) => {
                return height - value
            })
            .on('mouseover', function () {
                d3.select(this).attr('fill', 'red')
            })
            .on('mouseout', function () {
                d3.select(this).attr('fill', 'black')
            })

    </script>
</body>

</html>

比例尺

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>比例尺</title>
</head>
<body>
    <script src="./d3.v3.min.js"></script>
    <script>
        // 线性比例尺( 竖直方向 ) | 序数比例尺 (水平方向)
        //1. 线性比例尺
            let dataset = [ 0.5, 3, 0.1, 1.2, 4, 2.5 ]
            //要让数据0.1——4  ——>   0,300的区间      
            var min = d3.min( dataset )//最小值  0.1
            var max = d3.max( dataset )//最大值  4

            //得到一个线性比例尺
            let linear = d3
                    .scale
                    .linear() //线性比例尺
                    .domain([ min,max ]) //定义区间   x 当x得到 => y的值也就取出来了
                    .range([0,300]) //取值
       
            //console.log( linear )
            console.log( linear( 0.1 ) )
            console.log( linear( 3 ) )
            console.log( linear( 4 ) )//300
        
        console.log('-------------------------------------')

        //2. 序数比例尺
        let course = [ '语文','数学','英语','政治','历史' ]
                //投放到0,300的区间中
        
            //ordinal() 序数比例尺
          let ordinal = d3
                        .scale
                        .ordinal()
                        .domain( course )  //定义区间   x 当x得到 => y的值也就取出来了
                        .rangeRoundBands( [0,400] )//取值
                
                console.log( ordinal,'11111' )

                console.log( ordinal('语文') )
                console.log( ordinal('数学') )
                console.log( ordinal('英语') )
                console.log( ordinal('政治') )
                console.log( ordinal('历史') )

                console.log( ordinal.rangeBand() )  //ordinal.rangeBand() 可以理解为300平分数据个数的值

    </script>
</body>
</html>

坐标系

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>坐标系</title>
</head>

<body>
    <div id="container"></div>

    <script src="./d3.v3.min.js"></script>
    <script>
        let dataset = [0.5, 3, 0.1, 1.2, 4, 2.5]

        let width = 300
        let height = 300

        //d3.svg.axis 创建坐标系 

        let svg = d3
            .select('#container')
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .style('border', '1px solid red')

        //创建线性比例尺
        let linear = d3.scale.linear()   //擅长做竖直方向 上坐标系 
            .domain([0, d3.max(dataset)])
            .range([300, 0])

        //定义坐标系
        let axis = d3.svg.axis()
            .scale(linear)//指定比例尺
            .orient('left') //指定坐标系刻度的方向
            .ticks(5) //指定刻度的数量

        //追加坐标系
        svg.append('g')// group 组的意思
            .attr('class', 'axis_a')
            .attr('transform', 'translate(50,0)')
            .call(axis)

    </script>
    <style>
        .axis_a line,
        .axis_a path {
            fill: transparent;
            stroke: black
        }
    </style>
</body>

</html>

柱状图-坐标系

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>柱状图-坐标系</title>
    <style>
        .xAxis_a path,
        .yAxis_a path,
		.yAxis_a line{
            fill: none;
            ;
            stroke: black;
            /* stroke-width: 1 */
        }

        .tick text {
            font-size: 12px;
        }
    </style>
</head>

<body>

    <div id="container"></div>

    <script src="./d3.v3.min.js"></script>
    <script>
        //定义初始化的数据

        let dataset = [100, 50, 33, 80, 110, 60]
        let course = ['语文', '数学', '英语', '政治', '历史', '化学']
        let width = 300 //svg的宽
        let height = 300 //svg的高

        let padding = { left: 40, right: 40, top: 40, bottom: 40 }  //距离svg四周的间距

        let rectWidth = 30
        let rectPadding = 4 //矩形与矩形之间的距离

        //x轴的比例尺
        let xScale = d3.scale.ordinal()
            .domain(course)
            .rangeRoundBands([0, width - padding.left - padding.right]) //留出两边距离

        //y轴的比例尺   
        let yScale = d3.scale.linear()
            .domain([0, d3.max(dataset)])
            .range([height - padding.top - padding.bottom, 0])

        let svg = d3
            .select('#container')
            .append('svg')
            .attr('width', width)
            .attr('height', height)
            .style('border', '1px solid blue')

        svg.selectAll('rect')
            .data(dataset)//为rect集合绑定数据
            .enter()
            .append('rect')//绑定数据以后,还需要执行enter和append保证集合对象和数据统一
            .attr('width', rectWidth)
            .attr('height', (value, index) => {
                //console.log( yScale(value),'1111' )
                //return value
                return height - padding.top - padding.bottom - yScale(value)
            })
            .attr('x', (value, index) => {
                //console.log(value,index)
                //console.log( xScale(course[index]) )
                return xScale(course[index]) + rectPadding
            })
            .attr('transform', 'translate( ' + padding.left + ',' + padding.top + ' )')
            .attr('y', (value, index) => {
                return yScale(value)
            })
            .on('mouseover', function () {
                d3.select(this).attr('fill', 'red')
            })
            .on('mouseout', function () {
                d3.select(this).attr('fill', 'black')
            })

        //x坐标体恤
        let xAxis = d3.svg.axis()
            .scale(xScale)
            .orient('bottom')

        //y坐标系
        let yAxis = d3.svg.axis()
            .scale(yScale)
            .orient('left')

        svg.append('g')
            .attr('class', 'xAxis_a')
            .attr('transform', 'translate(' + padding.left + ',' + (height - padding.bottom) + ')')
            .call(xAxis)

        svg.append('g')
            .attr('class', 'yAxis_a')
            .attr('transform', 'translate(' + padding.left + ',' + padding.top + ')')
            .call(yAxis)

    </script>
</body>

</html>

 

常用的柱形图见博客

 

posted @ 2023-06-08 23:25  JackieDYH  阅读(28)  评论(0编辑  收藏  举报  来源