一:画直线
1.使用canvas标签---HTML
<canvas width="500px" height = '500px'>您的浏览器暂不支持canvas标签,请更换浏览器</canvas>
canvas标签里面的内容会在浏览器不兼容canvas的情况下进行显示
使用js操控canvas---JavaScript
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 开始一条路径
ctx.beginPath()
// 确定起始点
ctx.moveTo(100,100)
// 确定结束点
ctx.lineTo(400,100)
// 着色
ctx.stroke()
// 结束路径
ctx.closePath()
二、设置颜色和宽
我们只需要在着色之前 改变画笔的颜色
// 在着色之前设置颜色和线宽
ctx.strokeStyle = 'red' // 设置颜色
ctx.lineWidth = 5 // 设置线的宽度
// 着色
ctx.stroke()
三、画矩形
// rect矩形
// x,y,宽,高
ctx.rect(100,100,300,200)
// 描边
ctx.strokeStyle = 'red'
ctx.lineWidth = 5
// 填充,一定先填充,后进行着色边框
ctx.fillStyle = 'pink' // 填充颜色
ctx.fill()
ctx.stroke()
四、画统计图
let ctx = canvas.getContext('2d')
// 画线
ctx.beginPath()
ctx.moveTo(100,100)
ctx.lineTo(100,400)
ctx.lineTo(400,400)
ctx.stroke()
// 画矩形
ctx.fillStyle = 'red'
ctx.fillRect(200,200,20,200)
ctx.stroke()
随机画统计图
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// 画线
ctx.beginPath()
ctx.moveTo(100,100)
ctx.lineTo(100,400)
ctx.lineTo(400,400)
ctx.stroke()
// 画矩形
for (let i = 0; i < 6; i++) {
// 随机一个高度
let height =Math.floor( Math.random() * 280 + 10)
// 随机一个颜色
ctx.fillStyle = '#' + parseInt(Math.random() * 0xffffff).toString(16)
ctx.fillRect(120 + 40 * i,400 - height ,20,height)
}
五、案例
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// 1,画一张填充矩形
ctx.fillRect(20,20,100,100)
// 2,清除画布
ctx.clearRect(40,40,60,60)
// 3,画一个着边的矩形,不填充内部只有边框
ctx.strokeRect(50,50,40,40)
六、绘制三角形
ctx.beginPath()
// 起点。第一个点
ctx.moveTo(50,50)
// 第二个点
ctx.lineTo(100,100)
// 第三个点
ctx.lineTo(100,0)
// 填充实心
// ctx.fill()
// 接到起始点 or 自动闭合
// ctx.lineTo(50,50)
ctx.closePath()
ctx.stroke()
七、圆的组成
// 圆的组成:
// 圆心(x,y)
// 开始角度
// 结束角度
// 顺时针/逆时针
ctx.strokeStyle = 'orange'
ctx.lineWidth = 10
// 画圆
// x,y,半径,开始角度(默认三点钟方向),最后的具体角度,是否顺时针
// ctx.arc(x,y,radius,startAngle,endAngle,anticlockwise)
// ctx.arc(300,300,100,0,Math.PI,true)
ctx.arc(300,300,100,0,Math.PI/2,false)
ctx.stroke()
八、循环建圆
for (let i = 0; i < 4; i++){
for (let j = 0; j < 3; j++){
ctx.beginPath()
let x = 25 + j *80
let y = 25 + i * 80
let radius = 20
let startAngel = 0
let endAngel = Math.PI + (Math.PI * j) / 2
let flag = (i % 2) === 0 ? false : true
ctx.arc(x,y,radius,startAngel,endAngel, flag)
if (i < 2){
ctx.stroke()
}else {
ctx.fillStyle = 'pink'
ctx.fill()
}
}
}
九、画茶杯
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// 画杯身
ctx.lineWidth = 2
ctx.strokeRect(100,200,200,200)
// 画把手
drawCircle(300,300,50,6,false)
// 热气
// drawCircle(140,120,20,1,true)
// drawCircle(140,160,20,1,false)
//
// drawCircle(180,120,20,1,true)
// drawCircle(180,160,20,1,false)
//
// drawCircle(220,120,20,1,true)
// drawCircle(220,160,20,1,false)
//
// drawCircle(260,120,20,1,true)
// drawCircle(260,160,20,1,false)
// 使用循环
for (let i = 0; i < 4; i++) {
drawCircle(140 + i * 40,120,20,1,true)
drawCircle(140 + i * 40,160,20,1,false)
}
function drawCircle(x, y, r,width,flag){
ctx.beginPath()
ctx.arc(x, y, r,-Math.PI/2,Math.PI/2,flag)
ctx.lineWidth = width
ctx.stroke()
}
十、圆形统计图
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
let deg = Math.PI*2/360
let count = 1
let timer = setInterval(() => {
count++
ctx.beginPath()
// 从是12点方向开始
ctx.arc(250, 250, 200,-Math.PI/2,count*deg - Math.PI/2,false)
ctx.lineWidth = 2
ctx.stroke()
if (count === 360) clearInterval(timer)
},10)
十一、碰撞检测
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// 定义x y 半径
let x = 100
let y = 30
let r = 30
// 画布的宽高
let h = w = 500
// 控制小球速度
let xSpeed = 1
let ySpeed = 3
setInterval(function () {
// 清除画布
ctx.clearRect(0, 0, w, h)
x += xSpeed
y += ySpeed
// 当球到达边界时,进行更改
if (x - r <= 0 || x + r >= w){
xSpeed = -xSpeed
}
if (y - r <= 0 || y + r >= h){
ySpeed = -ySpeed
}
drawCircle(x, y, r)
}, 0)
function drawCircle(x, y, r) {
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.fillStyle = 'pink'
ctx.fill()
}
上面代码使用的是定时器,使用定时器会有卡顿的效果
那么bom提供了一个方法
window.requestAnimationFrame()
参数填方法名,下面是把定时器替换掉后的函数
function test(){
// 清除画布
ctx.clearRect(0, 0, w, h)
x += xSpeed
y += ySpeed
// 当球到达边界时,进行更改
if (x - r <= 0 || x + r >= w){
xSpeed = -xSpeed
}
if (y - r <= 0 || y + r >= h){
ySpeed = -ySpeed
}
drawCircle(x, y, r)
window.requestAnimationFrame(test)
}
test()
十二、面向对象的小球
let canvas = document.querySelector('canvas')
let ctx = canvas.getContext('2d')
// 画布的宽高
let h = w = 500
/**
* 面向对象
*/
function r(num){
return Math.random()*num
}
/**
* @param x 起始x坐标
* @param y 起始y坐标
* @param color 小球半径
* @param xSpeed x轴速度
* @param ySpeed y轴速度
* @constructor
*/
function Ball(){
// this.x = r(500)
// this.y = r(500)
this.x = r(50)+60
this.y = r(300)+60
this.r = r(50) + 10 // [10 - 60]
this.color = '#' + parseInt(Math.random() * 0xffffff).toString(16)
this.xSpeed = r(5)
this.ySpeed = r(5)
}
// 定义小球显示方法
Ball.prototype.show = function (){
ctx.beginPath()
ctx.arc(this.x,this.y,this.r,0,Math.PI*2)
ctx.fillStyle = this.color
ctx.fill()
}
// 定义小球运动(碰撞检测)
Ball.prototype.run = function (){
// 当球到达边界时,进行更改
if (this.x - this.r <= 0 || this.x + this.r >= w){
this.xSpeed = -this.xSpeed
}
this.x = this.x + this.xSpeed
if (this.y - this.r <= 0 || this.y + this.r >= w){
this.ySpeed = -this.ySpeed
}
this.y = this.y + this.ySpeed
}
// 存放小球的数组
let ballArr = []
// 创建一个小球
for (let i = 0; i < 30; i++) {
let ball = new Ball()
ballArr.push(ball)
ball.show()
}
console.log(ballArr)
// 小球运动
setInterval(function () {
// ctx.clearRect(0,0,w,h)
// for (let i = 0; i < ballArr.length; i++) {
// let ball = ballArr[i]
// // 更新坐标 显示小球
// ball.run()
// ball.show()
// }
},10)
function test(){
ctx.clearRect(0,0,w,h)
for (let i = 0; i < ballArr.length; i++) {
let ball = ballArr[i]
// 更新坐标 显示小球
ball.run()
ball.show()
}
window.requestAnimationFrame(test)
}
test()
十三、画文字
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 设置字体相关样式
ctx.font = '100px 宋体'
ctx.fillStyle = 'red'
// 绘制实心文字
ctx.fillText('hello',250,250)
// 绘制空心文字
ctx.strokeText('你好',0,250)
ctx.font = '100px 宋体'
ctx.fillText('hello canvas!',100,100,400) // 限制宽度
十四、渐变文字
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 设置字体相关样式
ctx.font = '100px 宋体'
// 设置线性渐变
let gradient = ctx.createLinearGradient(0,0,500,0)
gradient.addColorStop(0,'yellow')
gradient.addColorStop(0.5,'blue')
gradient.addColorStop(1,'red')
// 填充
ctx.fillStyle = gradient
ctx.fillText('今天天气很好,你有想我吗?',0,100,500)
ctx.strokeStyle = gradient
ctx.strokeText('炸鸡很好吃,但是它热量很高',0,200,500)
十五、文字位置
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 画直线
ctx.beginPath()
ctx.moveTo(250,0)
ctx.lineTo(250,500)
ctx.closePath()
ctx.stroke()
ctx.beginPath()
ctx.moveTo(0,250)
ctx.lineTo(500,250)
ctx.closePath()
ctx.stroke()
// 设置字体相关样式
ctx.font = '100px 宋体'
/***
* 水平文字的属性值textAlign:start end left right
* 垂直文字的属性值textBaseline = top bottom middle
*/
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText('HTML5',250,250)
十六、米字格
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 1:画垂直和水平线
drawLine(0, 250, 500, 250)
drawLine(250, 0, 250, 500)
// 画斜线
// 方法一
// for (let i = 0; i < 50; i++) {
// drawLine(i * 10, i * 10, i * 10 + 5, i * 10 + 5,'red')
// drawLine(500-i*10,i*10,500-(i*10+5),i*10+5,'red')
// }
// 方法二
ctx.setLineDash([5,5])
drawLine(0,0,500,500,"red")
drawLine(500,0,0,500,"red")
// 画字
drawText('米', 250, 250)
/***
* 画直线方法
*/
function drawLine(x1, y1, x2, y2, color) {
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.strokeStyle = color || '#000'
ctx.stroke()
ctx.closePath()
}
/***
* 画文字
*/
function drawText(text, x, y) {
ctx.font = '400px 宋体'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.fillText(text, x, y)
}
十七、绘制图片
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
let img = new Image()
img.src = 'sxb.jpg'
/***
* onload:图片加载成功后触发
* onerror:图片加载失败后触发
*/
img.onload = function (e){
// 获取当前图片的实际宽高
console.log(img.width,img.height)
/**
* 1.在画布上定位图像
* content.drawImage(img,x,y)
* 2.在画布上定位图像,并规定图像的宽度和高度
* content.drawImage(img,x,y,width,height)
* 3.剪切图像,并在画布上定位被剪切的部分
* context. drawImage( ing,sx,sy,swidth, sheight,x ,y ,width, height);
* img 规定要使用的图像、画布或视频。
* Sx可选。开始剪切的X坐标位置。
* sy可选。开始剪切的y坐标位置。
* swidth可选。 被剪切图像的宽度。
* sheight可选。被剪切图像的高度。
* x在画布上放置图像的X坐标位置。
* y在画布上放置图像的y坐标位置。
* width可选。 要使用的图像的宽度。( 伸展或缩小图像)
* height可选。要使用的图像的高度。(伸展或缩小图像)
*/
// 1
// ctx.drawImage(img,0,0)
// 2
// ctx.drawImage(img,0,0,100,100)
// 3
ctx.drawImage(img,40,20,160,160,150,150,200,200)
}
十八、线性小球
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 画布的宽高
let h = 500, w = 500
// 随机数
function r(num) {
return Math.random() * num
}
/**
* @param x 起始x坐标
* @param y 起始y坐标
* @param color 小球半径
* @param xSpeed x轴速度
* @param ySpeed y轴速度
* @constructor
*/
function Ball(text) {
this.x = r(380) + 60 // [60,440]
this.y = r(380) + 60 // [60,440]
this.r = r(50) + 10 // [10,60]
this.color = '#' + parseInt(Math.random() * 0xffffff).toString(16)
this.xSpeed = r(5)
this.ySpeed = r(5)
// 接收外部参数
this.text = text
}
Ball.prototype.show = function () {
this.run() // 更新坐标
drawCir(this.x, this.y, this.r, this.color) // 画小球
drawText(this.text, this.x + this.r, this.y) // 画文字
}
// 定义小球运动(碰撞检测)
Ball.prototype.run = function () {
// 当球到达边界时,进行更改
if (this.x - this.r <= 0 || this.x + this.r >= w) {
this.xSpeed = -this.xSpeed
}
this.x = this.x + this.xSpeed
if (this.y - this.r <= 0 || this.y + this.r >= w) {
this.ySpeed = -this.ySpeed
}
this.y = this.y + this.ySpeed
}
/**
* 画直线
* @param x1
* @param y1
* @param x2
* @param y2
* @param color
*/
function drawLine(x1, y1, x2, y2, color) {
ctx.beginPath()
ctx.moveTo(x1, y1)
ctx.lineTo(x2, y2)
ctx.strokeStyle = color || '#000'
ctx.stroke()
ctx.closePath()
}
/**
* 画文字
* @param text
* @param x
* @param y
*/
function drawText(text, x, y) {
ctx.font = '16px 微软雅黑'
ctx.textAlign = 'start'
ctx.textBaseline = 'middle'
ctx.fillText(text, x, y)
}
/**
* 画圆
* @param x
* @param y
* @param r
* @param color
*/
function drawCir(x, y, r, color) {
this.color = color
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.fillStyle = this.color
ctx.fill()
}
let titleArr = 'javascript HTML5前端 JAVA PHP Jquery Cnavas css css3 Angular Bootstrap'.split(' ')
console.log(titleArr)
// 存放小球
let ballArr = []
for (let i = 0; i < 5; i++) {
// 当前小球
let ball = new Ball(titleArr[i]) // 传入title
ballArr.push(ball)
ball.show()
}
//小球运动
function ballRun() {
ctx.clearRect(0, 0, w, h)
for (let i = 0; i < ballArr.length; i++) {
ballArr[i].show()
/**
* 小球连线 a球和b球
*/
for (let j = 0; j < i; j++) {
// 取出当前小球前面的小球
let prevBall = ballArr[j]
console.log(prevBall)
drawLine(ballArr[i].x, ballArr[i].y, prevBall.x, prevBall.y, ballArr[i].color)
}
}
window.requestAnimationFrame(ballRun)
}
ballRun()
十九、鼠标幻彩小球
HTML:
<canvas></canvas>
JavaScript:
// 获取画布
let canvas = document.querySelector('canvas')
// 获取画布的上下文
let ctx = canvas.getContext('2d')
// 获取窗口可视区域宽高
let w = document.documentElement.clientWidth - 6
let h = document.documentElement.clientHeight - 6
console.log(w, h)
// 更新canvas宽高
canvas.width = w
canvas.height = h
/**
* @param x 起始x坐标
* @param y 起始y坐标
* @param color 小球半径
* @constructor
*/
function Ball(x, y) {
this.x = x
this.y = y
this.r = 30
// 随机颜色
this.color = '#' + parseInt(Math.random() * 0xffffff).toString(16)
}
Ball.prototype.show = function () {
// 半径越来越小
this.r--
drawCir(this.x, this.y, this.r, this.color) // 画小球
}
// 小球数组
let ballArr = []
// 鼠标滑动事件
document.onmousemove = function (e) {
let ball = new Ball(e.x, e.y)
ballArr.push(ball)
ball.show()
}
/**
* 画圆
* @param x
* @param y
* @param r
* @param color
*/
function drawCir(x, y, r, color) {
this.color = color
ctx.beginPath()
ctx.arc(x, y, r, 0, Math.PI * 2)
ctx.fillStyle = this.color
ctx.fill()
}
setInterval(() => {
ctx.clearRect(0, 0, w, h)
for (let i = 0; i < ballArr.length; i++) {
/**
* 判断:如果小球半径r小于0 就要从数组中删除
*/
if (ballArr[i].r <= 0) {
ballArr.splice(i, 1)
} else {
ballArr[i].show()
}
}
}, 10)