gradient border: top + sides with corner arcs, fades out at bottom
This commit is contained in:
parent
3ae679a621
commit
6f42337008
1 changed files with 19 additions and 48 deletions
|
|
@ -40,68 +40,39 @@ PanelWindow {
|
||||||
|
|
||||||
ctx.clearRect(0, 0, w, h);
|
ctx.clearRect(0, 0, w, h);
|
||||||
|
|
||||||
// Opaque backing behind the stroke
|
// Horizontal gradient for the border
|
||||||
ctx.fillStyle = M.Theme.base00.toString();
|
|
||||||
ctx.beginPath();
|
|
||||||
if (r > lw) {
|
|
||||||
ctx.moveTo(0, r);
|
|
||||||
ctx.arc(r, r, r, Math.PI, -Math.PI / 2);
|
|
||||||
ctx.lineTo(w - r, 0);
|
|
||||||
ctx.arc(w - r, r, r, -Math.PI / 2, 0);
|
|
||||||
ctx.lineTo(w, lw);
|
|
||||||
ctx.lineTo(0, lw);
|
|
||||||
} else {
|
|
||||||
ctx.rect(0, 0, w, lw);
|
|
||||||
}
|
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
// Glow below the stroke — fades from gradient color to transparent
|
|
||||||
const glowH = h - lw;
|
|
||||||
if (glowH > 0) {
|
|
||||||
const glowGrad = ctx.createLinearGradient(0, lw, 0, h);
|
|
||||||
glowGrad.addColorStop(0, "rgba(255,255,255,0.06)");
|
|
||||||
glowGrad.addColorStop(1, "transparent");
|
|
||||||
|
|
||||||
// Use the horizontal gradient as a mask via compositing
|
|
||||||
const hGrad = ctx.createLinearGradient(0, 0, w, 0);
|
|
||||||
hGrad.addColorStop(0, M.Theme.base0C.toString());
|
|
||||||
hGrad.addColorStop(1, M.Theme.base09.toString());
|
|
||||||
|
|
||||||
// Draw vertical fade strip
|
|
||||||
ctx.globalAlpha = 0.25;
|
|
||||||
ctx.fillStyle = hGrad;
|
|
||||||
ctx.fillRect(0, lw, w, glowH);
|
|
||||||
|
|
||||||
// Erase bottom portion with transparent fade
|
|
||||||
ctx.globalAlpha = 1;
|
|
||||||
ctx.globalCompositeOperation = "destination-out";
|
|
||||||
const eraseGrad = ctx.createLinearGradient(0, lw, 0, h);
|
|
||||||
eraseGrad.addColorStop(0, "transparent");
|
|
||||||
eraseGrad.addColorStop(1, "black");
|
|
||||||
ctx.fillStyle = eraseGrad;
|
|
||||||
ctx.fillRect(0, lw, w, glowH);
|
|
||||||
ctx.globalCompositeOperation = "source-over";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gradient stroke
|
|
||||||
ctx.globalAlpha = 1;
|
|
||||||
const grad = ctx.createLinearGradient(0, 0, w, 0);
|
const grad = ctx.createLinearGradient(0, 0, w, 0);
|
||||||
grad.addColorStop(0, M.Theme.base0C.toString());
|
grad.addColorStop(0, M.Theme.base0C.toString());
|
||||||
grad.addColorStop(1, M.Theme.base09.toString());
|
grad.addColorStop(1, M.Theme.base09.toString());
|
||||||
ctx.strokeStyle = grad;
|
ctx.strokeStyle = grad;
|
||||||
ctx.lineWidth = lw;
|
ctx.lineWidth = lw;
|
||||||
|
|
||||||
|
// Stroke: top + left side + right side (open bottom)
|
||||||
|
// Left side down, curve, across top, curve, right side down
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
if (r > lw) {
|
if (r > lw) {
|
||||||
ctx.moveTo(0, r);
|
ctx.moveTo(hw, h);
|
||||||
|
ctx.lineTo(hw, r);
|
||||||
ctx.arc(r, r, r - hw, Math.PI, -Math.PI / 2);
|
ctx.arc(r, r, r - hw, Math.PI, -Math.PI / 2);
|
||||||
ctx.lineTo(w - r, hw);
|
ctx.lineTo(w - r, hw);
|
||||||
ctx.arc(w - r, r, r - hw, -Math.PI / 2, 0);
|
ctx.arc(w - r, r, r - hw, -Math.PI / 2, 0);
|
||||||
|
ctx.lineTo(w - hw, h);
|
||||||
} else {
|
} else {
|
||||||
ctx.moveTo(0, hw);
|
ctx.moveTo(hw, h);
|
||||||
ctx.lineTo(w, hw);
|
ctx.lineTo(hw, hw);
|
||||||
|
ctx.lineTo(w - hw, hw);
|
||||||
|
ctx.lineTo(w - hw, h);
|
||||||
}
|
}
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
|
// Fade out the bottom of the side borders
|
||||||
|
ctx.globalCompositeOperation = "destination-out";
|
||||||
|
const fadeGrad = ctx.createLinearGradient(0, h * 0.5, 0, h);
|
||||||
|
fadeGrad.addColorStop(0, "transparent");
|
||||||
|
fadeGrad.addColorStop(1, "black");
|
||||||
|
ctx.fillStyle = fadeGrad;
|
||||||
|
ctx.fillRect(0, h * 0.5, w, h * 0.5);
|
||||||
|
ctx.globalCompositeOperation = "source-over";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue