canvas学习笔记

  • canvas API中文网 - Canvas API中文文档首页地图
  • 使用canvas来绘制图形 - Web API 接口参考 | MDN
  • 什么是Canvas?
    • Canvas是H5新增的一个标签, 我们可以通过JS在这个标签上绘制各种图案
    • Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法。
  • 示例:
<body>
<!--1.在body中创建一个canvas标签-->
<!--
注意点
canvas标签有默认的宽度和高度
默认的宽度是300px
默认的高度是150px
-->
<canvas></canvas>
<script>// 2.通过js代码拿到canvas标签let oCanvas = document.querySelector("canvas");// 3.从canvas标签中获取到绘图工具let oCtx = oCanvas.getContext("2d");// 4.通过绘图工具在canvas标签上绘制图形// 4.1设置路径的起点oCtx.moveTo(50, 50);// 4.2设置路径的终点oCtx.lineTo(200, 50);// 4.3告诉canvas将这些点连接起来oCtx.stroke();
</script>
</body>
  • 不能通过CSS设置画布的宽高

    • 通过CSS设置画布宽高会在默认宽高的基础上拉伸
    • 如果需要设置canvas宽高请通过元素行内属性width和height设置
<canvas width="500" height="500"></canvas>
  • 线条默认宽度和颜色
  • 通过canvas绘制的线条默认宽度是1px, 颜色是纯黑色
  • 但是由于默认情况下canvas会将线条的中心点和像素的底部对齐,
  • 所以会导致显示效果是2px和非纯黑色问题。
  • 解决方式,y轴偏移0.5像素
oCtx.moveTo(50, 50.5);
oCtx.lineTo(200, 50.5);

canvas线条相关属性

/*
1.线条相关属性
lineWidth: 线条宽度
strokeStyle: 线条颜色
lineCap: 线末端类型:(butt默认)、round、square
* */
let oCanvas = document.querySelector("canvas");
let oCtx = oCanvas.getContext("2d");
// 修改线条的高度
oCtx.lineWidth = 50;
// 修改线条的颜色
oCtx.strokeStyle = "blue";
// 修改线条的两端样式
oCtx.lineCap = "round";
oCtx.moveTo(50, 50);
oCtx.lineTo(200, 50);
oCtx.stroke();
  • 绘制多段线
/*
1.多根线条注意点
如果是同一个路径, 那么路径样式会被重用(第二次绘制会复用第一次的样式)
如果是同一个路径, 那么后设置的路径样式会覆盖先设置的路径样式
2.如何给每根线条单独设置路径样式?
每根线条都开启一个新的路径即可
* */
let oCanvas = document.querySelector("canvas");
let oCtx = oCanvas.getContext("2d");
oCtx.moveTo(50, 50);
oCtx.lineTo(200, 50);
oCtx.lineWidth = 20;
oCtx.strokeStyle = "blue";
oCtx.stroke();
oCtx.beginPath(); // 重新开启一个路径
oCtx.moveTo(50, 100);
oCtx.lineTo(200, 100);
oCtx.lineWidth = 10; // 重新设置当前路径样式
oCtx.strokeStyle = "red";
oCtx.stroke();
oCtx.beginPath(); // 重新开启一个路径
oCtx.moveTo(50, 150);
oCtx.lineTo(200, 150);
oCtx.lineWidth = 15; // 重新设置当前路径样式
oCtx.strokeStyle = "green";
oCtx.stroke();

绘制简单图形

/*
1.closePath
自动创建从当前点回到起始点的路径
2.lineJoin
设置相交线的拐点样式 miter(默认)、round、bevel
* */
let oCanvas = document.querySelector("canvas");
let oCtx = oCanvas.getContext("2d");
oCtx.moveTo(50, 50);
oCtx.lineTo(200, 50);
oCtx.lineTo(200, 200);
oCtx.lineTo(50, 200);
// 注意点: 如果通过lineTo来闭合图形, 那么是不能很好的
// oCtx.lineTo(50, 50);
oCtx.closePath();
oCtx.lineWidth = 10;
oCtx.lineJoin = "round";
// 注意点: 默认情况下不会自动从最后一个点连接到起点
oCtx.stroke();

图形填充

  • 对于同一路径,在填充的时候回遵循非零环绕规则
  • 从当前的区域拉出一条直线, 遇到顺时针相交的线就+1, 遇到逆时针相交的线就-1
  • 最终计算的结果如何是0就不填充, 如果不是0就填充
/*1.stroke
绘制已定义的路径
2.fill
填充已定义的路径
*/
let oCanvas = document.querySelector("canvas");
let oCtx = oCanvas.getContext("2d");
oCtx.moveTo(100, 100);
oCtx.lineTo(300, 100);
oCtx.lineTo(300, 300);
oCtx.lineTo(100, 300);
oCtx.closePath();/*
Ctx.moveTo(150, 150);
Ctx.lineTo(250, 150);
Ctx.lineTo(250, 250);
Ctx.lineTo(150, 250);*/
Ctx.moveTo(250, 150);
Ctx.lineTo(150, 150);
Ctx.lineTo(150, 250);
Ctx.lineTo(250, 250);
oCtx.closePath();
/*
注意点: 只要没有手动开启新的路径, 那么使用的都是默认路径
如果都是默认路径, 那么设置的样式在同一个路径中都是有效的
* */
// oCtx.strokeStyle = "blue";
// oCtx.stroke();
oCtx.fill();

绘制表格

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>绘制表格</title><style>*{margin: 0;padding: 0;}canvas{display: block;margin: 300px auto;background: #e8e9ee;}</style>
</head>
<body>
<canvas width="500" height="400"></canvas>
<script>// 1.拿到canvaslet oCanvas = document.querySelector("canvas");// 2.从canvas中拿到绘图工具let oCtx = oCanvas.getContext("2d");// 3.定义变量保存小方格的尺寸let gridSize = 20;// console.log(oCanvas.offsetWidth);// console.log(oCanvas.offsetHeight);// console.log(oCtx.canvas.width);// console.log(oCtx.canvas.height);// 4.拿到canvas的宽高let canvasWidth = oCtx.canvas.width;let canvasHeight = oCtx.canvas.height;// 5.计算在垂直方向和水平方向可以绘制多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);// 6.绘制垂直方向的横线for(let i = 0; i < row; i++){oCtx.beginPath();oCtx.moveTo(0, i * gridSize - 0.5);oCtx.lineTo(canvasWidth, i * gridSize - 0.5);oCtx.strokeStyle = "#FFF";oCtx.stroke();}// 7.绘制水平方向的横线for(let i = 0; i < col; i++){oCtx.beginPath();oCtx.moveTo(i * gridSize - 0.5, 0);oCtx.lineTo(i * gridSize - 0.5, canvasHeight);oCtx.strokeStyle = "#FFF";oCtx.stroke();}
</script>
</body>
</html>
  • 绘制坐标

// 1.计算坐标系原点的位置
let originX = gridSize;
let originY = canvasHeight - gridSize;
// 2.计算X轴终点的位置
let endX = canvasWidth - gridSize;
// 3.绘制X轴
oCtx.beginPath();
oCtx.moveTo(originX, originY);
oCtx.lineTo(endX, originY);
oCtx.strokeStyle = "#000";
oCtx.stroke();
// 4.绘制X轴的箭头
oCtx.lineTo(endX - 10, originY + 5);
oCtx.lineTo(endX - 10, originY - 5);
oCtx.lineTo(endX, originY);
oCtx.fill();
// 5.计算Y轴终点的位置
let endY = gridSize;
// 3.绘制Y轴
oCtx.beginPath();
oCtx.moveTo(originX, originY);
oCtx.lineTo(originX, endY);
oCtx.strokeStyle = "#000";
oCtx.stroke();
// 4.绘制X轴的箭头
oCtx.lineTo(originX - 5, endY + 10);
oCtx.lineTo(originX + 5, endY + 10);
oCtx.lineTo(originX, endY);
oCtx.fill();

绘制折线图

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Canvas折线图封装</title><!----><style>*{margin: 0;padding: 0;}canvas{display: block;margin: 0 auto;background: #e8e9ee;}</style>
</head>
<body>
<script>class LineChart{constructor(width=300, height=150){// 1.创建canvasthis.canvas = document.createElement("canvas");this.canvas.width = width;this.canvas.height = height;document.body.appendChild(this.canvas);// 2.拿到绘图工具this.ctx = this.canvas.getContext("2d");}drawGrid(gridSize=20){let oCtx = this.ctx;// 4.拿到canvas的宽高let canvasWidth = oCtx.canvas.width;let canvasHeight = oCtx.canvas.height;// 5.计算在垂直方向和水平方向可以绘制多少条横线let row = Math.floor(canvasHeight / gridSize);let col = Math.floor(canvasWidth / gridSize);// 6.绘制垂直方向的横线for(let i = 0; i < row; i++){oCtx.beginPath();oCtx.moveTo(0, i * gridSize - 0.5);oCtx.lineTo(canvasWidth, i * gridSize - 0.5);oCtx.strokeStyle = "#ccc";oCtx.stroke();}// 7.绘制水平方向的横线for(let i = 0; i < col; i++){oCtx.beginPath();oCtx.moveTo(i * gridSize - 0.5, 0);oCtx.lineTo(i * gridSize - 0.5, canvasHeight);oCtx.strokeStyle = "#ccc";oCtx.stroke();}}drawCoor(gridSize=20){let oCtx = this.ctx;let canvasWidth = this.ctx.canvas.width;let canvasHeight = this.ctx.canvas.height;// 1.计算坐标系原点的位置let originX = gridSize;let originY = canvasHeight - gridSize;// 2.计算X轴终点的位置let endX = canvasWidth - gridSize;// 3.绘制X轴oCtx.beginPath();oCtx.moveTo(originX, originY);oCtx.lineTo(endX, originY);oCtx.strokeStyle = "#000";oCtx.stroke();// 4.绘制X轴的箭头oCtx.lineTo(endX - 10, originY + 5);oCtx.lineTo(endX - 10, originY - 5);oCtx.lineTo(endX, originY);oCtx.fill();// 5.计算Y轴终点的位置let endY = gridSize;// 3.绘制Y轴oCtx.beginPath();oCtx.moveTo(originX, originY);oCtx.lineTo(originX, endY);oCtx.strokeStyle = "#000";oCtx.stroke();// 4.绘制X轴的箭头oCtx.lineTo(originX - 5, endY + 10);oCtx.lineTo(originX + 5, endY + 10);oCtx.lineTo(originX, endY);oCtx.fill();}drawDot(list, dotSize=10){let oCtx = this.ctx;// 2.绘制数据点for(let i = 0; i < list.length; i++){oCtx.beginPath();oCtx.moveTo(list[i].x - dotSize / 2, list[i].y - dotSize / 2);oCtx.lineTo(list[i].x + dotSize - dotSize / 2, list[i].y - dotSize / 2);oCtx.lineTo(list[i].x + dotSize - dotSize / 2, list[i].y + dotSize - dotSize / 2);oCtx.lineTo(list[i].x - dotSize / 2, list[i].y + dotSize - dotSize / 2);oCtx.closePath();oCtx.fill();}}drawLine(list){let oCtx = this.ctx;oCtx.beginPath();for(let i = 0; i < list.length; i++){if(i === 0){oCtx.moveTo(list[i].x, list[i].y);}else{oCtx.lineTo(list[i].x, list[i].y);}}oCtx.stroke();}}let list = [{x: 100,y: 300},{x: 200,y: 200},{x: 300,y: 250},{x: 400,y: 100},];let lineChart = new LineChart(500, 400);lineChart.drawGrid(50);lineChart.drawCoor(50);lineChart.drawDot(list);lineChart.drawLine(list);
</script>
</body>
</html>

绘制矩形

  • 方式1:
/*
第一个参数: x的坐标
第二个参数: y的坐标
第三个参数: 矩形的宽度
第四个参数: 矩形的高度
* */
oCtx.rect(100, 100, 200, 200);
oCtx.stroke();
// oCtx.fill();
oCtx.beginPath();
oCtx.rect(150, 150, 100, 100);
oCtx.strokeStyle = "blue";
oCtx.stroke();
  • 方式2:
oCtx.strokeRect(100, 100, 200, 200);oCtx.strokeStyle = "blue";
oCtx.strokeRect(150, 150, 100, 100);
  • 填充矩形
oCtx.fillRect(100, 100, 200, 200);
oCtx.fillStyle = "blue";
oCtx.fillRect(150, 150, 100, 100);
  • 清空
// oCtx.clearRect(0, 0, 150, 150);
let canvasWidth = oCtx.canvas.width;
let canvasHeight = oCtx.canvas.height;
oCtx.clearRect(0, 0, canvasWidth, canvasHeight);

绘制柱状图

let list = [{x: 100,y: 300},{x: 200,y: 200},{x: 300,y: 250},
];
// 2.绘制矩形
for(let i = 0; i < list.length; i++){let barHeight = originY - list[i].y;oCtx.fillRect(list[i].x, list[i].y, gridSize, barHeight);
}

填充渐变色

/*
1.渐变背景颜色
和普通的标签一样我们也可以给填充的图形设置线性渐变和径向渐变的背景颜色
2.设置图形渐变背景颜色步骤
2.1通过绘图工具创建渐变背景颜色
2.2指定渐变的范围
2.3将渐变背景颜色设置给对应的图形
* */
// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
// 1.创建一个渐变的方案
/*
可以通过x0,y0 / x1,y1确定渐变的方向和渐变的范围
* */
let linearGradient = oCtx.createLinearGradient(100, 100, 300, 300);
/*
第一个参数是一个百分比 0~1
第二个参数是一个颜色
* */
linearGradient.addColorStop(0, "green");
linearGradient.addColorStop(0.5, "pink");
linearGradient.addColorStop(1, "blue");
// oCtx.createRadialGradient();
// oCtx.fillStyle = "blue";
oCtx.fillStyle = linearGradient;
oCtx.fillRect(100, 100, 200, 200);

绘制圆弧

  • canvas API中文网 - 中文文档 - CanvasRenderingContext2D.arc()
// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
/*
x, y: 确定圆心
radius: 确定半径
startAngle: 确定开始的弧度
endAngle: 确定结束的弧度
Boolean: 默认是false, false就是顺时针绘制, true就是逆时针绘制
context.arc(x, y, radius, startAngle, endAngle, Boolean);
* */
// oCtx.arc(100, 100, 100, 0, Math.PI);
// oCtx.arc(100, 100, 100, 0, Math.PI, true);
oCtx.arc(100, 100, 100, 0, Math.PI * 2);
oCtx.stroke();

绘制扇形

// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
oCtx.moveTo(100, 100);
oCtx.arc(100, 100, 100, 0, Math.PI/2);
oCtx.closePath();
// oCtx.stroke();
oCtx.fillStyle="deeppink"
oCtx.fill();

绘制饼图

// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
// 1.计算圆心的位置
let rx = oCtx.canvas.width/2;
let ry = oCtx.canvas.height/2;
let startAngle = 0;
for(let i = 1; i <= 4; i++){let endAngle = i * Math.PI/2;oCtx.beginPath();oCtx.moveTo(rx, ry);oCtx.arc(rx, ry, 100, startAngle, endAngle);oCtx.fillStyle = randomColor();oCtx.fill();startAngle = endAngle;
}
function randomColor() {let r = Math.floor(Math.random() * 256);let g = Math.floor(Math.random() * 256);let b = Math.floor(Math.random() * 256);return `rgb(${r},${g},${b})`;
}

绘制文字

// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
// 3.绘制参考线
let canvasWidth = oCtx.canvas.width;
let canvasHeight = oCtx.canvas.height;
oCtx.moveTo(0, canvasHeight/2);
oCtx.lineTo(canvasWidth, canvasHeight/2);
oCtx.stroke();
oCtx.moveTo(canvasWidth/2, 0);
oCtx.lineTo(canvasWidth/2, canvasHeight);
oCtx.stroke();
// 4.绘制文字
let str = "绘制文字测试";
// 通过font属性可以设置文字的大小和样式
oCtx.font = "50px 宋体";
// 通过textBaseline属性可以设置文字垂直方向的对齐方式
// 注意点: 在对齐的时候是以绘制文字的y作为参考点进行对齐的
oCtx.textBaseline = "middle";
// 通过textAlign属性可以设置文字水平方向的对齐方式
// 注意点: 在对齐的时候是以绘制文字的x作为参考点进行对齐的
oCtx.textAlign = "center";
/*
注意点:
在绘制文字的时候, 是以文字的左下角作为参考点进行绘制
* */
// oCtx.strokeText(str, canvasWidth/2, canvasHeight/2);
oCtx.fillText(str, canvasWidth/2, canvasHeight/2);

绘制图片

// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
// 3.加载图片
let oImg = new Image();
oImg.onload = function () {// 如果只有三个参数, 那么第一个参数就是需要绘制的图片// 后面的两个参数是指定图片从什么位置开始绘制// oCtx.drawImage(oImg, 100, 100);// 如果只有五个参数, 那么第一个参数就是需要绘制的图片// 后面的两个参数是指定图片从什么位置开始绘制// 最后的两个参数是指定图片需要拉伸到多大// oCtx.drawImage(oImg, 100, 100, 100, 100);// 如果有九个参数, 那么第一个参数就是需要绘制的图片// 最后的两个参数是指定图片需要拉伸到多大// 第6~7个参数指定图片从什么位置开始绘制// 第2~3个参数指定图片上定位的位置// 第4~5个参数指定从定位的位置开始截取多大的图片oCtx.drawImage(oImg, 50, 50, 100, 100, 100, 100, 100, 100);
}
oImg.src = "images/test.jpg";

添加事件监听

/*
因为整个canvas是一个标签, 所以只能通过监听鼠标在canvas上的位置来判断是否需要处理对应的图形
当然也可以通过第三方框架来解决交互问题
诸如: zrender.js / Knova.js /three.js / egret.js / pixi.js等等
* */
// 1.拿到canvas
let oCanvas = document.querySelector("canvas");
// 2.从canvas中拿到绘图工具
let oCtx = oCanvas.getContext("2d");
// 3.绘制矩形
let rectX = 100;
let rectY = 100;
let rectWidth = 100;
let rectHeight = 100;
oCtx.rect(rectX, rectY, rectWidth, rectHeight);
oCtx.fill();
oCtx.beginPath();
oCtx.rect(200, 200, 100, 100);
oCtx.fill();
// 4.添加点击事件
oCanvas.onclick = function (event) {let x = event.offsetX;let y = event.offsetY;/*if(x >= rectX && x <= rectX + rectWidth &&y >= rectY && y <= rectY + rectHeight){console.log("矩形被点击了");}else{console.log("矩形没有被点击");}*//*注意点:isPointInPath方法如果开启了一个新的路径, 那么判断的就是点是否在新的路径的图形中* */console.log(oCtx.isPointInPath(x, y));

canvas学习笔记相关推荐

  1. Canvas 学习笔记1

    #Canvas 学习笔记1 @[Canvas,Nunn,HTML5,javascript] ##前言 相信大家多多少少都有了解过`Canvas`,这里我就不多做解释了,网上也充斥了这方面的知识,很多人 ...

  2. Canvas学习笔记之画线

    Canvas学习笔记之画线 步骤 1.使用getElementById()获取canvas元素. 2.获取canvas的绘制环境getContext(). 3.进行绘制画笔的粗细和颜色定义,分别是li ...

  3. canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)...

    [下篇] -- 建议学习时间4小时  课程共(上中下)三篇 此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例, ...

  4. Canvas学习笔记 Canvas的基础知识点

    文章目录 前言 一.导航 初始化 属性与方法 小demo 二.绘制功能 2.1.绘制矩形 2.1.1.非面向思想实现动画 2.1.2.面向对象思维实现动画 2.2.绘制路径 2.3.绘制圆弧(动态圆形 ...

  5. HTML5中canvas实现拼图游戏,HTML5 Canvas学习笔记(6)拼图游戏(数字版)

    今天网上发现了一段代码,只有界面,很不错,学习了并完成了逻辑. 效果图: 点击这里试玩 http://www.108js.com/article/canvas/6/play.html 欢迎访问博主的网 ...

  6. Android Bitmap和Canvas学习笔记

    位图是我们开发中最常用的资源,毕竟一个漂亮的界面对用户是最有吸引力的. 1. 从资源中获取位图 可以使用BitmapDrawable或者BitmapFactory来获取资源中的位图. 当然,首先需要获 ...

  7. html坐标绘制路径,canvas学习笔记之绘制简单路径

    1 线段(直线路径) 绘制线段一般步骤: moveTo(x,y) 移动画笔到指定的坐标点(x,y) lineTo(x,y) 使用直线连接当前端点和指定的坐标点(x,y) stroke() 根据当前的画 ...

  8. canvas学习笔记-贝塞尔曲线

    3.4 贝塞尔曲线 canvas提供了两个绘制贝塞尔曲线api: ctx.quadraticCurveTo(cpx, cpy, x, y); 二次贝塞尔曲线,(cpx, cpy)控制点 (x, y)终 ...

  9. Canvas学习笔记及像素操作——实现马赛克

    绘制文本 window.onload = function () {//获取画布var canvas = document.querySelector('#test')//检查支持性if (canva ...

最新文章

  1. c 异常 java异常_C ++和Java中异常处理的比较
  2. VC 内联汇编中的一个注意事项
  3. 要做的题目-要用到hadoop资源
  4. 在软盘上找不到id地址标记_记录一下我的群辉使用腾讯云域名解析IPv6地址
  5. 当我们群嘲假博士时,不要忘了真博士们的艰辛
  6. 闲鱼发布2020租房报告:每天近万人在闲鱼找室友
  7. 哥德巴赫猜想用计算机证明,用计算机证明有限数哥德巴赫猜想成立:运行结果...
  8. Java普通工程转换成标准的maven工程
  9. Effective C++ 之 Item 5:了解C++默默编写并调用哪些函数
  10. android系统签名一样不,解决Android应用签名和系统不一致的问题
  11. PR视频剪辑教学,基础工具学习教程「附软件」码住。
  12. 【自动驾驶】模型预测控制(MPC)实现轨迹跟踪
  13. V Rising 服务器搭建
  14. eclipse 注销快捷键
  15. UEFI原理与编程实践-PROTOCOL
  16. python绘制图像并渲染_用Python的Matplotlib模块绘制3D图像
  17. CF1715D 2+ doors 题解
  18. UNIX时间戳的UTC(协调世界时)
  19. 生硬的论文,非得写什么架构设计
  20. java计算机毕业设计商品供应管理系统源码+系统+数据库+lw文档+mybatis+运行部署

热门文章

  1. 在配置SSH免密登录时报错:/usr/bin/ssh-copy-id: ERROR: failed to open ID file '/root/.pub': 没有那个文件或目录
  2. 【华为提前批】笔试 测评 面试 全流程(结构与材料工程师)
  3. 飞猪大数据:85后带来春节旅行新气氛
  4. 做快乐的程序员 - 李战 在淘宝网的一次讲座
  5. java中不可变对象(immutable object)是什么,有什么意义
  6. 分组折线图、柱状图实现(多条折线图、柱状图同时显示)实现方式
  7. [iPad]手势及分页
  8. css多种方法画四分之一圆曲线
  9. 阿里云对象存储服务OSS前后联调
  10. Web Services 简介