Skip to content

Instantly share code, notes, and snippets.

@hijiangtao
Last active May 14, 2021 04:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hijiangtao/4769c61573ebd2b068d6065930fbd65d to your computer and use it in GitHub Desktop.
Save hijiangtao/4769c61573ebd2b068d6065930fbd65d to your computer and use it in GitHub Desktop.
A wired example of Canvas be cut off by very long `.clip()` path

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();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment