熬夜总结了 “HTML5画布” 的知识点(万字长文,建议收藏)
感谢哪吒的投稿
前言
html5Canvas的知识点,是开发的必备技能,在实际工作中也常常会涉及到。
最近熬夜总结html5Canvas相关的知识点,大家一起看一下吧:
1.html5Canvas基础知识
Canvas是什么?翻译过来是画布的意思 Canvas元素用于在网页上绘制2D图形和图像 
Canvas使用的场景有:1,动画;2,H5游戏;3,图表。
效果动画,加载Loading:

H5游戏效果:

对于Canvas需要掌握:
使用Canvas画直线,矩形,圆形以及设置它们的样式。 
Canvas中的图形变换,渐变,文字和图片。 
Canvas的像素获取,阴影和曲线绘制以及区域的剪辑。 Canvas动画,交互和离屏技术。 
canvas默认大小,300*150 通过HTML,css,JavaScript设置width和height的区别 HTML和JavaScript设置的画布大小 css设置的是画布缩放后的大小 坐标系原点及方向(原点在左上角,向右为x方向,向下为y方向) 
画直线,矩形和原型
画直线: ctx.moveTo(x1,y1),ctx.lineTo(x2,y2)画圆形: ctx.arc(x,y,radius,0,Math.PI*2,true)画矩形:可以通过直线来画,也可以直接用( ctx.strokeRect(x1,y1,x2,y2)
beginPath和closePath
beginPath和closePath并不是成对出现的 beginPath的作用是开始一条新路径 closePath的作用是使当前路径闭合 
描边和填充样式
strokeStyle用来设置画笔样式,也就是直线,曲线,边框的样式 fillStyle用来设置 填充样式 lineWidth用来设置线条的粗细 
Canvas中的图形变换,渐变,文字和图片
Canvas中的图像变换 Canvas中的渐变 Canvas中的文字 Canvas中的图片 
Canvas中的图形变换
图形变换都是针对坐标系来说的:
平移: ctx.translate(x,y)旋转: ctx.rotate(rad)缩放: ctx.scale(x,y)
save和restore
用来保存和恢复上下文的环境ctx,一般成对出现
ctx.save(),保存当前上下文环境。ctx.restore(),恢复到上一次的上下文环境
Canvas中的渐变
线性渐变: ctx.createLinearGradient(xStart,yStart,xEnd,yEnd)
(xStart,yStart)是线段的起点,(xEnd,yEnd)是线段终点。起点到终点之间的颜色呈渐变。
gradient.addColorStop可以来控制渐变的颜色渐变可以理解为一种颜色
径向渐变:
ctx.createRadialGradient(xStart,yStart, radiusStart,xEnd,yEnd,radiusEnd);
(xStart,yStart)是第一个圆的原心,radiusStart是第一个圆的半径,(xEnd,yEnd)是第二个圆的原心,radiusEnd是第二个圆的半径
第一圆到第二个圆之间的颜色呈现渐变。
Canvas中的文字
描边文字:ctx.strokeText(text,x,y)
填充文字:ctx.fillText(text,x,y);
设置字体样式:ctx.font
例如: ctx.font="bold 100px sans-serif"设置水平对齐方式: ctx.textAlignleft,start,左对齐,center居中对齐,end,right,右对齐 
设置垂直对齐方式:ctx.textBaseline
top,顶对齐,middle,居中,bottom,底部对齐 计算文本宽度: ctx.measuerText(text).width须在设置字体样式之后计算
Canvas图片
绘制图片3种方法
ctx.drawImage(image,x,y),该方法把图片绘制在(x,y)处ctx.drawImage(image,x,y,w,h),该方法把图片绘制在(x,y)处,并缩放为宽w,高hctx.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh),该方法把图片中(sx,sy)处的宽sw,高sh的区域,绘制到(dx,dy)处,并缩放为宽dw,高dh
在image加载完成之后绘制:


示例:
var img = new Image();img.src = 'logo.png';img.onload = function() {ctx.drawImage(img,0,0,40,40,0,0,80,80);}
Canvas绘制
Canvas的图形绘制和像素获取 Canvas阴影绘制 Canvas剪辑区域 Canvas曲线绘制 
Canvas图形画刷
ctx.createPattern可以创建一个画刷模式,进而可以设置到fillStyle里,进行画刷的填充。
函数原型: ctx.createPattern(image,type)
type取值:
no-repeat不平铺repeat-x橫方向平repeat-y纵方向平铺repeat全方向平铺
Canvas像素操作
获取像素 
var imageData = ctx.getImageData(x,y,w,h)返回的是一维数组:[r1,g1,b1,a1,r2,g2,b2,a2...]
设置像素 
ctx.putImageData(imageData,x,y)把imageData放在(x,y)处
设置像素 
ctx.putImageData(imageData, x, y, dirtyX, dirtyY, dirtyW, dirtyH)只显示(dirtyX,dirtyY)处的宽dirtyW,dirtyH的区域
Canvas阴影绘制
ctx.shadowOffsetX:阴影x方向的偏移距离ctx.shadowOffsetY:阴影y方向的偏移距离ctx.shadowColor:阴影的颜色ctx.shadowBlur:阴影的模糊半径效果图:

Canvas剪辑区域
设置一个路径; 调用ctx.clip(); 再绘制图形。 
Canvas绘制曲线
狐线:
context.arc(x,y,radius, starAngle,endAngle, anticlockwise)圆心(x,y) 半径radius从starAngle到endAngleanticlockwise代表是否逆时针方向
生成工具
Canvas Quadratic Curve Example

http://blogs.sitepointstatic.com/examples/tech/canvas-curves/quadratic-curve.html
http://blogs.sitepointstatic.com/examples/tech/canvas-curves/bezier-curve.html
二次样条曲线:
context.quadraticCurveTo(qcpx,qcpy, qx,qy)贝塞尔曲线:
context.bezierCurveTo(cp1x,cp1y, cp2x, cp2y, x,y)Canvas动画,Canvas离屏技术 
ctx.clearRect(x,y, width,height)
清除(x,y)点起, 宽width,高height的区域,用于重新绘制
离屏技术是什么:通过在离屏Canvas中绘制元素,再复制到显示Canvas中,从而大幅提高性能的一种技术。

使用离屏技术:


静态场景绘制特别耗资源,动态场景绘制简单。为了不每次更新动态场景的时候,都去绘制静态场景。 一般把静态场景绘制在离屏canvas上,更新动态场景的时候,把静态场景copy过来,而不是重新绘制。 
离屏技术:
一个Canvas中的图形绘制到另一个Canvas方法:
ctx.drawImage(canvas,x,y),该方法把canvas绘制在(x,y)处ctx.drawImage(canvas,x,y, w,h),该方法把canvas绘制在(x,y)处,并缩放为宽w,高hctx.drawImage(canvas, sx, sy, sw, sh, dx, dy, dw, dh),该方法把canvas中(sx, sy)处的宽sw,高sh的区域,绘制到(dx,dy)处,并缩放为宽dw, 高dh
对canvas插件的相关了解
什么是Canvas插件,掌握Chart.js插件,了解Chartist.js和HighCharts.js插件
(图表)Chart.js插件:https://www.chartjs.org/
Chartist.js插件是一个简单的响应式图表插件:支持SVG格式(http://gionkunz.github.io/chartist-js/)
HighCharts.js插件:方便快捷的HTML5交互性图标库:https://www.highcharts.com/
Chartist.js插件与HighCharts.js插件
Chartist.js配置简单,css和JavaScript分离,响应式图表,支持不同的浏览器尺寸和分辨率。 HighCharts.js,兼容当今所有的浏览器,包含iPhone,IE,火狐等。 
响应式布局,它的用户体验友好,响应式网站可以根据不同终端,不同尺寸和不同应用环境,自动调整界面布局,展示内容,提供非常好的视觉效果。响应式布局就是一个网站能够兼容多个终端
2. 构建Canvas元素
示例:
#canva {border: 1px solid red;}// 绘制宽高200的canvas
使用JavaScript实现绘图的流程 
在开始绘图时,先要获取Canvas元素的对象,在获取一个绘图的上下文。
获取Canvas对象 ,使用document对象的getElementById()方法获取。
var canvas = document.getElementById("canvas")可以使用通过标签名称来获取对象的getElementsByTagName方法
创建二维的绘图上下文对象 
使用getContext()方法来获取
var context  = canvas.getContext("2d")在Canvas上绘制文字 
context.font="98px 黑体"; // 文字样式context.fillStyle="red"; // 文字颜色context.textAlign = "center"; // 文字对齐方式// 绘制文字context.fillText("达达前端",100, 123, 234);
绘制图像:


使用drawImage()方法可以将图像添加到Canvas画布中,绘制一幅图像,需要有三个重载的方法:
使用:
drawImage(image, x, y)// 在画布上定位图像// 方法在画布上绘制图像、画布或视频。// 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸。drawImage(image, x, y, width, height)// 在画布上定位图像,并规定图像的宽度和高度drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight)// 剪切图像,并在画布上定位被剪切的部分
参数:
| 参数 | 描述 | 
|---|---|
| image | 规定要使用的图像,画布或视频 | 
| sourceX | 开始剪切的x坐标位置 | 
| sourceY | 开始剪切的y坐标位置 | 
| sourceWidth | 被剪切图像的宽度 | 
| sourceHeight | 被剪切图像的高度 | 
| destX | 在画布上放置图像的 x 坐标位置 | 
| destY | 在画布上放置图像的 y 坐标位置 | 
| destWidth | 要使用的图像的宽度 | 
| destHeight | 要使用的图像的高度 | 
插入图像:

function Draw() {// 获取canvas对象var canvas = document.getElementById("canvas");// 获取2d上下文绘图对象var context = canvas.getContext("2d");// 使用Image()构造函数创建图像对象var newImg = new Image();// 指定图像的文件地址newImg.src = "../images/dadaqianduan.jpg";newImg.onload = function () {// 左上角开始绘制图像context.drawImage(newImg, 0, 0);context.drawImage(newImg, 250, 100, 150, 200);context.drawImage(newImg, 90, 80, 100, 100, 0, 0, 120, 120);}}
在Canvas中绘制文字“达达前端”:
// canvas 宽高200canvas {border: 2px solid #ccc;}
3.绘制矩形
两个方法:
strokeRect() - 矩形边框 fillRect() - 填充矩形区域 strokeStyle - 设置线条的颜色 lineWidth - 设置线条宽度,默认宽度为1,单位是像素 fillStyle - 设置区域或文字的填充颜色 
绘制矩形边框,使用strokeStyle方法:
// 绘制矩形边框strokeRect(x,y, width, height);
填充矩形区域,使用fillRect()方法:
// 填充矩形区域fillRect(x,y,width,height);
绘制矩形
// 绘制矩形function drawRect() {var canvas = document.getElementById("canvas");var context = canvas.getContext("2d");// 描边context.strokeStyle = "#000";// 线条宽度context.lineWidth = 1;// 矩形边框context.strokeRect(50,50, 150, 100);// 填充context.fillStyle="#f90";// 矩形context.fillRect(50,50,150,100);}window.addEventListener("load",DrawRect,true);
使用clearRect方法,可以擦除指定的矩形区域:
// 擦除指定的矩形区域context.clearRect(x,y,width,height)
4.体验canvas绘图
在实际开发中,画布是默认300*150的大小。

示例:
// 为画布设置边框canvas {border: 1px solid #ccc;}// 准备画布,默认是300*150// 设置画布的大小// 准备绘制工具
如果使用css设置宽高,画布会按照300*150的比例进行缩放,将300*150的页面显示在400*400的容器中。
// 设置画布宽度var cx = canvas.width = 400;var cy = canvas.height = 400;
使用js动态设置宽高。
建议使用HTML中的width和height,或者js动态设置宽高
创建一个canvas标签,第一步:
// 获取这个canvas的上下文对象var canvas = document.getElementById('canvas');var context = canvas.getContext('2d');
方法:
fill()填充路径stroke()描边arc()创建圆弧rect()创建矩形fillRect()绘制矩形路径区域strokeRect()绘制矩形路径描边clearRect()在给定的矩形内清除指定的像素beginPath()起始一条路径,或重置当前路径moveTo()把路径移动到画布中的指定点,不创建线条lineTo()添加一个新点,在画布中创建从该点到最后指定点的线条clip()从原始画布剪切任意形状和尺寸的区域arcTo()创建两切线之间的弧/曲线quadraticCurveTo()创建二次方贝塞尔曲线bezierCurveTo()创建三次方贝塞尔曲线isPointInPath()如果指定的点位于当前路径中,则返回 true,否则返回 false
辅助线绘制弧线:arcTo() 方法
语法:
// 辅助线绘制弧线arcTo(x1, y1, x2, y2, radius)
arcTo()方法绘制一条弧线
代码:
// 绘制一条弧线function draw() {var canvas = document.getElementById('canvas');var context = canvas.getContext('2d');// 开始绘制context.beginPath();// 移动点context.moveTo(80, 120);// 绘制线条context.lineTo(150, 60);context.lineTo(180, 130);// 描边context.strokeStyle="rgba(0,0,0,0.4)";context.lineWidth=2;context.stroke();context.beginPath();context.moveTo(80,120);context.arcTo(150,60,180,130,50);context.strolkeStyle="rgba(255,135,0,1)";context.stroke();}
绘制二次样条曲线
quadraticCurveTo()方法:
quadraticCurveTo(cpX, cpY, x, y);// cpX, cpY描述了控制点的坐标,x, y描述了曲线的终点坐标
绘制贝济埃曲线
bezierCurveTo()方法:它是应用于二维图形应用程序的数学曲线。
bezierCurveTo(cp1X, cp1Y, cp2X, cp2Y, x, y);// cp1X, cp1Y 表示第一个控制点的坐标// cp2X, cp2Y 表示第二个控制点的坐标// x, y表示曲线的终点坐标
绘制曲线:
function draw() {// 绘制曲线var canvas = document..getElementById('canvas');var context = canvas.getContext('2d');// 开始绘制context.beginPath();// 移动context.moveTo(100,180);// 连线context.lineTo(110,80);context.moveTo(260,100);context.lineTo(300,200);// 描边context.strokeStyle="rgba(0,0,0,0.4)";// 设置宽度context.lineWidth=3;context.stroke();context.beginPath();context.moveTo(100,180);// 绘制贝济埃曲线context.bezierCurveTo(110,80,260,100,300,200);// 设置宽度context.lineWidth = 3;context.strokeStyle="rgba(255,135,0,1)";context.stroke();}
四分之一圆

var canvas = document.getElementById('canvas');var context = canvas.getContext('2d');// 画布宽度200var canX = canvas.width = 200var canY = canvas.height = 200;// 开始绘制context.beginPath();// 四分之一圆context.arc(100, 100, 50, 0, Math.PI*0.5, false);context.strokeStyle="white"context.stroke();context.beginPath();context.lineTo(200, 200);context.lineTo(200, 100);context.lineTo(100,50);context.strokeStyle = '#fff';context.stroke();
lineCap设置或返回线条的结束断点样式lineJoin设置或返回两条线相交时,产生拐角类型lineWidth设置或返回当前的线条宽度miterLimit设置或返回最大斜接长度
fillRect()绘制一个实心矩形strokeRect()绘制一个空心矩形
设置阴影,shadowBlur -context.shadowBlur = 20
createLinearGradient()创建线性渐变createPattern()在指定的方向上重复指定的元素createRadialGradient()创建放射状/环形的渐变addColorStop()规定渐变对象中的颜色和停止位置
gradient.addColorStop(stop,color)scale()缩放当前绘图变大或变小rotate()旋转当前绘图translate()重新映射画布的(0,0)位置
6.使用图像
使用三种方法插入图像
function draw() {var canvas = document.getElementById('canvas');var context = canvas.getContext('2d');// image实例var newImg = new Image();newImg.src='../images/dada.jpg' // 指定图像的文件地址newImg.onload = function(){// 绘图context.drawImage(newImg, 0, 0);context.drawImage(newImg, 250,100, 150,200);context.drawImage(newImg, 90,80,100,100,0,0,120,120);}}
在插入图像之前,需要考虑图像加载的时间,如果图像没加载完成就已经执行drawImage()方法,就不会显示任何图片。
7.绘制渐变
提供了两种渐变的创建的方法:
// 创建线性渐变createLinearGradient()方法// 创建径向渐变createRadialGradient()方法
设置渐变颜色和过渡方式
语法如下:
offset是一个范围在0.0到1.0之间的浮点值 表示渐变的开始点和结束点之间的一部分 offset的0为开始点,1为结束点 
addColorStop(offset, color);绘制线性渐变的矩形
function draw() {var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')// 创建渐变对象,线性渐变var grd = context.createLinearGradient(0,0,300,0)// 设置渐变颜色grd.addColorStop(0, '#xxx'); // 设置颜色grd.addColorStop(1, '#xxx'); // 设置颜色// 将填充样式设置为线性渐变对象context.fillStyle = grd;context.fillRect(0,0,300,80);}
绘制径向渐变的矩形
function draw() {var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')// 径向渐变var grd = context.createRadialGradient(50,50,0,100,100,90);// 设置渐变颜色以及方式grd.addColorStop(0,'#xxx');grd.addColorStop(1,'#xxx');context.fillStyle = grd;context.beginPath();// 圆形context.arc(100,100,90,0,Math.PI*2,true);context.fill();}
描边属性
线帽属性:lineCap,表示指定线条的末端如何绘制值:lineCap: butt, round, square,当线条具有一定的宽度才能表现出来。
butt// 定义了线段没有线帽round// 定义了线段的末端为一个半圆形的线帽square// 定义了线段的末端为一个矩形的线帽
线条的连接属性lineJoin,用于两条线条到的连接方式:
miter两条线段的外边缘一直延伸到它们相交,属性miterLimit是用来描述如何绘制两条线段的交点,是表示延伸长度和线条长度的比值。
默认为10,只有miter使用时有效
lineJoin = [value];round// 两条线段的外边缘应该和一个填充的弧结合bevel// 两条线段的外边缘应该和一个填充的三角形相交
8.模式
语法如下:
createPattern(image, repetitionStyle)repeat表示图像在各个方向上循环平铺repeat-x表示图像在横向上循环平铺repeat-y表示图像在纵向上循环平铺no-repeat表示图像只使用一次
function draw() {var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')var img = new Image();// 使用Image()构造函数创建图像对象img.src='../images/xxx'// 指定图像的文件地址img.onload = function() {// 绘图模式var ptrn = context.createPattern(img, 'repeat');// 填充样式context.fillStyle = ptrn;// 填充矩形context.fillReat(0,0,500,200);}}
移动变化:
// 移动translate(dx,dy);// 绘制function draw() {var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')// 设置移动偏移量context.translate(200, 200);// 绘制一个圆形ArcFace(context);}// 绘制一个圆形function ArcFace(context) {// 绘制一个圆形边框context.beginPath();// 绘制圆形context.arc(0,0,90,0,Math.PI*2,true);// 线宽context.lineWidth=5;// 描边context.strokeStyle='#f90';context.stroke();// 绘制context.beginPath();context.moveTo(-30, -30);context.lineTo(-30, -20);context.moveTo(30, -30);context.lineTo(30, -20);context.moveTo(-20, 30);// 曲线context.bezierCurveTo(-20, 44, 20, 30, 30, 20);context.strokeStyle='#000';context.lineWidth=10;context.lineCap = 'round';// 笑脸?context.stroke();}
缩放变换,语法如下:
scale(sx, sy);// sx为水平方向上的缩放因子,sy为垂直方向上的缩放因子
// 示例function draw() {var canvas = document.getElementById('canvas')var context = canvas.getContent('2d')// 移动context.translate(200,200);// 缩放context.scale(0.5,0.5);ArcFace(context);}
旋转变换:
rotate(angle)// 旋转例子function draw() {var canvas = document.getElementById('canvas');var context = canvas.getContext('2d')context.translate(200,200);// 旋转context.rotate(Math.PI/6);context.scale(0.5, 0.5)ArcFace(context)}
矩形变形,语法如下:
transform(m1x,m1y,m2x,m2y,dx,dy); // 移动,缩放,旋转1. 移动translate (dx, dy)2. 缩放scale (sx,sy)3. 旋转rotate (A)
9.使用文本
绘制文本的方法:
fillText(text, x, y, maxwidth)strokeText(texxt, x, y, maxwidth)
text表示要绘制的文本参数x表示绘制文字的起点横坐标 参数y表示绘制文字的起点纵坐标 参数 maxwidth表示显示文本的最大宽度
文本属性表:
| 属性 | 说明 | 
|---|---|
| font | 数组字体样式 | 
| textAlign | start,end,left,right,center | 
| textBaseline | top,hanging,middle,alphabetic,ideographic,bottom | 
绘制文本
// 绘制文本示例function draw() {var canvas = document.getElementById('canvas')var context = canvas.getContext('2d')// 填充颜色context.fillStyle = '#000';context.font = 'bold 12px impact';// 绘制文本context..fillText('达达前端,魔王哪吒', 10, 10);context.strokeStyle = '#000';context.font = 'bold italic 12px impact';// 绘制文本context.strokeText('jeskson', 10, 10);}
绘制获取文本宽度的measureText()方法:
measureText(text)测量文本的宽度:
function draw() {var canvas = document.getElementById('canvas');var context = canvas.getContext('2d');context.fillStyle='#000';context.font='bold 10px impact';// 测量文本的宽度var tm = context.measureText(txt);context.fillText(txt,10,10);context.fillText(tm.width, tm.width+10, 50);context.strokeStyle = '#000';context.font = 'bold italic 10px impact';// 测量文本的宽度tm = context.measureText(txt);context.strokeText(txt,10,10);context.strokeText(tm.width, tm.width+10, 100);}
阴影效果
阴影属性表:
| 属性 | 说明 | 
|---|---|
| shadowColor | 使用半透明颜色 | 
| shadowOffsetX | 阴影的横向位移量 | 
| shadowOffsetY | 阴影的纵向位移量 | 
| shadowBlur | 高斯模糊 | 
状态保存和恢复
状态保存方法 save()状态恢复方法 restore(),恢复最后一次保存的状态
状态的保存和恢复是通过数据栈进行的
10.操作像素
图像数据对象 ImageData获取图像数据的方法 getImageData(),用于从Canvas上下文中获取图像数据。getImageData(sx, sy, sw, sh);绘制图像数据的方法 putImageData()getImageData(imagedata,dx,dy[,..])创建图像数据的方法 createImageData()
绘制海报
// 画布// 效果图// 按钮长按图片发送给朋友 data() {return {tempImgShow: false,tempImg: '',cansWh: { // 画布宽高cansWidth: 800,cansHeight: 900,},qrcode: { // 举例二维码top: 0.85,left: 0.035,width: 0.23,qrHeight: null,},...productImg: { // 产品图top: 0.1,left: 0.03,width: 1,height: 0.5,},};},
// 绘制图drawImg(method,param){return new Promise((resolve, reject)=>{if(param.url.indexOf('http') === 0){uni.downloadFile({url: param.url,success(res) {param.url = res.tempFilePathmethod(param).then(res=>{resolve(res)}).catch(err=>{reject(err)})},fail(error) {console.log(error)}})}else{method(param).then(res=>{resolve(res)}).catch(err=>{reject(err)})}})}
// 绘制圆形drawCircle(param) {var that = this,x = param.x,y = param.y,r = param.r,url = param.url;return new Promise((resolve, reject) => {x = Math.ceil(that.cansWh.cansWidth * x);y = Math.ceil(that.cansWh.cansHeight * y);r = r > 1 ? r : Math.ceil(that.cansWh.cansWidth * r);that.ctx.save();var d = 2 * r;var cx = x + r;var cy = y + r;that.ctx.arc(cx, cy, r, 0, 2 * Math.PI);that.ctx.clip();that.ctx.drawImage(url, x, y, d, d);that.ctx.restore();that.ctx.draw(true, res=>{resolve();});});}
// 绘制图drawPic(item) {return new Promise((resolve, reject) => {let x, y, w, h, r;y = item.sTop <= 1 ? this.cansWh.cansHeight * item.sTop : item.sTop;w = item.sWidth <= 1 ? this.cansWh.cansWidth * item.sWidth : item.sWidth;h = item.sHeight <= 1 ? this.cansWh.cansHeight * item.sHeight : item.sHeight;if (item.sLeft == 'center') {x = item.sWidth <= 1 ? this.cansWh.cansWidth * (0.5 - item.sWidth / 2) : this.cansWh.cansWidth * 0.5 - item.sWidth /2;} else {x = this.cansWh.cansWidth * item.sLeft;}if (item.r) {r = item.r;this.ctx.save();if (w < 2 * r) r = w / 2;if (h < 2 * r) r = h / 2;this.ctx.beginPath();this.ctx.moveTo(x + r, y);this.ctx.arcTo(x + w, y, x + w, y + h, r);this.ctx.arcTo(x + w, y + h, x, y + h, r);this.ctx.arcTo(x, y + h, x, y, r);this.ctx.arcTo(x, y, x + w, y, r);this.ctx.closePath();this.ctx.clip();this.ctx.drawImage(item.url, x, y, w, h);this.ctx.restore(); // 返回上一状态} else {this.ctx.drawImage(item.url, x, y, w, h);}this.ctx.draw(true, res=>{resolve();});});}
// 保存saveCans() {let tempRatio = 1;uni.canvasToTempFilePath({x: 0,y: 0,width: this.cansWh.cansWidth * tempRatio,height: this.cansWh.cansHeight * tempRatio,destWidth: this.cansWh.cansWidth * tempRatio * 2,destHeight: this.cansWh.cansHeight * tempRatio * 2,canvasId: 'dadaPoster',success: (res) => {this.tempImg = res.tempFilePath;setTimeout(() => {this.tempImgShow = true;}, 100);uni.hideLoading();},fail: (res) => {console.log(res);uni.hideLoading();}},);}
小结
canvas标签的使用
// canvas标签的使用// 获取canvasvar canvas = document.getElementById('target')if(canvas.getContext) {var ctx = canvas.getContext('2d');}else {alert('该浏览器版本过低,请更换')}// 矩形fillRect( x , y , width , height) // 填充strokeRect( x , y , width , height) // 空心clearRect( x, y , width , height ) // 清除透明var grd = ctx.createLinearGradient( x1 ,y1 ,x2 ,y2); //线性渐变var grd = ctx.createRadialGradient(x1 ,y1 ,r1 ,x2 ,y2 ,r2);//径向渐变
曲线
二次贝塞尔曲线 quadraticCurveTo( cp1x, cp1y , x ,y )(cp1x,cp1y) 控制点 (x,y)结束点三次贝塞尔曲线 bezierCurveTo( cp1x, cp1y ,cp2x , cp2y ,x , y )(cp1x,cp1y)控制点1 (cp2x,cp2y) 控制点2 (x,y)结束点






HTML5绘图制作海报
* x:绘制图像的x坐标* y:绘制图像的y坐标* w:绘制图像的宽度* h:绘制图像的高度*/context.drawImage(img1, 0, 0, img1.width, img1.height);// 将 img2 加入画布context.drawImage(img2, 100, 100, img2.width, img2.height);// 文字填充颜色context.fillStyle = '#333';// 文字字体context.font = 'bold 45px 黑体';// 设置文字var name_text = '达达前端,魔王哪吒';// 获取文字的宽度var name_width = context.measureText(name_text).width;// 获取除去文本后的一半的宽度var x = (canvas.width - name_width) / 2;/*** context.font:设置字体样式* context.textAlign:水平对齐方式* context.textBaseline:垂直对齐方式* context.measureText(text):计算字体长度(px)*/context.fillText(name_text, x, 450);context.fillStyle = '#333'; // 文字填充颜色context.font = '25px bold 黑体';var con_1 = 'dadaqianduan';var con_2 = '达达';/*** text:要绘制的文字* x:文字起点的x坐标轴* y:文字起点的y坐标轴*/context.fillText(con_1, x, 400);var con_width_2 = context.measureText(con_2).width;context.fillText(con_2, canvas.width - x - con_width_2, 400);context.stroke();// 将画布内容导出var src = canvas.toDataURL();img3.src = src;const a = document.createElement("a");a.href = src;a.download = '自定义.png';a.click();}
html5绘图操作(html2canvas)
script引入文件html2canvas(content, { //content是将要截图的div元素scale: 2,logging: false, //在console中输出信息useCORS: true //允许跨域//proxy: string, //代理地址//timeout: number //超时时间}).then(function(canvas) {let dataUrl = canvas.toDataURL()console.log(dataUrl)})
crossOrigin属性设置成Anonymous就可以跨域? - 并不可以的哦!
后台解决跨域问题 转成 base64格式(后端,前端,建议前端)
html5移动端生成海报
大致效果:

var code_model = '', // 放置二维码canvas_model = '', // 放置canvasposter_model = '';长按保存图片至手机相册
//poster_model为效果图$("body").append(code_model, canvas_model, poster_model);$.ajax({url: "/photo/dada",data: {id: id},success: function (res) {$.hideLoading();if (res.e = "1111") {if (!res.data.is_buy) {location.href = res.data.jump_url;return false;}$(".poster").show();var data_base = res.data.poster_info;new QRCode('qrcode', {text: data_base.url,width: 100,height: 100,colorDark: '#000000',colorLight: '#ffffff',correctLevel: QRCode.CorrectLevel.H});var c = document.getElementById("myCanvas"),cxt = c.getContext("2d");var img = new Image(), imgUrl, personName = data_base.name;//跨域问题img.crossOrigin = 'anonymous';img.src = data_base.image;img.onload = function () {//图片加载为异步加载cxt.drawImage(img, 0, 0);cxt.save();cxt.beginPath();cxt.arc(100, 200, 33, 0, 2 * Math.PI, true);cxt.strokeStyle = '#fff';cxt.stroke();cxt.clip();var img_head = new Image();img_head.crossOrigin = 'anonymous';var avatar_height = data_base.avatar_height, avatar_width = data_base.avatar_width;img_head.src = data_base.avatar;img_head.onload = function () {cxt.drawImage(img_head, 0, 0, avatar_height, avatar_width, 54, 520, 80, 80);cxt.restore();var img_code = new Image();img_code.crossOrigin = 'anonymous';cxt.lineWidth = "4";cxt.strokeStyle = '#FFF';cxt.rect(80, 80, 400, 400);cxt.stroke();setTimeout(function () {img_code.src = $("#qrcode").find("img").attr("src");img_code.onload = function () {cxt.drawImage(img_code, 0, 0, 100, 100, 450, 450, 80, 80);cxt.font = '21px 黑体';cxt.fillStyle = "#000";cxt.fillText(personName, 250, 520);imgUrl = c.toDataURL("image/png", 1);$(".poster_img").attr("src", imgUrl);$(".poster_container").show();};}, 0);};};} else {$.toast(res.m, "text");}}});script>
微信小程序所使用的绘图api
CanvasContext``canvas 组件的绘图上下文
CanvasContext 是旧版的接口, 新版 Canvas 2D 接口与 Web 一致。
string|CanvasGradient fillStyle- 填充颜色string|CanvasGradient strokeStyle- 边框颜色number shadowOffsetX- 阴影相对于形状在水平方向的偏移number shadowOffsetY- 阴影相对于形状在竖直方向的偏移number shadowColor- 阴影的颜色number shadowBlur- 阴影的模糊级别number lineWidth- 线条的宽度string lineCap- 线条的端点样式string lineJoin- 线条的交点样式
lineJoin
| 值 | 说明 | 
|---|---|
| bevel | 斜角 | 
| round | 圆角 | 
| miter | 尖角 | 
number miterLimit- 最大斜接长度number lineDashOffset- 虚线偏移量,初始值为0
几个相关的画图api 点这里
const app = getApp()const setText = (context, fs, color, x, y, c) => {context.setFontSize(fs);context.setFillStyle(color);context.setTextAlign('left');context.fillText(c, x, y);context.restore();};Page({data: {imagePath:''},onLoad(){var that=this;wx.downloadFile({url: 'https://xxxx.com/image',success: function (res) {that.setData({path: res.tempFilePath})}})var ctx = wx.createCanvasContext('mycanvas');var c_avatar = '../image/timg2.jpg';var wechat = '../image/wechat.png';var path = that.data.path;ctx.fillStyle = "#ffe200";ctx.fillRect(0, 0, 375, 612);setText(ctx, 16, '#xxx', 90, 45, '达达);// 绘制画报背景图ctx.drawImage(path, 30, 95, 400, 500);//头像ctx.arc(45, 45, 25, 0, 2 * Math.PI)ctx.strokeStyle = "#fff";ctx.clip();ctx.drawImage(c_avatar, 20, 20, 50, 50);// 绘制生成画报ctx.draw(true, setTimeout(function () {// 保存wx.canvasToTempFilePath({canvasId: 'mycanvas',success: function (res) {console.log(res)var tempFilePath = res.tempFilePath;that.setData({imagePath: tempFilePath});},fail: function (res) {console.log(res);}})}, 1000));}})
点关注,不迷路
好了各位,以上就是这篇文章的全部内容,能看到这里的人都是人才。我后面会不断更新网络技术相关的文章,如果觉得文章对你有用,欢迎给个“在看”,也欢迎分享,感谢大家 !!
—————END—————
推荐阅读
2、你不知道的 TypeScript 泛型(万字长文,建议收藏)
6、想去力扣当前端,TypeScript 需要掌握到什么程度?
❝关注加加,星标加加~
❞
如果觉得文章不错,帮忙点个在看呗
