UNPKG

inverted-corners

Version:

A Houdini Paint worklet for inverted corners using the CSS Paint API.

7 lines 2.7 kB
/** * Inverted Corners (https://inverted-corners.netlify.app/) * @author over-engineer <dev@over-engineer.com> * @copyright 2021 over-engineer * @license MIT */ class InvertedCornersPainter{static get inputProperties(){return["--corner-radius","--background","list-style-image"]}_getRadii(radii){const[a=0,b=0,c=0,d=0]=radii;return 2===radii.length?[a,b,a,b]:[a,b,c,d]}_isInverted(radius){return radius<0}paint(ctx,geom,properties){const radii=properties.get("--corner-radius").toString().trim().split(" ").map((radius=>parseInt(radius))),gradProps=properties.get("--background").toString().split(",").map((prop=>prop.trim()));gradProps[0]=gradProps[0].replace("deg","");const image=properties.get("list-style-image");let angle=0,colors=gradProps;isNaN(+gradProps[0])||([angle,...colors]=gradProps,angle=+angle);const[topLeft,topRight,bottomRight,bottomLeft]=this._getRadii(radii),maxInvRadius=Math.abs(Math.min(...radii,0));if(ctx.fillStyle="#000",colors.length>=1){angle=angle*Math.PI/180;const gradLength=Math.sqrt(geom.width**2+geom.height**2)/2,x1=geom.width/2-Math.cos(angle)*gradLength,y1=geom.height/2-Math.sin(angle)*gradLength,x2=geom.width/2+Math.cos(angle)*gradLength,y2=geom.height/2+Math.sin(angle)*gradLength,step=1/(colors.length-1),grad=ctx.createLinearGradient(x1,y1,x2,y2);for(let i=0;i<colors.length;i+=1){const[color,colorStop]=colors[i].split(" ");let offset=i===colors.length-1?1:i*step;colorStop&&(offset=colorStop),grad.addColorStop(offset,color)}ctx.fillStyle=grad}ctx.beginPath(),this._isInverted(topLeft)?ctx.moveTo(maxInvRadius-Math.abs(topLeft),0):ctx.moveTo(maxInvRadius+Math.abs(topLeft),0),ctx.quadraticCurveTo(maxInvRadius,0,maxInvRadius,Math.abs(topLeft)),ctx.lineTo(maxInvRadius,geom.height-Math.abs(bottomLeft)),this._isInverted(bottomLeft)?ctx.quadraticCurveTo(maxInvRadius,geom.height,maxInvRadius-Math.abs(bottomLeft),geom.height):ctx.quadraticCurveTo(maxInvRadius,geom.height,maxInvRadius+Math.abs(bottomLeft),geom.height),this._isInverted(bottomRight)?ctx.lineTo(geom.width-maxInvRadius+Math.abs(bottomRight),geom.height):ctx.lineTo(geom.width-maxInvRadius-Math.abs(bottomRight),geom.height),ctx.quadraticCurveTo(geom.width-maxInvRadius,geom.height,geom.width-maxInvRadius,geom.height-Math.abs(bottomRight)),ctx.lineTo(geom.width-maxInvRadius,Math.abs(topRight)),this._isInverted(topRight)?ctx.quadraticCurveTo(geom.width-maxInvRadius,0,geom.width-maxInvRadius+Math.abs(topRight),0):ctx.quadraticCurveTo(geom.width-maxInvRadius,0,geom.width-maxInvRadius-Math.abs(topRight),0),ctx.closePath(),ctx.fill(),image instanceof CSSImageValue&&(ctx.clip(),ctx.drawImage(image,0,0,geom.width,geom.height))}}registerPaint("inverted-corners",InvertedCornersPainter);