七、(1)报表原理+D3+Echarts

报表原理+D3+Echarts

Canvas简介

  • canvas是一个矩形区域的画布,可以用JS控制每一个像素在上面绘画。
  • canvas 标签使用 JavaScript 在网页上绘制图像,本身不具备绘图功能。
  • canvas 拥有多种绘制路径、矩形、圆形、字符以及添加图像的方法。

Canvas绘图入门

canvas标签语法和属性

  • canvas:画布油布的意思 英 ['kænvəs] 美 ['kænvəs]
  • 标签名:canvas,双标签,需要闭合。
  • 单位: px,可以设置width和height属性,否则忽略单位。
  • width和hegiht:默认300*150像素

canvas中的属性

设置样式(颜色)
  fillStyle   填充颜色设置
  strokeStyle   设置笔触的颜色
  lineWidth   设置 线条宽度

矩形

  rect(x,y,w,h)    创建矩形
  fillRect(x,y,w,h)    绘制填充矩形
  strokeRect(x,y,w,h)   绘制描边矩形

路径属性

  fill()    填充
  stroke()   绘制 定义好的路径
  beginPath()   起始路径
  moveTo()   把笔移动到指定点
  lineTo()   绘制从起点到终点的线
  closePath()   闭合路径

基本的绘制路径

canvas坐标系

canvas坐标系,从最左上角0,0开始。x向右增大, y向下增大

设置绘制起点(moveTo)

  • * 语法:ctx.moveTo(x, y);
  • * 解释:设置上下文绘制路径的起点。相当于移动画笔到某个位置
  • * 参数:x,y 都是相对于 canvas盒子的最左上角。
  • * 注意:**绘制线段前必须先设置起点,不然绘制无效。

绘制直线(lineTo)

  • * 语法:ctx.lineTo(x, y);
  • * 解释:从x,y的位置绘制一条直线到起点或者上一个线头点。
  • * 参数:x,y 线头点坐标。

路径开始和闭合

  • * 开始路径:ctx.beginPath();
  • * 闭合路径:ctx.closePath();
  • * 解释:如果复杂路径绘制,必须使用路径开始和结束。闭合路径会自动把最后的线头和开始的线头连在一起。
  • * beginPath: 核心的作用是将 不同绘制的形状进行隔离,每次执行此方法,表示重新绘制一个路径,跟之前的绘制的墨迹可以进行分开样式设置和管理。

描边(stroke)

  • * 语法:ctx.stroke();
  • * 解释:根据路径绘制线。路径只是草稿,真正绘制线必须执行stroke
  • * stroke: (用笔等)画;轻抚;轻挪;敲击;划尾桨;划掉;(打字时)击打键盘

canvas绘制的基本步骤:

  • 第一步:获得上下文 =>canvasElem.getContext('2d');
  • 第二步:开始路径规划 =>ctx.beginPath()
  • 第三步:移动起始点 =>ctx.moveTo(x, y)
  • 第四步:绘制(点、线、面、图片...) =>ctx.lineTo(x, y)
  • 第五步:闭合路径 =>ctx.closePath();
  • 第六步:绘制描边 =>ctx.stroke();
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #my-canvas{
            width: 600px;
            height: 400px;
            border: #ff6600 2px solid;
        }
    </style>
</head>
<body>
<div>
    <canvas id="my-canvas" width="600" height="400"></canvas>
</div>

<script>
    let byId = document.getElementById("my-canvas");
    //方式一
    let ctxt = byId.getContext("2d");
    // ctxt.rect(100,100,200,100);//x y w h
    ctxt.fillStyle="red";//填充颜色
    ctxt.fill();//颜色填充
    ctxt.stroke();

    //方式二
    //填充矩形
    // ctxt.fillRect(100,100,300,200);
    //描边矩形
    ctxt.strokeRect(100,100,300,200);
</script>

实例1: 直线绘制

cx.strokeStyle="red";//画笔的颜色
cx.lineWidth=2;//线框
cx.moveTo(500,500); //设置线条的起始位置
cx.lineTo(100, 100); //给路径一个终点
cx.stroke();//开始绘制

<script type="text/javascript">
//1. 找到画布
var mycan=document.getElementById("mycan");
//2. 设置绘图方式
var ct=mycan.getContext("2d");

//3. 画直线
//3-1. 线条颜色
ct.strokeStyle="red";
//3-2. 线条宽度
ct.lineWidth=5;
//3-3. 提笔的起点
ct.moveTo(50,50);
//3-4. 提笔的终点
ct.lineTo(550,550);
//3-5. 执行绘画
ct.stroke();
</script>

实例2:绘制三角形

    <style>
        #my-canvas{
            width: 600px;
            height: 400px;
            border: #ff6600 2px solid;
        }
    </style>
</head>
<body>
<div>
    <canvas id="my-canvas" width="600" height="400"></canvas>
</div>

<script>
    //获取元素
    let id = document.getElementById("my-canvas");
    let ctext = id.getContext("2d");

    ctext.lineWidth=3;//设置线条宽度
    ctext.strokeStyle="green";//设置线条颜色

    ctext.moveTo(0,0);//移动触笔
    ctext.lineTo(300,200);//起始位置

    ctext.moveTo(600,0);//移动触笔
    ctext.lineTo(0,400);//起始位置
    ctext.stroke();

    //绘制三角形
    ctext.beginPath();//重置路径
    ctext.strokeStyle="red";
    ctext.moveTo(200,300);
    ctext.lineTo(400,300);

    ctext.moveTo(300,100);
    ctext.lineTo(200,300);

    ctext.moveTo(300,100);
    ctext.lineTo(400,300);

    ctext.stroke();

    // 闭合路径
    ctext.beginPath();//重置路径
    ctext.strokeStyle="#00f";
    ctext.moveTo(100,10);
    ctext.lineTo(10,100);
    ctext.lineTo(200,100);
    ctext.closePath();//闭合路径
    ctext.stroke();
</script>

填充(fill)

  • * 语法:ctx.fill();
  • * 解释:填充,是将闭合的路径的内容填充具体的颜色。默认黑色。
  • * 注意:交叉路径的填充问题,“非零环绕原则”,顺逆时针穿插次数决定是否填充。

绘制描边后执行填充颜色:

ctx.fillStyle="cornflowerblue";
ctx.fill();

快速创建矩形rect()方法

  • * 语法:ctx.rect(x, y, width, height);
  • * 解释:x, y是矩形左上角坐标, width和height都是以像素计
  • * rect方法只是规划了矩形的路径,并没有填充和描边。
  • * 改造案例:04填充矩形.html
  • *rect: abbr. 矩形(rectangular);收据(receipt)
//开始绘制矩形
ctx.beginPath();
ctx.rect(100,100,400,300);

//填充颜色
ctx.fillStyle="cornflowerblue";
ctx.fill();

//描边颜色
ctx.strokeStyle="blue";
ctx.lineWidth=5;
ctx.stroke();

快速创建描边矩形和填充矩形

  • * 语法: ctx.strokeRect(x, y, width, height);
  • - 参数跟rect相同,注意此方法绘制完路径后立即进行stroke绘制
  • * 语法:ctx.fillRect(x, y, width, height);
  • - 参数跟rect相同, 此方法执行完成后。立即对当前矩形进行fill填充。

实例3:坐标绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #my-canvas {
            width: 600px;
            height: 400px;
            border: #ccc 1px solid;
        }
    </style>
</head>
<body>
<div>
    <canvas id="my-canvas" width="600" height="400"></canvas>
</div>

<script>
    let id = document.getElementById("my-canvas");
    let ctext = id.getContext("2d");
    const step = 10, w = id.width, h = id.height;
    ctext.strokeStyle = "#ccc";
    //横线
    for (let i = 1; i < h / step; i++) {
        ctext.moveTo(0, 10 * i);
        ctext.lineTo(600, 10 * i);
        ctext.stroke();
    }
    //循环绘制竖线
    for (let i = 1; i < w / step; i++) {
        ctext.moveTo(10 * i, 0);
        ctext.lineTo(10 * i, 400);
        ctext.stroke();
    }
    //定义常量
    const x0=30,y0=350,jw=20,ml=20,d=40;
   // 绘制y轴坐标
    ctext.beginPath();
    ctext.strokeStyle="red";
    ctext.moveTo(x0,y0);
    ctext.lineTo(x0,y0-300);
    ctext.lineTo(x0-step,y0-300+step);

    ctext.moveTo(x0,y0-300);
    ctext.lineTo(x0+step,y0-300+step);
    ctext.stroke();
    //绘制x轴
    ctext.beginPath();
    ctext.strokeStyle="red";
    ctext.moveTo(x0,y0);
    ctext.lineTo(w-x0,y0);
    ctext.lineTo(w-x0-step,y0-step);

    ctext.moveTo(w-x0,y0);
    ctext.lineTo(w-x0-step,y0+step);

    let arrs=[60,120,50,700,200,280];
    let colors=["red","blue","yellow","pink","green","deeppink"];

    //定义变量,存放最大值
    let max=arrs[0];
    arrs.forEach(function (value) {
        if (max<value){
            max=value;
        }
    });
    let s=300/max;//得到系数
    for (let i=0;i<arrs.length;i++){
        ctext.fillStyle=colors[i];
        ctext.fillRect(x0+ml+d*i,y0-1,jw,-arrs[i]*s);
    }
    ctext.stroke();
</script>
</body>
</html>

 

效果图:

进阶绘制

绘制文字

1. 绘制上下文的文字属性

  • font 设置或返回文本内容的当前字体属性
  • font 属性使用的语法与 CSS font 属性相同。

例如:ctx.font = "18px '微软雅黑'";

  • textAlign 设置或返回文本内容的当前对齐方式
  • start : 默认。文本在指定的位置开始。
  • end : 文本在指定的位置结束。
  • center: 文本的中心被放置在指定的位置。
  • left : 文本左对齐。
  • right : 文本右对齐。
  • top : 文本基线是 em 方框的顶端。
  • bottom : 文本基线是 em 方框的底端。

例如:ctx.textAlign = center|end|left|right|start'; ```

2. 上下文绘制文字方法

  • * ctx.fillText(文字,x坐标,y坐标) 在画布上绘制“实心”文本
  • * ctx.strokeText(文字,x坐标,y坐标) 在画布上绘制“空心”文本

D3简单入门

1. 选择集

  • d3.select(selector) 选中与指定选择器字符串匹配的第一个元素
  • d3.selectAll(selector) 选中匹配指定选择器的所有的元素

2. 数据绑定

selection.data([values[, key]]) 连接指定的一组数据的和当前选择。指定的values是一组数据值(例如,数字或对象)或一个函数返回一组值。
如果没有指定key函数,则values的第一数据被分配到当前选择中第一元素,第二数据分配给当前选择的第二个元素,依此类推。

  • undate --update数据个数等于DOM元素个数
  • enter --enter数据个数大于DOM元素个数,数据多出的数组元素部分就是enter
  • exit --exit数据个数小于DOM元素个数,dom多出的dom部分就是exit

3. DOM操作

selection.attr(name[, value]) 选中的元素通过指定的name为指定的value设置属性,name也可以是一个name和value属性对象

  • selection.append(name) 当前选择的每个元素最后追加具有指定名称的新元素
  • selection.insert(name[, before]) 当前选择与指定before选择器匹配的每个元素之前插入具有指定name的新元素

4. 远程加载数据,封装了ajax

d3.json(url[, callback]) 指定的url创建一个JSON文件请求其mime type为"application/json"。
如果指定了回调函数callback,请求将通过GET方法立即分发,当文件被加载或者请求失败之后回调函数将被异步调用。

d3.json("./dataDemo.json",(err,root)=>{
console.log("rootJSON",root);
//获取节点数组
let nodes=tree.nodes(root);
//获取连线数组
let links=tree.links(nodes);
});

绘图

d3是基于svg和canvas绘图的,基本元素绘制如下:
矩形    rect
圆形    circle
椭圆形   ellipse
线段    line
折线    ployline
多边形   polygon
路径    path
文字    text

树状图

树形绘图api

d3.layout.tree()   创建树形
tree.size([])    设置树形的宽高
tree.sparation()   设置节点之间的间隔
tree.nodes(root)   根据root开始计算获取节点数组
tree.links(nodes)  根据nodes开始计算获取连线数组

节点对象nodes

parent:   父节点
children:   子节点
depth:   节点深度
x:   节点x坐标
y:   节点y坐标

连线对象links

source:   前端节点(前面源)
target:   后端节点(后面目标)

6.5. 事件绑定:使用on给节点绑定事件句柄函数

function nodeClick() {
d3.select(this).transition().attr('r', 8)
}
node.append("circle")
.attr("r",4.5)
.attr('fill', 'white')
.on('click', nodeClick)

6.6. 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>Document</title>
<style>
.node circle{
fill:#fff;
stroke:steelblue;
stroke-width: 1.5px;
}
.node{
font: 12px sans-serif;
}
.link{
fill:none;
stroke:#ccc;
stroke-width: 1.5px;
}
</style>
<script src="./d3Library/d3.v3.js"></script>
</head>
<body>
<script>
var width = 500,
height = 500;

//定义数据转换函数
var tree = d3.layout.tree()
.size([width,height-200])
//定义对角线生成器diagonal
var diagonal = d3.svg.diagonal()
.projection(function(d){return [d.y, d.x]})

//定义svg
var svg = d3.select("body").append("svg")
.attr("width",width)
.attr("height",height)
.append("g")
.attr("transform","translate(40,0)")

//读取json文件,进行绘图
d3.json("./03city.json",function(erro,root){
var nodes = tree.nodes(root);
var links = tree.links(nodes);

//画点
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class","node")
.attr("transform",function(d){return "translate("+ d.y+","+ d.x+")"})
//加圈圈
node.append("circle")
.attr("r",4.5)
.attr('fill', 'white')
.on('click', nodeClick) //注册单击事件

//加文字
node.append("text")
.attr("dx",function(d){return d.children?-8:8;})
.attr("dy",3)
.style("text-anchor", function (d) {return d.children?"end":"start"})
.text(function (d) {return d.name})

//画线
var line = svg.selectAll("link")
.data(links)
.enter()
.append("path")
.attr("class","link")
.attr("d",diagonal)

//单击事件句柄函数
function nodeClick() {
d3.select(this).transition().attr('r', 8).attr('fill', '#f30')
}
})
</script>
</body>
</html>

Echarts报表组件

案例1:echarts使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/echarts.js"></script>
</head>
<body>
<div id="my-echarts" style="width: 600px;height: 400px"></div>
<script>
    //获取实例
    let myecharts = echarts.init(document.getElementById("my-echarts"));
    let option = {
        title: {
            text: "个人报表",
            show: true,
            textStyle:{
                color:"red"
            }
        },
        tooltip: {},
        legend: {
            data:['销量']
        },
        xAxis: {
            data: ["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]
        },
        yAxis:{},
        series:[{
            name:"销量",
            type:"bar",
            data:[20,30,10,5,15,20]
        }]
    };
    myecharts.setOption(option);
</script>
</body>
</html>
posted @ 2021-06-09 13:43  全村的希望、  阅读(210)  评论(0编辑  收藏  举报