A wired example of Canvas be cut off by very long .clip()
path
Discussion can be found at StackOverflow.
A wired example of Canvas be cut off by very long .clip()
path
Discussion can be found at StackOverflow.
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Wired Cut off Canvas</title> | |
<Style> | |
body { | |
background-color: gray; | |
} | |
#canvas { | |
position: absolute; | |
x: 2px; | |
y: 2px; | |
} | |
#canvas2 { | |
position: absolute; | |
x: 754px; | |
y: 2px; | |
} | |
</Style> | |
</head> | |
<body> | |
<canvas id="canvas"></canvas> | |
<canvas id="canvas2"></canvas> | |
<script src="./index.js"></script> | |
</body> | |
</html> |
class BaseCanvas { | |
constructor() { | |
this.canvas = document.getElementById('canvas'); | |
this.ctx = this.canvas.getContext('2d'); | |
this.canvas2 = document.getElementById('canvas2'); | |
this.ctx2 = this.canvas.getContext('2d'); | |
this.config = { | |
width: 750, | |
height: 20000, | |
rectWidth: 680, | |
rectHeight: 18000, | |
} | |
} | |
updateCanvas() { | |
const { width, height, rectWidth, rectHeight } = this.config; | |
this.canvas.height = height; | |
this.canvas.width = width; | |
this.drawBackground(); | |
const x = (width - rectWidth) / 2; | |
const y = x; | |
this.drawClipContent(x, y, rectWidth, rectHeight, 20, () => { | |
this.ctx.fillStyle = '#FFF'; | |
this.ctx.fillRect(x, y, rectWidth, rectHeight); | |
// some other logics here | |
// ... | |
}); | |
} | |
drawBackground() { | |
this.ctx.fillStyle = '#4997FE'; | |
this.ctx.fillRect(0, 0, this.config.width, this.config.height); | |
} | |
drawClipContent( | |
x, | |
y, | |
width, | |
height, | |
radius, | |
contentFn | |
) { | |
this.ctx.save(); | |
this.ctx.beginPath(); | |
this.ctx.translate(x, y); | |
this.drawRoundRectPath(width, height, radius, true); | |
this.ctx.closePath(); | |
this.ctx.clip(); | |
if (contentFn) { | |
this.ctx.translate(-x, -y); | |
contentFn(); | |
} | |
this.ctx.restore(); | |
} | |
drawClipContent2( | |
x, | |
y, | |
width, | |
height, | |
radius, | |
contentFn | |
) { | |
this.ctx.save(); | |
this.ctx.translate(x, y); | |
this.ctx.beginPath(); | |
this.drawRoundRectPath(width, height, radius, true); | |
this.ctx.closePath(); | |
this.ctx.clip(); | |
if (contentFn) { | |
this.ctx.translate(-x, -y); | |
this.ctx.fillStyle = '#FFF'; | |
this.ctx.fillRect(x, y, rectWidth, rectHeight); | |
} | |
this.ctx.restore(); | |
} | |
drawRoundRectPath(width, height, radius) { | |
const topLeftRadius = radius; | |
const topRightRadius = radius; | |
const bottomLeftRadius = radius; | |
const bottomRightRadius = radius; | |
this.ctx.arc(width - bottomRightRadius, height - bottomRightRadius, bottomRightRadius, 0, Math.PI / 2); | |
this.ctx.lineTo(bottomLeftRadius, height); | |
this.ctx.arc(bottomLeftRadius, height - bottomLeftRadius, bottomLeftRadius, Math.PI / 2, Math.PI); | |
this.ctx.lineTo(0, topLeftRadius); | |
this.ctx.arc(topLeftRadius, topLeftRadius, topLeftRadius, Math.PI, (Math.PI * 3) / 2); | |
this.ctx.lineTo(width - topRightRadius, 0); | |
this.ctx.arc(width - topRightRadius, topRightRadius, topRightRadius, (Math.PI * 3) / 2, Math.PI * 2); | |
this.ctx.lineTo(width, height - topRightRadius); | |
} | |
} | |
// calling | |
const ins = new BaseCanvas(); | |
ins.updateCanvas(); |