【HTML】Canvas 2D image

reference link

HTML Canvas | Newbie Tutorial

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
    );
  });
}

Guess you like

Origin blog.csdn.net/wuli_youhouli/article/details/128325369