canvas

简单说明

  1. canvas是html5的一个标签,代表一个画布,可以在上面进行绘画、动画等操作。画布默认大小是300*150。
  2. canvas标签本省只是画布,要实现上面有文字、线条等呈现,需要使用js实现。总之,画布上一切的呈现,都需要使用js来实现。canvas标签本质上就是一张图片,只是一张空白图片。
  3. 创建好的画布,要在上面进行绘画,需要使用js,用js操作canvas标签的 - canvas技术
  4. canvas标签,需要将画布调整大小的时候,加样式只是能改变视觉效果,真实的画布大小并没有改变,只是将画布的图片等比例放大了而已
  5. 调整画布大小,需要设置canvas标签的width属性和height属性
  6. canvas标签是一个双标签,在canvas标签中是不能放内容的,放了也没有用,只有当浏览器不支持canvas标签的时候,内部的内容才会显示
  7. 画布大小不能使用样式控制,用样式调整的是一个可视区域,其实真实的大小,还是一样的,只是在画布上画内容的话,会等比例放大。调整画布大小,需要在标签上直接添加width和height属性。
  8. canvas标签也是可以放文字的,只是当canvas标签不被浏览器支持的时候,会显示,例如ie8。

canvas的简单使用:

  1. 获取canvas元素

    var canvas = document.querySelector('canvas')
    
  2. 获取这个元素的工具箱 - 上下文

工具箱中包含了很多工具:直线工具、弧形工具、文本工具、矩形工具… 我们需要依赖这些工具进行绘画
canvas提供了一个工具箱 - canvas.getContext() - 获取工具箱

语法:

var ctx = canvas.getContext('2d')
canvas现在没有3d的,所有3d效果都是2d模拟出来的 - 要有一个固定的参数 '2d' - 默认返回工具箱

画直线

设置线条的宽度 - 工具箱.lineWidth = 值
值是不需要设置px单位的,默认是px,设置的是一个数字

ctx.lineWidth = 2

先将画笔放到画布上 - 工具箱.moveTo(x轴的坐标,y轴的坐标)

ctx.moveTo(100,100)

通过直线移动画笔 - 选择直线工具,并移动画笔到执行的位置 - 工具箱.lineTo(x轴的坐标,y轴的坐标)

ctx.lineTo(200,100)

默认不显示线,理解成他默认是白色的,需要让他显示出来
描边 - 工具箱.stroke() - 描边默认使用黑色,默认描边使用1px

ctx.stroke()

但是我们看到的线条,既不是1px的,也不是黑色的?
因为,canvas将线条,拉伸了,其实这个线就是2px的,拉伸以后,颜色就被稀释了,所以看起来没有那么黑
拉伸是因为浏览器不识别0.5的边框,设置2px的线条宽度,就不会被拉伸

所以我们在画布中设置线条的时候,尽量设置双数,不被拉伸,单数会被拉伸

基于这个问题,我们以后在绘图的时候,尽量将像素设置为双数。


使用

画多条线:

可以在一个画布中画多条线,但是直接将画笔以线的形式移动到一个位置的时候,是从前面的结束位置,到新的位置画了一条新的线,所以我们需要重新将画笔移动到第二条线的开始位置,然后再以线的形式移动画笔,再次描边。

但是在描第二条边的时候,会再次描第一条边,所以多次描边,前面的线的颜色会越来越深。

我们通常在绘制的时候,会等所有图案绘制结束之后,描一次边,不会描多次。

如果要设置描边的颜色,可以在描边之前设置描边的颜色:

ctx.strockStyle = '颜色值';

问题:如何给多条线设置不同的宽度和颜色?因为我们在最后描边的时候,发现所有线都是同一个颜色,哪怕给每条线都进行描边,也是一样的结果,说明每条线之间有很大的关联,canvas默认会从上下文上继承颜色和宽度。

我们需要在每次开始绘制的时候,告诉canvas下次的绘制是重新设置,跟上面的没有关系:

ctx.beginPath()

步骤:

  1. 获取canvas元素
var canvas = document.querySelector('canvas')
  1. 获取工具箱
var ctx = canvas.getContext('2d')
  1. 设置线条的宽度
ctx.lineWidth = 10
  1. 把画笔放到画布上
ctx.moveTo(100,100)
  1. 使用直线工具移动画笔
ctx.lineTo(200,100)
  1. 描边
ctx.stroke()
  1. 重新开启一个路径 - 工具箱.beginPath()
ctx.beginPath()
  1. 设置线条的宽度20
ctx.lineWidth = 20
  1. 再画一条线
ctx.moveTo(100,200)
ctx.lineTo(200,200)
ctx.stroke()

此时,上面的线比下面的线颜色要深,因为上面的线被描了两次边

效果:

画三角形:

三条线回到起点,就是三角形,但是线的结尾和开头部分,进行闭合的时候,其实是缺一个角的。

闭合:

  1. 手动闭合,再次画一次开始的线段

  2. 自动闭合 - 需要在描边之前闭合

    ctx.closePath() // 会自动将开始和结束的边进行闭合
    
  3. 依靠填充的方式闭合:

    ctx.fill() // 填充颜色默认是黑色
    

描边和填充可以一起使用,也可以单独使用,但是都有各自的规则:

描边会把填充的内容扩大

描边的颜色默认是黑色,使用ctx.strokeStyle来设置描边颜色

填充的颜色默认是黑色,使用ctx.fillStyle来设置填充颜色

步骤:

  1. 获取canvas元素
var canvas = document.querySelector('canvas')
  1. 获取工具箱
var ctx = canvas.getContext('2d')
  1. 设置一个线条宽度
ctx.lineWidth = 20
  1. 画三角形需要三条线
ctx.beginPath()
ctx.moveTo(100,100)
ctx.lineTo(200,100)
  1. 第二条
ctx.lineTo(200,200)
  1. 填充
ctx.fill()

效果:

画填充回形:

需求:

大正方形:200 * 200;小正方形:100 * 100;出现在画布的最中心;线宽2;

获取画布的宽度和高度:

ctx.canvas.width
ctx.canvas.height

通过线段描边,得到两个正方形,填充规则 - 非零填充规则:

在任何一个填充的区域,向外(到外围canvas的区域)拉一条线,数数经过了几个顺时针和逆时针进行计算:

顺时针+1,逆时针-1

最后得到的数字不是0,就填充;是0,就不填充

步骤:

  1. 获取canvas元素,获取工具箱
var canvas = document.querySelector('canvas')var ctx = canvas.getContext('2d')
  1. 画大正方形
ctx.beginPath()
ctx.moveTo(50,50)
ctx.lineTo(250,50)
ctx.lineTo(250,250)
ctx.lineTo(50,250)
ctx.lineTo(50,50)
  1. 画小正方形
ctx.moveTo(100,100)
ctx.lineTo(100,200)
ctx.lineTo(200,200)
ctx.lineTo(200,100)
ctx.lineTo(100,100)
  1. 描边,填充
ctx.stroke()ctx.fill()

效果:

canvas进行填充的时候,有一个非零填充规则:

我们要填充的时候,可以给每一个要填充的区域开始向外拉一条线 - 计算
这条线一直到画布的最大范围
计算这条线经过的形状的边
每经过一个边,就计算这个边画的时候是使用顺时针画的,还是逆时针画的
最初始拿0计算,经过顺时针+1,经过逆时针的边-1
最后计算得出的结果是0或者不是0
如果不是0的区域就填充,如果是0的区域就不填充

线段两端的样式:

butt - 默认是没有 - 不会超出线段区域
round - 原型,会超出线段区域
square - 矩形形状,会超出线段区域

ctx.lineCap = 值;
// 获取canvas元素var canvas = document.querySelector('canvas')// 获取工具箱var ctx = canvas.getContext('2d')ctx.lineWidth = 20ctx.beginPath()ctx.moveTo(100, 50)ctx.lineTo(200, 50)// 线两端样式 - 工具箱.lineCap = 值// ctx.lineCap = 'butt'; // 默认值,表示没有帽子ctx.lineCap = 'round'; // 圆形的帽子,会加长线ctx.lineCap = 'square'; // 圆形的帽子,会加长线ctx.stroke()

圆形:

默认:

线段和线段交接处的样式:

miter - 默认
round - 圆弧形状
bevel - 平角形状

ctx.lineJoin = 值;
// 获取canvas元素
var canvas = document.querySelector('canvas')
// 获取工具箱
var ctx = canvas.getContext('2d')ctx.lineWidth = 20
ctx.moveTo(50,30)
ctx.lineTo(150,100)
ctx.lineTo(250,30)// ctx.lineJoin - 设置两条线连接的地方的样式
// ctx.lineJoin = 'miter' // 默认是两条线的角度的连接点
// ctx.lineJoin = 'round' // 两条线在连接的时候使用圆形连接
ctx.lineJoin = 'bevel' // 使用平角进行连接ctx.stroke()

默认是两条线的角度的连接点:

两条线在连接的时候使用圆形连接:

使用平角进行连接:

画虚线:

需要在绘制线条之前,设置线条的样式为虚线:

数组 - 虚线方案,在数组中描述线条和空白的长度,然后不停的重复
两个值,第一个值是线条长度,第二个值是空白长度 - 重复
三个值,第一个值是线条长度,第二个值空白长度,第三个值是线条的长度;接下来是第二个值的空白长度,第二个值是线条的长度,第三个值是空白的长度 - 重复
四个值,第一个值是线条长度,第二个值是空白长度,第三个值是线条的长度,第四个值是空白长度 - 重复
ctx.setLineDash(参数);

获取虚线的方案:

ctx.getLineDash()
// 获取到的是一个数组,数组中记录了一段不重复的虚线方案

总结:
数组中有奇数个元素,那重复的个数就是 2*奇数个
数组中有偶数个元素,那重复的个数就是偶数个
步骤:

  1. 获取canvas元素,获取工具箱
var canvas = document.querySelector('canvas')
// 获取工具箱
var ctx = canvas.getContext('2d')
  1. 设置虚线方案
ctx.setLineDash([5,10,15])
  1. 4个值,实线、空白、实线、空白 - 重复
ctx.lineWidth = 10
ctx.moveTo(100,100)
ctx.lineTo(500,100)ctx.stroke()

效果:

利用循环画纯色渐变的线条:

ctx.lineWidth = 10
for(var i=0;i<256;i++){ctx.beginPath()ctx.moveTo(100+i,100)ctx.lineTo(100+i+1,100)ctx.strokeStyle = `rgb(255,${255-i},${255-i})`ctx.closePath()ctx.stroke()
}

画折线图

html

<style>canvas{border:1px solid #000;}
</style>
<canvas width=600 height=300></canvas>

js

var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
// 画点的函数
function setPoint(pointData){ctx.beginPath()ctx.moveTo(pointData.x - 5,pointData.y - 5)ctx.lineTo(pointData.x - 5,pointData.y + 5)ctx.lineTo(pointData.x + 5,pointData.y + 5)ctx.lineTo(pointData.x + 5,pointData.y - 5)ctx.stroke()ctx.fill()
}
// 画多个点的函数
function setPoints(pointsData){pointsData.forEach(v=>{setPoint(v)})
}
var pointsData = [{x:20,y:280},{x:120,y:180},{x:220,y:160},{x:320,y:50},{x:420,y:105}
]
setPoints(pointsData)
// 画坐标轴
var space = 20;
var width = ctx.canvas.width
var height = ctx.canvas.height
// x轴
function setAxiosX(){var pointX = space;var pointY = height - space;var endX = space;var endY = space;ctx.beginPath()ctx.moveTo(pointX,pointY)ctx.lineTo(endX,endY)// 画箭头ctx.lineTo(endX-5,endY+10)ctx.lineTo(endX+5,endY+10)ctx.lineTo(endX,endY)ctx.stroke()ctx.fill()
}
setAxiosX()
// y轴
function setAxiosY(){var pointX = space;var pointY = height - space;var endX = width-space;var endY = height - space;ctx.beginPath()ctx.moveTo(pointX,pointY)ctx.lineTo(endX,endY)// 画箭头ctx.lineTo(endX-10,endY-5)ctx.lineTo(endX-10,endY+5)ctx.lineTo(endX,endY)ctx.stroke()ctx.fill()
}
setAxiosY()// 点连线
function connectPoints(pointsData){for(var i=0;i<pointsData.length-1;i++){ctx.moveTo(pointsData[i].x,pointsData[i].y)ctx.lineTo(pointsData[i+1].x,pointsData[i+1].y)ctx.stroke()}
}
connectPoints(pointsData)

面向对象封装折线图:

class LineChart{constructor(classname,data){// 画布标签获取到this.canvas = document.querySelector('.'+classname)// 工具箱this.ctx = this.canvas.getContext('2d')// 定义画布大小this.canvasWidth = this.ctx.canvas.widththis.canvasHeight = this.ctx.canvas.height// 定义坐标轴到画布边缘的间隙this.space = 20// 定义原点this.originX = 0this.originY = 0// 定义箭头三角形的高 和 点 的长度this.length = 10// 将数据绑定成类的属性this.data = data// 定义画布中的数据this.canvasData = null;}// 定义一个初始化方法init(){// 获取原点this.getOrigin()// 创建坐标轴 - x、ythis.createAxisX()this.createAxisY()// 转换数据this.convert(this.data)// 描每个点// this.setPoint(data)// 描所有点this.setPoints(this.canvasData)// 连线this.connectLine(this.canvasData)}connectLine(data){for(let i=0;i<data.length-1;i++){this.ctx.beginPath()// 放画笔this.ctx.moveTo(data[i].x,data[i].y)// 画线this.ctx.lineTo(data[i+1].x,data[i+1].y)this.ctx.closePath()this.ctx.stroke()}}// 描所有点的方法setPoints(data){data.forEach(point=>{this.setPoint(point)})}// 描一个点的方法setPoint(data){this.ctx.beginPath()// 放画笔位置this.ctx.moveTo(data.x-this.length/2,data.y-this.length/2)// 画线this.ctx.lineTo(data.x+this.length/2,data.y-this.length/2)this.ctx.lineTo(data.x+this.length/2,data.y+this.length/2)this.ctx.lineTo(data.x-this.length/2,data.y+this.length/2)this.ctx.lineTo(data.x-this.length/2,data.y-this.length/2)this.ctx.closePath()this.ctx.stroke()this.ctx.fill()}// 转换数据的方法convert(){// 将坐标轴的数据转成画布的数据// 遍历数据this.canvasData = this.data.map(point=>{return {x:point.x+this.space,y:this.canvasHeight - this.space - point.y}})}// 创建y轴createAxisY(){this.ctx.beginPath()// 将画笔放到原点this.ctx.moveTo(this.originX,this.originY)// 画线this.ctx.lineTo(this.originX,this.space)// 画箭头this.ctx.lineTo(this.originX-this.length/2,this.space + this.length)this.ctx.lineTo(this.originX+this.length/2,this.space + this.length)this.ctx.lineTo(this.originX,this.space)this.ctx.closePath()this.ctx.stroke()this.ctx.fill()}// 获取原点的方法getOrigin(){this.originX = this.space;this.originY = this.canvasHeight - this.space}// 定义创建x坐标轴的方法createAxisX(){this.ctx.beginPath()// 将画笔放到原点this.ctx.moveTo(this.originX,this.originY)// 画线this.ctx.lineTo(this.canvasWidth - this.space,this.originY)// 画箭头this.ctx.lineTo(this.canvasWidth-this.space-this.length,this.originY-this.length/2)this.ctx.lineTo(this.canvasWidth-this.space-this.length,this.originY+this.length/2)this.ctx.lineTo(this.canvasWidth - this.space,this.originY)this.ctx.closePath()this.ctx.stroke()this.ctx.fill()}
}var lc = new LineChart('linechart',[{x:0,y:0},{x:100,y:100},{x:200,y:120},{x:300,y:220},{x:400,y:150},])
console.log(lc);
lc.init()

画矩形:

矩形需要设置起点和矩形的宽和高:

ctx.rect(起点x,起点y,宽,高)

然后进行描边或填充。

直接进行绘制矩形并描边:

ctx.strokeRect(起点x,起点y,宽,高)

直接绘制矩形并填充:

ctx.fillRect(起点x,起点y,宽,高)

当进行多个矩形填充不同颜色的时候,不需要结束路径,因为绘制矩形没有开启新的路径,绘制形状互相是独立的。

清除矩形:

清除矩形是将指定范围内的东西都清除掉

ctx.clearRect(起点x,起点y,宽,高)

步骤:

var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')
  1. 矩形 - ctx.rect(矩形的起始坐标的x,矩形的起始坐标的y,矩形x轴长度,矩形y轴的长度)
ctx.rect(50, 50, 200, 100)
  1. 描边
ctx.strokeStyle = 'red';
  1. 设置填充颜色
ctx.fillStyle = 'yellowgreen';
  1. 填充
 ctx.fill()


清除矩形:

 // 快速创建描边矩形 - 不用描边了ctx.strokeRect(50, 50, 200, 100)// 快速创建填充矩形 - 不用填充了ctx.fillRect(50, 200, 200, 100)// 清除矩形ctx.clearRect(25, 100, 300, 150)

渐变:

设置颜色的时候是可以设置渐变的。渐变跟形状无关,在画布中确定好渐变的区域和颜色之后,在这个区域内的图形,填充或描边时可以将颜色设置成渐变。

设置渐变方案:

ctx.createLinearGradient(开始x,开始y,结束x,结束y) // 返回渐变方案

通过设置的初始值和结束值可以确定渐变的方向。

设置渐变颜色:

渐变方案.addColorStop(数字,颜色)
// 数字:
/*
取值范围是0~1,0代表开始,1代表结束
*/

渐变方案可以直接赋值给填充或描边颜色的,例:

// 设置渐变方案
var linearGradient = ctx.createLinearGradient(100,100,500,100);
// 添加渐变颜色
linearGradient.addColorStop(0,'red');
linearGradient.addColorStop(0.5,'green');
linearGradient.addColorStop(1,'blue');
// 将渐变方案设置给填充颜色
ctx.fillStyle = linearGradient;
// 绘制矩形
ctx.fillRect(150,150,500,200)

步骤:

  1. 获取节点 工具箱
var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d')
  1. 设置一个渐变方案 - 设置给画布的
    参数1:渐变开始的坐标 里面的 x坐标
    参数2:渐变开始的坐标 里面的 y坐标
    参数3:渐变结束的坐标 里面的 x坐标
    参数4:渐变结束的坐标 里面的 y坐标
    有了这4个参数,明白了渐变的方向 - 返回一个渐变方案
var linearGradient = ctx.createLinearGradient(0,0,600,0)
  1. 给渐变方案设置渐变的颜色
    参数1:数字 - 取值范围 0~1
    0表示开始
    1表示结束
linearGradient.addColorStop(0,'red');
linearGradient.addColorStop(1,'green')
  1. 渐变方案可以当做是一个颜色直接赋值给填充或描边的颜色值
ctx.strokeStyle = linearGradient
ctx.lineWidth = 10
ctx.strokeRect(50,200,500,50)

效果:

画弧线:

画弧线是画一个路径,后面需要填充或描边。

ctx.arc(圆心x,圆心y,半径,开始弧度,结束弧度)

弧度:当圆形上的边跟半径相等的时候就是一个弧长,弧度其实就是弧长的个数。

我们通常描述的时候,会使用角度来描述弧形,很少描述弧度,但是计算机在计算的时候使用弧度的时候比较多。

弧度和角度的换算:

周长 = π * 半径 * 2
一周长是360度,1弧长是半径,所以:
1弧长对应的角度 = 180 / π
新角度/计算出来的角度 = 新弧长 / 1弧长
新弧长 = 1弧长 * 新角度 / 计算出来的角度
新弧长 = r * 60 * π / 180
弧度 = 角度 * π / 180

横向x轴向右的角度是0度,顺时针是正角度,所以画一个0度到60度的弧形:

// 圆心是100*100,半径是100
ctx.arc(100,100,100,0,60 * Math.PI/180)
ctx.stroke()
ctx.fill()

将这个弧形和半径进行填充就能得到一个扇形。

ctx.moveTo(100,100)
ctx.arc(100,100,100,0,Math.PI/3)
ctx.stroke()
ctx.fill()

等分圆形:

var width = ctx.canvas.width;
var height = ctx.canvas.height
var pointX = width / 2;
var pointY = height / 2;var r = 100;
var num = 4;
var startArc = 0;
for(var i=0;i<num;i++){ctx.beginPath()ctx.moveTo(pointX,pointY)ctx.fillStyle = getColor()ctx.arc(pointX,pointY,r,startArc,(i+1)*360/num*Math.PI/180)ctx.stroke()ctx.fill()startArc = (i+1)*360/num*Math.PI/180
}function getColor(){var r = Math.floor(Math.random()*256);var g = Math.floor(Math.random()*256);var b = Math.floor(Math.random()*256);return `rgb(${r},${g},${b})`
}

画饼图:

已知数据:

15 ~ 20 岁, 22 人
20 ~ 25 岁, 18 人
25 ~ 30 岁, 31 人
30 ~ 35 岁, 17 人
35 ~ 40 岁, 123 人

将数据抽象出来成一个数组:

[22,18,31,17,123]

每个数据对应的弧长:

角度:(数据 / 总和) * 360
弧度:角度 * Math.PI / 180

代码:

var arr = [22,18,31,17,123]
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d')var width = ctx.canvas.width;
var height = ctx.canvas.height;var pointX = width / 2;
var pointY = height / 2;
var r = 100;
var sum = arr.reduce((a,b)=>a+b)
var startArc = 0
arr.forEach(v=>{var endArc = startArc + v/sum * 360 * Math.PI/180ctx.beginPath()ctx.moveTo(pointX,pointY);ctx.fillStyle = getColor()ctx.arc(pointX,pointY,r,startArc,endArc)ctx.stroke()ctx.fill()startArc = endArc
})
function getColor(){var r = Math.floor(Math.random()*256);var g = Math.floor(Math.random()*256);var b = Math.floor(Math.random()*256);return `rgb(${r},${g},${b})`
}

画文字:

ctx.strokeText(文本,文字开始x,文字开始y) // 描边
ctx.fillText(文本,文字开始x,文字开始y) // 填充文字

文字大小:

ctx.font = '字号大小 字体'
// 字号大小就是 数字px

上下对齐方式:

取值:
默认是baseline
bottom:底线对齐
top:顶线对齐
middle:中线对齐

ctx.textBaseLine = 值;

左右对齐方式:
取值:基于我们设置的文字坐标来对齐的
left - 默认值,左对齐
right - 右对齐

ctx.textAlign = 值;

获取文本内容的总宽度:

ctx.measureText(文本内容)获取到一个对象,其中包含width属性就是文字的宽度

实战:

画一个完整的统计饼图

源码:

var canvas = document.querySelector('canvas')
var ctx = canvas.getContext('2d');var x = ctx.canvas.width / 2 + 200;
var y = ctx.canvas.height / 2;
var r = 150
var R = r + 40var data = [{title:"15 ~ 20 岁",num:20},{title:"20 ~ 25 岁",num:15},{title:"25 ~ 30 岁",num:10},{title:"30 ~ 35 岁",num:35},{title:"35 ~ 40 岁",num:12},{title:"40 ~ 45 岁",num:25},{title:"45 ~ 50 岁",num:30},{title:"50 ~ 55 岁",num:35},{title:"55 ~ 60 岁",num:50}
];// 处理数据
var startNum = data[0].num
var total = data.reduce((a,b)=>{if(typeof a === 'number'){return a + b.num}else{return startNum + b.num}})
// console.log(total);
data.forEach(v=>{// 给每个对象添加弧度// v.arc = v.num/total*360 * Math.PI / 180v.arc = v.num/total*2 * Math.PI
})
// console.log(data);// 画饼
var startArc = 0
data.forEach((v,index)=>{ctx.beginPath()ctx.moveTo(x,y)var endArc = startArc + v.arcctx.arc(x,y,r,startArc,endArc)startArc = endArcvar color = getColor()ctx.fillStyle = colorctx.fill()// 画延伸线outLine(v.arc,endArc,color,v.title)// 画说明方块descSquare(index)
})
// 画说明方块
function descSquare(index){var squareWidth = 50;var squareHeight = 30;var squareLeft = 20;var squareTop = 20// 画小方块ctx.fillRect(squareLeft,squareTop*(index+1)+squareHeight*index,squareWidth,squareHeight)// 计算文字的开始坐标var textX = squareLeft + squareWidth + squareLeftvar textY = squareTop*(index+1)+squareHeight*index+squareHeight/2ctx.textBaseline = 'middle';ctx.textAlign = 'left';var percent = (data[index].num / total).toFixed(2) * 100 + '%'ctx.fillText(data[index].title+'   ' + percent,textX,textY)}
// 画延伸线
function outLine(currentArc,endArc,color,title){// 获取到需要画线的这个弧度var arc = endArc - currentArc/2// 计算这条线的终点x和yvar endX = Math.cos(arc) * R + xvar endY = Math.sin(arc) * R + yctx.moveTo(x,y)ctx.lineTo(endX,endY)ctx.strokeStyle = color// 获取文字长度ctx.font = '16px 楷体'var textWidth = ctx.measureText(title).widthif(endX<x){textX = endX - textWidthctx.textAlign = 'left';}else{textX = endX + textWidthctx.textAlign = 'right';}ctx.textBaseline = 'bottom';ctx.lineTo(textX,endY)// 写字ctx.strokeText(title,textX,endY-3)ctx.stroke()
}// 随机颜色
function getColor(){return `rgb(${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)},${Math.floor(Math.random()*256)})`
}

echarts插件的使用

官网地址:https://echarts.apache.org/zh/index.html

1、下载echarts.min.js文件

具体方法在官网有很多种。

2、 引入ECharts

 <script src="echarts.min.js"></script>

3、绘制一个简单的图表,在官网挑选自己喜欢的图表

这里挑选了一个北京公交线路图

复制源码 Ctrl +c 和 Ctrl +v

效果:

制作自己需要的扇形图,柱形统计图,气泡图等

制作一个天气饼状图


修改响应的数据


可添加响应的配置项,修改等等


更多详情可查看手册。


觉得博主总结的不错的,可以收藏支持一波~

canvas入门,一篇博文带你学会用代码绘画,直击实战案例!相关推荐

  1. 五小时三万字之一篇博文带你学会SQL【期末数据库稳了】

    ❤️SQL必备知识详解(MySQL版)❤️ 1.数据定义(DDL) 1.1基本表的定义,删除与修改 1.1.1.表的完整性约束 1.1.1.1.非外建约束 1.1.1.2.外建约束与外键策略 1.2. ...

  2. 36篇博文带你学完opencv :python+opencv进阶版学习笔记目录

    基础版学习笔记传送门 36篇博文带你学完opencv :python3+opencv学习笔记汇总目录(基础版) 进阶版笔记 项目 opencv进阶学习笔记1: 调用摄像头用法大全(打开摄像头,打开摄像 ...

  3. 一篇博文带你0基础 Html和css入门

    前端初学入门,找不到学习方向,不喜欢记笔记?没关系,这篇博文为你整理了详细的学习笔记汇总,欢迎收藏,喜欢的可以直接到博文尾处,免费下载md笔记哦~⭐⭐⭐ Html5 网站: 1.网站的建立流程

  4. 【新手宝典】一篇博文带萌新建站并了解建站体系流程和对萌新友好的便捷方式,这篇博文很有可能是你的启蒙文

    前言 本片博文主要面向于还没接触过web开发的萌新,以及想知道整体流程并且完成建站的萌新:如果你是个大佬,就没必要看下去了. 本篇博文没有难啃的骨头,请各位萌新放心食用. 本篇博文采用通俗易懂的方式讲 ...

  5. 想自学Python却不知该如何入门?这篇文章带你轻松入门Python

    以2019年的资料为蓝本,2018年的资料为补充,还参考了一些网上的教程,旨在更好地总结Python基础知识,力求简明扼要,以供实战演练时能够快速查询遗忘的知识点.学一门语言贵在坚持用它,不用就淡忘了 ...

  6. 自然语言处理NLP-100例 | 第二篇:在线课程评论情感分析-本科毕设实战案例

    大家好,我是K同学啊~ 春去秋来,时间就这样嘀嗒嘀嗒的过去,不知道大家的毕设做得怎么样了呢 K同学就今天和大家分享一篇关于在线课程评论情感分析的实战案例,帮助大家找找灵感. 数据用的是一份公开的在线课 ...

  7. go-elasticSearch实战篇,带你学会elasticSearch的增删改查

    前言 哈喽,everybody,这是go-elastic学习系列教程第二篇文章.上一篇我们学习了ElasticSearch基础,如果还不懂基础的,可以先看一看上一篇文章,传送门.这一篇我们开始实战,写 ...

  8. 计算机视觉:图像特征与描述大全 ,有代码(一篇博文带你简单了解完图像特征提取技术)

    图像特征提取是 我们在做图像分类,图像检测,图像分割等任务前的任务. 图像特征提取的好坏,一定程度上决定着后续任务最终的结果.是特征工程,特征工程的重要性就不多说啦把,它决定着一个任务的上限成就. 算 ...

  9. 36篇博文带你学完opencv :python3+opencv学习笔记汇总目录(基础版)

    经过几天的学习,opencv基础部分学习完啦.整理出来. OpenCV opencv学习笔记1:图片读入,显示与保存(有代码) opencv学习笔记2:图像处理基础 opencv学习笔记3:像素处理 ...

最新文章

  1. Ubuntu14.04 Mininet中将Openvswitch升级步骤
  2. ArcGIS对AutoCAD操作的图文教程
  3. qt-5.6.0 移植之纯净的linux文件系统的建立
  4. eclipse中使用javap分析java代码备忘
  5. mysql server 5.6root_root密码mysqlMySQL-5.6.24免安装版配置方法
  6. 《java基础知识》Java变量作用域
  7. DHCP服务和NIS服务
  8. C#基础系列——语法
  9. 6种字符串数组的java排序 (String array sort)
  10. 神奇的go语言(聊天室的开发)
  11. RDD之一:总体介绍
  12. codeblock异常关闭,重新开机,启动时提示有另外的实例在运行的解决办法。
  13. Windows 0day成功验证之ETERNALBLUE 本帖由春秋首发~作者:神风 @春秋文阁负责人 方程式又一波0day【该贴有工具】:https://bbs.ichunqiu.com/thr
  14. 支付宝小程序框架分析
  15. java jsp 乱码_JSP中文乱码问题
  16. linux企业版as,Redhat 企业版 LINUX AS5.0 下载地址
  17. 计算机屏幕偏振光原理,隐形却很重要 PC屏幕的那层膜
  18. case when 的使用
  19. 【MindSpore,ModelArts】华为云ModelArts简明教程 | 图文
  20. Jira中文包插件,更专业的中文Jira

热门文章

  1. Xcode极速代码,征服Xcode
  2. 用户头像上传之 jQuery+ajax+php+预处理
  3. 什么云文档支持html,有道云协作支持文件格式有哪些?
  4. 100 道 Linux 常见面试题
  5. 游戏开发中的策略模式
  6. 计算机什么专业适合男生,男生最吃香的十大专业是哪些?(最适合男生的10个专业)...
  7. [转载]运行金山词霸2007死机问题
  8. 干掉蓝光播放器,KODI称王
  9. 淘宝的淘友圈正在公开你的隐私
  10. uniapp软键盘把界面顶起问题解决