Extend and optimize
1. Image smoothing
<script>
const canvas=document.getElementById('canvas');
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
const ctx=canvas.getContext('2d');
/* Image smoothing imageSmoothingEnabled*/
/* Image source */
const img=new Image();
img.src='./images/chess.jpg';
img.onload=function(){
const {width,height}=img;
DrawImage (image, x, y) */
ctx.drawImage(img,100.100,width*10,height*10);
ctx.imageSmoothingEnabled=false;
ctx.drawImage(img,100.100+height*10,width*10,height*10);
};
</script>
Copy the code
2. Canvas draws a line one pixel wide
<script>
const canvas=document.getElementById('canvas');
canvas.width=window.innerWidth;
canvas.height=window.innerHeight;
const ctx=canvas.getContext('2d');
/* Draw a line */
ctx.beginPath();
ctx.lineWidth=1;
ctx.moveTo(50.50);
ctx.lineTo(400.50);
ctx.stroke();
/* One pixel wide line */
/* Method 1 */
ctx.beginPath();
ctx.lineWidth=1;
ctx.moveTo(50.150.5);
ctx.lineTo(400.150.5);
ctx.stroke();
/* Method 2 */
ctx.translate(0.5.0.5);
ctx.beginPath();
ctx.lineWidth=1;
ctx.moveTo(50.250);
ctx.lineTo(400.250);
ctx.stroke();
</script>
Copy the code
3. Pixel ratio of the appropriate device
<script>
/* Adaptor device resolution */
{
const canvas=document.getElementById('canvas2');
const ctx=canvas.getContext('2d');
// get the devicePixelRatio devicePixelRatio from the window object
const ratio=window.devicePixelRatio;
console.log('ratio',ratio);
// Multiply the canvas size by the ratio of pixels, that is, make the canvas larger
canvas.width=width*ratio;
canvas.height=height*ratio;
// Synchronize the canvas scale with the canvas scale
ctx.scale(ratio,ratio);
// Set canvas CSS size to define the visual size of the canvas
canvas.style.width=width+'px';
canvas.style.height=height+'px';
/ / drawing
ctx.font='60px arial ';
ctx.fillText('canvas'.10.100);
}
</script>
Copy the code
4. Canvas to picture
<body>
<canvas id="canvas" width="420" height="126"></canvas>
<img id="img" src="" alt="">
<script>
const canvas=document.getElementById('canvas');
const ctx=canvas.getContext('2d');
const img=new Image();
img.src='https://img.kaikeba.com/70350130700202jusm.png';
img.setAttribute("crossOrigin".'Anonymous');
img.onload=function(){
ctx.drawImage(img,0.0);
const imgURL=canvas.toDataURL();
console.log('imgURL',imgURL);
document.querySelector('#img').setAttribute('src',imgURL);
}
</script>
</body>
Copy the code
5. Ball tails
<script>
const canvas=document.getElementById('canvas');
const [width,height]=[window.innerWidth,window.innerHeight];
canvas.width=width;
canvas.height=height;
/ / brush
const ctx=canvas.getContext('2d');
// Ball objectification
class Ball{
constructor(r,color='#00acec'){
this.color=color;
this.r=r;
this.x=0;
this.y=0;
}
draw(ctx){
ctx.save();
ctx.beginPath();
ctx.fillStyle=this.color;
ctx.arc(this.x,this.y,this.r,0.Math.PI*2); ctx.fill(); ctx.restore(); }}// Instantiate the ball
let ball=new Ball(15);
ball.y=50;
ball.x=width/2;
// Record the time
let time=new Date(a);/ / gravity gravity
const gravity=0.01;
/ / elastic
const bounding=-0.8;
// Speed/ms vy
let vy=0.3;
let vx=0.3;
// Animation method
function animate(){
/ / time
let now=new Date(a);let diff=now-time;
time=now;
/ / acceleration
vy+=gravity;
// Set the ball position
ball.y+=vy*diff;
ball.x+=vx*diff;
// Bottom collision
if(ball.y+ball.r>height){
ball.y=height-ball.r;
vy*=bounding;
}
// Left side collision
if(ball.x-ball.r<0){
ball.x=ball.r;
vx*=bounding;
}
// Right side collision
if(ball.x+ball.r>width){ ball.x=width-ball.r; vx*=bounding; }}// Render method! (function render(){
// Set the animation
animate();
/ / erasure
/ / CTX. ClearRect (0, 0, width, height);
// Each drawing adds a filter mask to the previous drawing
ctx.fillStyle='rgba (250235215,0.1)';
ctx.fillRect(0.0,width,height);
/ / drawing
ball.draw(ctx);
// Recursively call the render function
window.requestAnimationFrame(render); }) ()</script>
Copy the code
6, point to the mouse line 3d
// Create a 2d vector js file
// Vector2.js
export default class Vector2{
constructor(x=0,y=0){
this.x=x;
this.y=y;
}
/ / add the add (v)
add(v){
this.x+=v.x;
this.y+=v.y;
return this;
}
/ / subtraction sub (v)
sub(v){
this.x-=v.x;
this.y-=v.y;
return this;
}
// Angle ()
angle(){
const {x,y}=this;
let dir=Math.atan2(y,x);
if(dir<0){dir+=Math.PI*2}
return dir;
}
/ / rotation rotate (a)
rotate(a){
const c=Math.cos(a);
const s=Math.sin(a);
const {x,y}=this;
this.x=x*c-y*s;
this.y=x*s+y*c;
return this;
}
// Length read length()
length(){
const {x,y}=this;
return Math.sqrt(x*x+y*y);
}
// setLength setLength(len)
setLength(len){
const {x,y}=this;
const r=this.length();
const c=x/r;
const s=y/r;
this.x=c*len;
this.y=s*len;
return this;
}
/ / clone clone ()
clone(){
return new Vector2(this.x,this.y);
}
/ / copy copy (v)
copy(v){
this.x=v.x;
this.y=v.y;
return this;
}
// Len length, dir direction
static polar(len,dir){
return new Vector2(
Math.cos(dir)*len,
Math.sin(dir)*len
)
}
}
Copy the code
<script type="module">
import Vector2 from "./jsm/Vector2.js";
const [width,height]=[window.innerWidth,window.innerHeight];
const canvas=document.getElementById('canvas');
canvas.width=width;
canvas.height=height;
const ctx=canvas.getContext('2d');
/ / object
class Line{
constructor(start=new Vector2(),end=new Vector2()) {
this.start=start;
this.end=end;
}
draw(ctx){
const {start,end}=this;
ctx.save();
/ / line
ctx.beginPath();
ctx.moveTo(start.x,start.y);
ctx.lineTo(end.x,end.y);
ctx.lineWidth=2;
ctx.stroke();
/ / dot
ctx.beginPath();
ctx.arc(end.x,end.y,6.0.Math.PI*2); ctx.fill(); ctx.restore(); }}// Circle object
class Circle{
constructor(pos,r) {
this.pos=pos;
this.r=r;
}
draw(ctx){
const {pos,r}=this;
ctx.save();
ctx.setLineDash([6]);
ctx.beginPath();
ctx.arc(pos.x,pos.y,r,0.Math.PI*2); ctx.stroke(); ctx.restore(); }}// The base of the line
const basicPos=new Vector2(width/2,height/2);
// Line length
const r1=100;
// The radius of the circle is R2
const r2=200;
/ / object
const line=new Line(basicPos.clone(),new Vector2(basicPos.x+r1,basicPos.y));
// Small circle object
const circle1=new Circle(basicPos.clone(),r1);
// Large circle object
const circle2=new Circle(basicPos.clone(),r2);
/ / rendering
render();
window.addEventListener('mousemove',mousemoveFn);
function mousemoveFn(event){
// Mouse position mousePos
const mousePos=new Vector2(event.clientX,event.clientY);
MouseSubPos = mouseSubPos = mouseSubPos = mouseSubPos
const mouseSubBasic=mousePos.sub(basicPos);
// Get the distance from the mouse to the base point and calculate the ratio of this distance to the radius of the large circle
let ratio=mouseSubBasic.length()/r2;
// Keep the ratio no more than 1
ratio=Math.min(ratio,1);
// Compute the vector length len
const len=r1*ratio;
// Let the mouseSubBasic vector have the same length as R1
const pos=mouseSubBasic.setLength(len);
// Offset vector based on base point position
pos.add(basicPos);
// Update the end position of the line
line.end.copy(pos);
/ / rendering
render();
}
// Render method
function render(){
ctx.clearRect(0.0,width,height);
line.draw(ctx);
circle1.draw(ctx);
circle2.draw(ctx);
}
</script>
Copy the code
7, 404 page sight follow
<script type="module">
import Vector2 from "./jsm/Vector2.js";
const [width,height]=[window.innerWidth,window.innerHeight];
const canvas=document.getElementById('canvas');
canvas.width=width;
canvas.height=height;
const ctx=canvas.getContext('2d');
/ / img loader
const ImgLoader={
onload(imgs,fn){
const imgPros=imgs.map((ele) = >{
return ImgLoader.imgPro(ele);
});
Promise.all(imgPros).then((val) = >{
fn(val);
},() = >{
console.error('Image load failed');
});
},
imgPro(img){
return new Promise((resolve) = >{
img.onload=function(){ resolve(img); }}); }};/ / body
class BodyRect{
constructor(img,pos){
this.img=img;
this.pos=pos;
}
draw(ctx){
const {img,pos}=this; ctx.save(); ctx.drawImage(img,pos.x,pos.y); ctx.restore(); }}/ / eyes
class EyeRect{
constructor(img,pos,offset){
this.img=img;
this.pos=pos;
this.offset=offset;
}
draw(ctx){
const {img,pos,offset}=this; ctx.save(); ctx.drawImage(img,pos.x-offset,pos.y-offset); ctx.restore(); }}// The perceived distance of the eye
const maxR=50;
// The radius of the orbit
const rimR=15;
// The position of the eyes relative to the monster
const basicPos=[new Vector2(126.52),new Vector2(219.59)];
// The offset distance of pupil. During drawImage, the base point of the eyeball is at the upper left corner, which needs to be adjusted to the center
const eyeR=11;
// Body and eyes
let monsterBody,eyeLeft,eyeRight;
// Move the position of the transform
let monsterPos=getMonsterPos();
// Monster body image
const bodyImg=new Image();
bodyImg.src='./images/404.png';
// Eye image
const eyeImg=new Image();
eyeImg.src='./images/eye.png';
// When both images are loaded successfully, render the graphics
ImgLoader.onload([bodyImg,eyeImg],loadedFn);
function loadedFn(){
// Build body and eyes
monsterBody=new BodyRect(bodyImg,new Vector2(0.0));
eyeLeft=new EyeRect(eyeImg,basicPos[0].clone(),eyeR);
eyeRight=new EyeRect(eyeImg,basicPos[1].clone(),eyeR);
/ / rendering
render();
// Add mouse movement events
canvas.addEventListener('mousemove',mousemoveFn);
// Listen for window size changes
window.addEventListener('resize',resizeFn);
}
// Render method
function render(){
/ / clean up
ctx.clearRect(0.0,width,height);
/ / rendering
ctx.save();
ctx.translate(monsterPos.x,monsterPos.y);
monsterBody.draw(ctx);
eyeLeft.draw(ctx);
eyeRight.draw(ctx);
ctx.restore();
}
// Mouse movement
function mousemoveFn(event){
// Get the mouse position
const mousePos=new Vector2(event.clientX,event.clientY).sub(monsterPos);
// Go through both eyes
[eyeLeft,eyeRight].forEach((ele,ind) = >{
// Get the distance from the mouse to the base point of the pupil
const mouseSubObj=mousePos.clone().sub(basicPos[ind]);
// Calculate the distance from the pupil to the center of the circle proportionally based on the eye center
const radius=Math.min(mouseSubObj.length()/maxR,1)*rimR;
// Set the pupil position
const pos=mouseSubObj.setLength(radius).add(basicPos[ind]);
// Assign to the position of the eye
ele.pos.copy(pos);
});
/ / rendering
render();
}
// Get the monster location
function getMonsterPos(){
return new Vector2(canvas.width-500,canvas.height-500);
}
// Window size changes
function resizeFn(){
const [width,height]=[window.innerWidth,window.innerHeight];
canvas.width=width;
canvas.height=height;
monsterPos=getMonsterPos();
render();
}
</script>
Copy the code
PutImageData and synthetic
<script>
const [width,height]=[window.innerWidth,window.innerHeight];
const canvas=document.getElementById('canvas');
canvas.width=width;
canvas.height=height;
const ctx=canvas.getContext('2d');
const imgDt=ctx.createImageData(400.400);
imgDt.data.forEach((ele,ind) = >{
imgDt.data[ind]=255;
})
/* Global transparency */
/*ctx.globalAlpha=1; CTX. PutImageData (imgDt, 0, 0); // white rectangle ctx.fillStyle='# FFF '; CTX. FillRect,0,400,400 (400); * /
/* Path clipping */
/ / path
/*ctx.beginPath(); CTX. Arc (400400200, 0, Math. PI * 2); ctx.stroke(); ctx.clip(); // white rectangle ctx.fillStyle='# FFF '; CTX. FillRect,0,400,400 (400); CTX. PutImageData (imgDt, 0, 0); * /
/* Global composition */
// Draw a graph
/*ctx.beginPath(); CTX. Arc (400400200, 0, Math. PI * 2); ctx.fill(); //globalCompositeOperation ctx.globalCompositeOperation='source-in'; // ctx.fillStyle='# FFF '; / / CTX. FillRect,0,400,400 (400); CTX. PutImageData (imgDt, 0, 0); * /
/*putImageData is tailored to the correct unlock method */
// Draw a graph
ctx.putImageData(imgDt,0.0);
//globalCompositeOperation
ctx.globalCompositeOperation='destination-in';
// Draw the graph
ctx.beginPath();
ctx.arc(400.400.200.0.Math.PI*2);
ctx.fill();
</script>
Copy the code
Canvas draws complex graphics
<embed id="svg"
src="./images/mount.svg"
width="300"
height="300"
type="image/svg+xml"
pluginspage="http://www.adobe.com/svg/viewer/install/" />
<canvas id="canvas"></canvas>
<script type="module">
const canvas=document.getElementById('canvas');
canvas.width=300;
canvas.height=300;
const ctx=canvas.getContext('2d');
// Embed Gets the SVG container
const embed=document.querySelector('embed');
/* When the page content is loaded successfully * getSVGDocument() gets the SVG document object in the SVG container * querySelector() gets the polygon node in the SVG document object * parsePoints() parses the vertex data in the polygon node * Draw () so vertex data, draw canvas graph * */
window.onload=function(){
const svgDom=embed.getSVGDocument();
const poly=svgDom.querySelector('#poly');
console.log('poly',poly);
const points=parsePoints(poly.getAttribute('points'));
console.log('points',points);
/ * * / canvas drawing
ctx.beginPath();
points.forEach(p= >{
ctx.lineTo(p[0],p[1]);
})
ctx.fill();
}
/* Parses polygon * arr in SVG to cut points attributes into arrays with Spaces, such as ['x,y'... Vertice converts string points to integer points such as '1.2,2.8' → [1,3] * * */
function parsePoints(points){
const vertices=[];
let arr=points.split(' ');
for(let ele of arr){
if(ele){
const vertice=ele.split(', ').map((num) = >{
return Math.round(num); }); vertices.push(vertice); }}return vertices;
}
</script>
Copy the code