reference link
Features
Canvas draws 2D graphics through JavaScript and is a new element in HTML 5.
What is drawn is a bitmap, and the image will be distorted when enlarged. Ability to save images in .png or .jpg format, more suitable for gaming applications. Event handlers are not supported
<canvas>
The container (rectangle) of the graphic must use js to define charts or other images.
The height and width attributes must be set, and the width and height cannot be set with style, which is an invalid operation. The default height and width of 150*300 are returned.
<canvas id="cvs" height="150" width="300"></canvas>
getContext()
getContext() returns an object providing drawing methods and properties .
getContext("2d") gets the 2d context object.
var cvs = document.getElementById('cvs');
var ctx = cvs.getContext('2d');
style
strokestrokeStyle, fillfillStyle
The attributes that it has at the same time are solid color, gradient, and repeat.
solid color
ctx.fillStyle="#FF0000";
ctx.fillRect(20,20,150,100); //x的坐标,y的坐标,矩形宽度,矩形高度
gradient
Linear gradient createLinearGradient
var grd=ctx.createLinearGradient(170,0,0,0);
grd.addColorStop(0,"black");
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(20,20,150,100);
Radial gradient createRadialGradient
var grd=ctx.createRadialGradient(100,50,5,90,60,100);
grd.addColorStop(0,"red");
grd.addColorStop(1,"white");
ctx.fillStyle=grd;
ctx.fillRect(20,20,150,100);
Repeat createPattern()
Repeats the specified element in the specified direction.
var img=document.getElementById("img")
var pat=ctx.createPattern(img,"repeat"); // repeat、repeat-x、repeat-y、no-repeat
ctx.rect(0,0,220,128);
ctx.fillStyle=pat;
ctx.fill();
rectangle
Create rect
ctx.rect(20,20,150,100);
ctx.stroke();
ctx.rect(20,20,50,50);
ctx.fill();
strokestrokeRect
ctx.strokeStyle="#FF0000";
ctx.strokeRect(20,20,150,100);
Fill fillRect
Default is black
ctx.fillStyle="#FF0000";
ctx.fillRect(20,20,150,100); //x的坐标,y的坐标,矩形宽度,矩形高度
Clear clearRect
Clears the specified pixels within the given rectangle.
ctx.fillStyle="red";
ctx.fillRect(0,0,300,150);
ctx.clearRect(20,20,100,50);
line
line end point
ctx.beginPath();
ctx.lineWidth=10;
ctx.lineCap="butt";
ctx.moveTo(20,20);
ctx.lineTo(200,20);
ctx.stroke();
ctx.beginPath();
ctx.lineCap="round";
ctx.moveTo(20,40);
ctx.lineTo(200,40);
ctx.stroke();
ctx.beginPath();
ctx.lineCap="square";
ctx.moveTo(20,60);
ctx.lineTo(200,60);
ctx.stroke();
Intersection inflection point
ctx.beginPath();
ctx.lineWidth=10;
ctx.lineJoin="round";
ctx.moveTo(20,20);
ctx.lineTo(100,50);
ctx.lineTo(20,100);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth=10;
ctx.lineJoin="bevel";
ctx.moveTo(80,20);
ctx.lineTo(160,50);
ctx.lineTo(80,100);
ctx.stroke();
ctx.beginPath();
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.moveTo(140,20);
ctx.lineTo(200,50);
ctx.lineTo(140,100);
ctx.stroke();
Miter angle
ctx.lineWidth=10;
ctx.lineJoin="miter";
ctx.miterLimit=5;
ctx.moveTo(20,20);
ctx.lineTo(50,27);
ctx.lineTo(20,34);
ctx.stroke();
path
line
ctx.beginPath(); // 开始
ctx.lineWidth="5"; // 宽度
ctx.strokeStyle="green";
ctx.moveTo(30,25); //开始点
ctx.lineTo(150,35); // 到这个点绘制线条
ctx.lineTo(150,75);
ctx.closePath(); // 从当前点回到起始点
ctx.stroke(); // 画
quadratic Bezier curve
ctx.beginPath();
ctx.moveTo(20,20);
ctx.quadraticCurveTo(20,100,200,20);
ctx.stroke();
cubic bezier curve
ctx.beginPath();
ctx.moveTo(20,20);
ctx.bezierCurveTo(20,100,200,100,200,20);
ctx.stroke();
clipping
Cut an area of any shape and size from the original canvas.
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.fillStyle="red";
ctx.fillRect(0,0,150,100);
ctx.rect(50,20,200,120);
ctx.stroke();
ctx.clip();
ctx.fillStyle="red";
ctx.fillRect(0,0,150,100);
circle or partial circle
//x坐标,y坐标,半径,开始位置,整圆:2*Math.PI,true逆时针,false是顺时针
ctx.beginPath();
ctx.arc(100,75,50,0,2*Math.PI);
ctx.stroke();
arc between two lines
ctx.beginPath();
ctx.moveTo(20,20);
ctx.lineTo(100,20);
ctx.arcTo(150,20,150,70,50);
ctx.lineTo(150,120);
ctx.stroke();
Test whether a point is in a path
ctx.rect(20,20,150,100);
ctx.stroke();
if (ctx.isPointInPath(20,80)) {
console.log("在区域内")
}else {
console.log("不在区域内")
}
convert
scale enlarge
ctx.strokeRect(5,5,25,15);
ctx.scale(2,2);
ctx.strokeRect(5,5,25,15);
rorate rotate
ctx.rotate(20*Math.PI/180);
ctx.fillRect(50,20,100,50);
translate translate
ctx.fillRect(10,10,100,50);
ctx.translate(70,70);
ctx.fillRect(10,10,100,50);
transform
ctx.fillStyle="yellow";
ctx.fillRect(0,0,250,100)
ctx.transform(1,0.5,-0.5,1,30,10);
ctx.fillStyle="red";
ctx.fillRect(0,0,250,100);
ctx.transform(1,0.5,-0.5,1,30,10);
ctx.fillStyle="blue";
ctx.fillRect(0,0,250,100);
setTransform
A change that is not based on the previous one. So the blue one will cover the previous red one.
ctx.fillStyle="yellow";
ctx.fillRect(0,0,250,100)
ctx.setTransform(1,0.5,-0.5,1,30,10);
ctx.fillStyle="red";
ctx.fillRect(0,0,250,100);
ctx.setTransform(1,0.5,-0.5,1,30,10);
ctx.fillStyle="blue";
ctx.fillRect(0,0,250,100);
shadow shadow
ctx.shadowBlur=20;
ctx.shadowColor="black";
ctx.fillStyle="red";
ctx.fillRect(10,10,50,50);
ctx.shadowBlur=20;
ctx.shadowOffsetX=20;
ctx.shadowColor="black";
ctx.fillStyle="red";
ctx.fillRect(70,10,50,50);
ctx.shadowBlur=20;
ctx.shadowOffsetY=20;
ctx.shadowColor="black";
ctx.fillStyle="red";
ctx.fillRect(150,10,50,50);
transparency
ctx.fillStyle="red";
ctx.fillRect(20,20,75,50);
ctx.globalAlpha=0.2;
ctx.fillStyle="blue";
ctx.fillRect(150,20,75,50);
synthesis
The red rectangle is the destination image and the blue rectangle is the source image :
ctx.fillStyle="red";
ctx.fillRect(20,20,75,50);
ctx.fillStyle="blue";
ctx.globalCompositeOperation="source-over";
ctx.fillRect(50,50,75,50);
ctx.fillStyle="red";
ctx.fillRect(150,20,75,50);
ctx.fillStyle="blue";
ctx.globalCompositeOperation="destination-over";
ctx.fillRect(180,50,75,50);
text
letter
ctx.font="italic small-caps bold 32px aria";
ctx.fillText("Hello World",10,50);
Horizontal alignment
ctx.strokeStyle="red";
ctx.moveTo(150,20);
ctx.lineTo(150,170);
ctx.stroke();
ctx.font="15px Arial";
ctx.textAlign="start";
ctx.fillText("textAlign=start",150,60);
ctx.textAlign="end";
ctx.fillText("textAlign=end",150,80);
ctx.textAlign="left";
ctx.fillText("textAlign=left",150,100);
ctx.textAlign="center";
ctx.fillText("textAlign=center",150,120);
ctx.textAlign="right";
ctx.fillText("textAlign=right",150,140);
vertical alignment
//在Y = 100画一条红线
ctx.strokeStyle="red";
ctx.moveTo(5,100);
ctx.lineTo(395,100);
ctx.stroke();
ctx.font="20px Arial"
ctx.textBaseline="top";
ctx.fillText("Top",5,100);
ctx.textBaseline="bottom";
ctx.fillText("Bottom",50,100);
ctx.textBaseline="middle";
ctx.fillText("Middle",120,100);
ctx.textBaseline="alphabetic";
ctx.fillText("Alphabetic",190,100);
ctx.textBaseline="hanging";
ctx.fillText("Hanging",290,100);
Solid words
ctx.font="30px Arial";
ctx.textAlign ="center";
ctx.textBaseline = "bottom";
ctx.fillText("fillText",80,50);
Hollow words
// 渐变
var grd = ctx.createLinearGradient(0,0,300,0);
grd.addColorStop("0","magenta");
grd.addColorStop("0.5","blue");
grd.addColorStop("1.0","red");
// 文字
ctx.font="30px Verdana";
ctx.strokeStyle=grd;
ctx.strokeText("Big smile!",10,50);
text width
let wd = ctx.measureText("Hello World").width
ctx.font="30px Arial";
ctx.fillText(wd,10,50);
image
var img=document.getElementById("scream");
img.onload = function() {
ctx.drawImage(img,0,0);
}
img.onload = function() {
ctx.drawImage(img,20,10,150,180);
}
var img=document.getElementById("scream");
img.onload = function(){
// 图片,x坐标,y坐标,被剪切的宽度,被剪切的高度,放置图像的x坐标,放置图像的y坐标,宽度,高度
ctx.drawImage(img,90,130,50,60,10,10,50,60)
}
image dataimageData
var imgData=ctx.createImageData(100,50);
console.log("imgdata的宽度是: " + imgData.width);
console.log("imgdata的高度是: " + imgData.height);
console.log("imgdata的长度: " + imgData.data.length);
for (var i=0;i<imgData.data.length;i+=4)
{
// rgba
imgData.data[i+0]=255; // r
imgData.data[i+1]=0; // g
imgData.data[i+2]=0; // b
imgData.data[i+3]=155; // a
}
ctx.putImageData(imgData,10,10);
console.log("imgdata: " + JSON.stringify(imgData));
// 获取数据复制一份
var imgData2=ctx.getImageData(10,10,50,50);
ctx.putImageData(imgData2,10,70);
Canvas HD screen blur problem
Original link: The solution for blurry images generated by canvas - Jianshu The solution for blurry images generated by canvas - Jianshu
On devices with high-definition screens, blurring problems can be solved with hidpi-canvas-polyfill .
- First go to GitHub to download the hidpi-canvas.js file: portal ;
- Introduce the hidpi-canvas.js file into the project;
- Call the getPixelRatio() function to get the ratio value;
- In drawImage(), multiply width and height by ratio;
In some iOS devices, there may be an issue with image.onload failure, resulting in the inability to draw images into the canvas. The reasons for this phenomenon may be:
1. There is an issue with image.onload failure in iOS (note: image.onload is executed only if the image is loaded normally. If there is a slight error, image.onerror will be executed instead of image.onload) ;
2. If image.src is a base64 format file, do not set image.crossOrigin = "anonymous", otherwise image.onload may not be executed, making it impossible to draw pictures normally.
Regarding the problem of onload failure, you may learn a lot from this answer on Stack Overflow: IPhone img onload fails .
// html
<div onclick="makeCanvasToPhoto()" style="width: 100px; padding: 10px 30px;background: #eee;text-align: center">生成图片</div>
<canvas id="canvasBox" style="margin: 50px auto"></canvas>
<!-- 引入js -->
<script type="text/javascript" src="canvas.js"></script>
<script type="text/javascript" src="hidpi-canvas.min.js"></script>
// canvas.js 文件
function makeCanvasToPhoto() {
var that = this;
var canvas = document.getElementById("canvasBox");
var context = canvas.getContext('2d');
var ratio = getPixelRatio(context); // 关键代码
canvas.width = 300 * ratio; // 画布宽度
canvas.height = 300 * ratio; // 画布高度
var divWidth = 300 * ratio; // 用于内容居中
var divHeight = 300 * ratio; // 用于内容居中
// 画矩形
context.beginPath();
context.fillStyle = "#abcdef";
context.fillRect(0, 0, divWidth, divHeight);
context.closePath();
// 图片
context.beginPath();
var imgObj = new Image();
imgObj.crossOrigin = "anonymous"; // 在iOS 9设备中,如果src是base64格式,设置了crossOrigin 属性,会导致无法执行image.onload 而执行image.onerror 函数
imgObj.src = 'http://img0.imgtn.bdimg.com/it/u=458129248,1588126214&fm=26&gp=0.jpg';
imgObj.onload = function () {
var imgWidth = '150';
var imgHeight = '150';
context.drawImage(this, 50, 50, imgWidth * ratio, imgHeight * ratio)
};
context.closePath();
// 文本
context.beginPath();
context.font = '32px bold';
context.fillStyle = '#1a1a1a';
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText('文本', 50, 240);
context.closePath();
context.drawImage(canvas, 0, 0, divWidth, divHeight);
var base64Obj = canvas.toDataURL('image/png', 1);
console.log(base64Obj);
}
function getPixelRatio(context) {
var backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1;
return (window.devicePixelRatio || 1) / backingStore;
};
Canvas image cropped into a circle
<p>裁剪之前</p>
<img :src="options.img" />
<p>裁剪之后</p>
<img :src="options.canvasImg">
this.options.img = store.getters.avatar;
console.log('img',this.options.img)
this.imageToCircle(this.options.img).then((res) => {
this.options.canvasImg = res
console.log('canvasImg',this.options.canvasImg)
})
imageToCircle(picUrl) {
// 通过图片地址换出圆形的图片
let radius, diameter, canvas, ctx;
let img = new Image();
img.setAttribute("crossOrigin", "anonymous"); // 解决图片跨域访问失败
img.src = picUrl;
return new Promise((reslove) => {
img.addEventListener(
"load",
() => {
let { width, height } = img;
if (img.width > img.height) {
radius = height / 2;
} else {
radius = width / 2;
}
diameter = radius * 2;
canvas = document.createElement("canvas");
if (!canvas.getContext) {
// 判断浏览器是否支持canvas,如果不支持在此处做相应的提示
console.log("您的浏览器版本过低,暂不支持。");
return false;
}
canvas.width = diameter;
canvas.height = diameter;
ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, diameter, diameter);
// 描边
ctx.save(); //save和restore可以保证样式属性只运用于该段canvas元素
ctx.strokeStyle = "#eee"; //设置边线的颜色
ctx.lineWidth = 2;
ctx.beginPath(); //开始路径
ctx.arc(radius, radius, radius - 5, 0, Math.PI * 2); //画一个整圆.
ctx.stroke(); //绘制边线
// 截圆形图
ctx.save();
ctx.beginPath();
ctx.arc(radius, radius, radius - 5, 0, Math.PI * 2);
ctx.clip();
let x = 0,
y = 0,
swidth = diameter,
sheight = diameter;
ctx.drawImage(img, x, y, swidth, sheight, 0, 0, diameter, diameter);
ctx.restore();
// toDataURL()是canvas对象的一种方法,用于将canvas对象转换为base64位编码
let dataURL = canvas.toDataURL("image/png");
reslove(dataURL);
},
false
);
});
}