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