canvas必备基础
推荐2个好的学习canvas的地址,一个是mdn的官网,另一个是阮一峰的canvas相关大作。
现在主要针对上面的资料说几点:
canvas的本质
<canvas>
元素用于生成图像。它本身就像一个画布,JavaScript 通过操作它的 API,在上面生成图像。它的底层是一个个像素,基本上是一个可以用 JavaScript 操作的位图(bitmap)。
它与 SVG 图像的区别在于,是脚本调用各种方法生成图像,SVG 则是一个 XML 文件,通过各种子元素生成图像。
绘制图形
绘制矩形
下面展示
// 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段)
// 绘制一个填充的矩形
// fillRect(x, y, width, height)
//绘制一个矩形的边框
// strokeRect(x, y, width, height)
// 绘制一个矩形的边框
// 清除指定矩形区域,让清除部分完全透明。
<html> <head> <style> body { background: gray; } </style> </head> <body> <canvas id="canvas" width="450" height="450"></canvas> <script type="application/javascript"> //<canvas> 只支持两种形式的图形绘制:矩形和路径(由一系列点连成的线段) // 绘制一个填充的矩形 // fillRect(x, y, width, height) //绘制一个矩形的边框 // strokeRect(x, y, width, height) // 绘制一个矩形的边框 // 清除指定矩形区域,让清除部分完全透明。 // clearRect(x, y, width, height) var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; // 绘制一个填充的矩形。 ctx.fillRect(10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; // 绘制一个矩形的边框 ctx.strokeRect(130, 130, 155, 150); //绘制一个空白的矩形 ctx.fillStyle = 'red'; ctx.clearRect(45, 45, 60, 60); } </script> </body> </html>
绘制三角形
常用的api
以下方法和属性用来绘制路径。
`CanvasRenderingContext2D.beginPath():开始绘制路径。
CanvasRenderingContext2D.closePath():结束路径,返回到当前路径的起始点,会从当前点到起始点绘制一条直线。如果图形已经封闭,或者只有一个点,那么此方法不会产生任何效果。
CanvasRenderingContext2D.moveTo():设置路径的起点,即将一个新路径的起始点移动到(x,y)坐标。
CanvasRenderingContext2D.lineTo():使用直线从当前点连接到(x, y)坐标。
CanvasRenderingContext2D.fill():在路径内部填充颜色(默认为黑色)。
CanvasRenderingContext2D.stroke():路径线条着色(默认为黑色)。
CanvasRenderingContext2D.fillStyle:指定路径填充的颜色和样式(默认为黑色)。
CanvasRenderingContext2D.strokeStyle:指定路径线条的颜色和样式(默认为黑色)。`
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>绘制三角形</title> </head> <body onload="draw();"> <canvas id="canvas" width="150" height="150"></canvas> </body> <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.beginPath(); //设置路径的起点,即将一个新路径的起始点移动到(x,y)坐标。 ctx.moveTo(75, 50); //使用直线从当前点连接到(x, y)坐标。 ctx.lineTo(100, 75); ctx.lineTo(100, 25); //在路径内部填充颜色(默认为黑色) ctx.fill(); } } </script> </html>
绘制圆形
CanvasRenderingContext2D.arc():通过指定圆心和半径绘制弧形。
CanvasRenderingContext2D.arcTo():通过指定两根切线和半径绘制弧形。
CanvasRenderingContext2D.arc()主要用来绘制圆形或扇形。
用arc函数绘制不同的圆弧 var canvas = document.getElementById('game'); var ctx = canvas.getContext('2d'); ctx.filSytle = "rgba(200,200,100,0.6)"; //绘制下半圆 ctx.beginPath(); ctx.arc(100,110,50,0,Math.PI); ctx.closePath(); ctx.fill(); //绘制上半圆 ctx.beginPath(); ctx.arc(100,90,50,0,Math.PI,true); ctx.closePath(); ctx.fill(); //绘制左半圆 ctx.beginPath(); ctx.arc(230,100,50, Math.PI/2,Math.PI*3/2); ctx.closePath(); ctx.fill(); //绘制右半圆 ctx.beginPath(); ctx.arc(250, 100, 50 , Math.PI*3/2, Math.PI/2); ctx.closePath(); ctx.fill(); // 绘制一个接近于圆的形状 ctx.beginPath(); ctx.arc(180, 240, 50 , Math.PI*7/6, Math.PI*2/3); ctx.closePath(); ctx.fill(); // 绘制一段小圆弧 ctx.beginPath(); ctx.arc(150, 250, 50 , Math.PI*7/6, Math.PI*2/3, true); ctx.closePath(); ctx.fill();
推荐这篇文字介绍的arc参数很详细:
绘制图像CanvasRenderingContext2D.drawImage()
Canvas API 允许将图像文件写入画布,做法是读取图片后,使用drawImage()方法将这张图片放上画布。
CanvasRenderingContext2D.drawImage()有三种使用格式。
ctx.drawImage(image, dx, dy);
ctx.drawImage(image, dx, dy, dWidth, dHeight);
ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
image:图像元素
sx:图像内部的横坐标,用于映射到画布的放置点上。
sy:图像内部的纵坐标,用于映射到画布的放置点上。
sWidth:图像在画布上的宽度,会产生缩放效果。如果未指定,则图像不会缩放,按照实际大小占据画布的宽度。
sHeight:图像在画布上的高度,会产生缩放效果。如果未指定,则图像不会缩放,按照实际大小占据画布的高度。
dx:画布内部的横坐标,用于放置图像的左上角
dy:画布内部的纵坐标,用于放置图像的右上角
dWidth:图像在画布内部的宽度,会产生缩放效果。
dHeight:图像在画布内部的高度,会产生缩放效果。
图片从顶点铺到画布上
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>图像处理</title> <!-- ctx.drawImage(image, dx, dy);--> <!-- ctx.drawImage(image, dx, dy, dWidth, dHeight);--> <!-- ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);--> </head> <body> <canvas id="myCanvas"></canvas> <script> // var canvas = document.getElementById('myCanvas'); // var ctx = canvas.getContext('2d'); // var img = new Image(); // img.src = 'https://img-home.csdnimg.cn/images/20220921102650.png'; // img.onload = function () { // ctx.drawImage(img, 0, 0); // }; var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); var image = new Image(60, 45); image.onload = drawImageActualSize; image.src = '../images/2.png'; function drawImageActualSize() { canvas.width = this.naturalWidth; canvas.height = this.naturalHeight; ctx.drawImage(this, 0, 0, this.naturalWidth, this.naturalHeight); } </script> </body> </html>
图片从设置(x,y)开始铺到画布上
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>practice9-DrawImage</title> <style type="text/css"> *{ padding:0; margin: 0; } body{ text-align: center; padding-top: 20px; } canvas{ box-shadow: 0 0 10px #333333; margin: 0 auto; } </style> </head> <body onload="draw()"> <canvas id="canvas" width="800" height="600"></canvas> <script> function draw(){ var ctx = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); //定义图片 var img = new Image(); img.src = '../images/2.png'; //确保图片被加载完成 img.onload = function() { //使用drawImage绘制到画布上面 ctx.drawImage(this,5,5); } }else{ alert('请更新浏览器!!!'); } } </script> </body> </html>
图像定制大小 铺到画布上
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>practice9-DrawImage</title> <style type="text/css"> *{ padding:0; margin: 0; } body{ text-align: center; padding-top: 20px; } canvas{ box-shadow: 0 0 10px #333333; margin: 0 auto; } </style> </head> <body onload="draw()"> <canvas id="canvas" width="800" height="600"></canvas> <!--用法二:定图像的宽度和高度,将图像放大或者缩小--> <!--context.drawImage(img,x,y,width,height);--> <script> function draw(){ var ctx = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); //定义图片 var img = new Image(); img.src = '../images/2.png'; //确保图片被加载完成 img.onload = function() { //使用drawImage绘制到画布上面 ctx.drawImage(this,50,50,300,300); } }else{ alert('请更新浏览器!!!'); } } </script> </body> </html>
画布是800x600.
ctx.drawImage(this,50,50,300,300);图像从(50,50)坐标开始铺图像只显示宽300高300.
绘制图像时候,画布和图像都在动
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>practice9-DrawImage</title> <style type="text/css"> *{ padding:0; margin: 0; } body{ text-align: center; padding-top: 20px; } canvas{ box-shadow: 0 0 10px #333333; margin: 0 auto; } </style> </head> <body onload="draw()"> <canvas id="canvas" width="800" height="600"></canvas> <script> function draw(){ var ctx = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); //定义图片 var img = new Image(); img.src = '../images/2.png'; //确保图片被加载完成 img.onload = function() { //使用drawImage绘制到画布上面 ctx.drawImage(this,100,100,100,100,50,50,700,500); } }else{ alert('请更新浏览器!!!'); } } </script> </body> </html>
绘制文字
CanvasRenderingContext2D.fillText(text, x, y [, maxWidth])
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>绘制文字</title> </head> <body> <canvas id="myCanvas"></canvas> <script> var canvas = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); //(填充的字符串,横坐标,纵坐标) ctx.fillText('Hello world', 50, 50); </script> </body> </html>
好了有了上面的知识后,就开始实战了。
实战: canvas绘制图像并标注算法框
比如我这里有个算法:
格式为:
var dtcoord = [{x: 50, y: 50, w: 100, h: 100, txt: "抽烟", conf: "0.38"},{x: 100, y: 200, w: 120, h: 100, txt: "抽烟", conf: "0.95"}]; var gtcoord = [{x: 20, y: 20, w: 100, h: 100, txt: "未带安全帽", conf: "0.93"},{x: 260, y: 260, w: 100, h: 100, txt: "未带安全帽", conf: "0.92"}];
要实现的效果为:
- 红色框标注抽烟算法,
- 黄色框标注未带安全帽算法
源码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div class="item-img"> <canvas id="myCanvas" width="1280" height="650"> </canvas> </div> <!--原文链接:https://blog.csdn.net/weixin_43994675/article/details/119763634--> </body> <!--推荐2个网站:https://www.bookstack.cn/read/webapi-tutorial/spilt.5.docs-websocket.md--> <!--https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Using_images--> <script> var dtcoord = [{x: 50, y: 50, w: 100, h: 100, txt: "抽烟", conf: "0.38"},{x: 100, y: 200, w: 120, h: 100, txt: "抽烟", conf: "0.95"}]; var gtcoord = [{x: 20, y: 20, w: 100, h: 100, txt: "未带安全帽", conf: "0.93"},{x: 260, y: 260, w: 100, h: 100, txt: "未带安全帽", conf: "0.92"}]; queryCanvasInfo(); //获取canvas节点 function queryCanvasInfo() { var c = document.getElementById("myCanvas"); var ctx = c.getContext('2d'); //定义图片 var img = new Image(); createCanvasImg(c, ctx, img, "2.png"); } //创建图片画布 function createCanvasImg(c, ctx, img, imgURL) { img.src = imgURL; img.onload = () => { //图片加载时 ctx.clearRect(0, 0, c.width, c.height); //清空这个范围的画布 let a = img.width / img.height; //计算原始图片的宽高比例 console.log(img.width, img.height, 999); if (img.width > img.height) { //当图片宽度大于高度则写死宽度按高度调整比例 maxW = c.width; //最大宽度要等于画布的宽度 maxH = maxW / a; } else { //相反 (maxH = c.height), (maxW = maxH * a); } times = img.width / maxW; //计算原图与canvas的比例 canvasInfo(maxW, maxH, img, ctx); //重新绘制图片 }; } //绘制图片 function canvasInfo(maxW, maxH, img, ctx) { let w = maxW, //计算缩放的宽度 h = maxH; //计算缩放的高度 ctx.drawImage( img, //图片实例 0, 0, //x轴y轴的边距 w, h //图片的宽高 ); canvasRect(dtcoord, "dt", ctx); canvasRect(gtcoord, "gt", ctx); } //标注框绘制 function canvasRect(list, txt, ctx) { list.forEach((item) => { console.log(item) if (!item) return; x = Number(item.x) / times, y = Number(item.y) / times, w = Number(item.w) / times, h = Number(item.h) / times; ctx.lineWidth = "2"; //框的粗细 if (txt == "gt") { ctx.strokeStyle = "yellow"; //gt选中的标注框为红色 } else { ctx.strokeStyle = "red"; //dt选中的标注框为红色 } console.log(2222) //开始绘制 console.log(x, y, w, h) ctx.strokeRect(x, y, w, h); //文本 //CanvasRenderingContext2D.fillText(text, x, y [, maxWidth]) ctx.fillStyle = '#fff'; ctx.fillText(item.conf, (x + w/2) , y-2); // ctx.beginPath(); // ctx.moveTo(x-, y); // ctx.lineTo(x+w, y); // ctx.lineTo(x+w, y+h); // ctx.lineTo(x, y+h); // ctx.fill() }); } </script> </html>
本文主要介绍了canvas的基础知识,简单使用,最后来一个算法标注框的实现案例。
完