paintBackground method
Implementation
void paintBackground(Offset offset, PaintingContext context) {
var rect = offset & size;
final width = size.width;
final height = size.height;
pointerWidth = width < pointerWidth ? width : pointerWidth;
pointerHeight = height < pointerHeight ? height : pointerHeight;
if (pointerWidth < peakRadius) {
peakRadius = pointerWidth;
}
final arc = math.atan(pointerHeight / pointerWidth * 2);
final double halfArcWidth = math.sin(arc) * peakRadius;
final double l = peakRadius / math.cos(arc);
var pointerStartX = width * pointerBias - pointerWidth / 2;
var pointerEndX = width * pointerBias + pointerWidth / 2;
var minRadius = math.min(width - pointerWidth, height - pointerHeight) / 2;
if (borderRadius > minRadius) {
borderRadius = minRadius;
}
Radius radius = Radius.circular(borderRadius);
startPadding = startPadding > borderRadius ? startPadding : borderRadius;
endPadding = endPadding > borderRadius ? endPadding : borderRadius;
if (pointerStartX < startPadding) {
pointerStartX = startPadding;
pointerEndX = startPadding + pointerWidth;
} else if (pointerEndX > width - endPadding) {
pointerStartX = width - endPadding - pointerWidth;
pointerEndX = width - endPadding;
}
var arcY = math.tan(arc) * halfArcWidth;
arcY = pointerHeight < arcY ? pointerHeight : arcY;
Path path = Path();
if (isUpward) {
path.moveTo(pointerStartX, pointerHeight);
path.lineTo(pointerStartX + pointerWidth / 2 - halfArcWidth, arcY);
// path.relativeConicTo(halfArcWidth, -arcY, halfArcWidth * 2, 0, 1);
path.arcTo(
Rect.fromCircle(
center: Offset(pointerStartX + pointerWidth / 2, l),
radius: peakRadius),
-math.pi / 2 - arc,
arc * 2,
false);
path.lineTo(pointerEndX, pointerHeight);
path.lineTo(width - borderRadius, pointerHeight);
path.arcToPoint(Offset(width, pointerHeight + borderRadius),
radius: radius);
path.lineTo(width, height - borderRadius);
path.arcToPoint(Offset(width - borderRadius, height), radius: radius);
path.lineTo(borderRadius, height);
path.arcToPoint(Offset(0, height - borderRadius), radius: radius);
path.lineTo(0, pointerHeight + borderRadius);
path.arcToPoint(Offset(borderRadius, pointerHeight), radius: radius);
path.close();
} else {
final bottom = height - pointerHeight;
path.moveTo(pointerStartX, 0);
path.lineTo(width - borderRadius, 0);
path.arcToPoint(Offset(width, borderRadius), radius: radius);
path.lineTo(width, bottom - borderRadius);
path.arcToPoint(Offset(width - borderRadius, bottom), radius: radius);
path.lineTo(pointerEndX, bottom);
path.lineTo(pointerEndX - pointerWidth / 2 + halfArcWidth, height - arcY);
path.arcTo(
Rect.fromCircle(
center: Offset(pointerEndX - pointerWidth / 2, height - l),
radius: peakRadius),
math.pi / 2 - arc,
arc * 2,
false);
path.lineTo(pointerStartX, bottom);
path.lineTo(borderRadius, bottom);
path.arcToPoint(Offset(0, bottom - borderRadius), radius: radius);
path.lineTo(0, borderRadius);
path.arcToPoint(Offset(borderRadius, 0), radius: radius);
path.close();
}
path = path.shift(offset);
final innerPath = Path();
innerPath.addPath(path, Offset.zero);
var inflateRect = rect.inflate(strokeWidth / 2);
if (filter != null) {
context.pushClipPath(
needsCompositing,
const Offset(0, 0),
inflateRect,
path,
(PaintingContext innerContext, Offset innerOffset) {
innerContext.pushLayer(
BackdropFilterLayer(
filter: filter,
blendMode: blendMode,
),
(PaintingContext innerContext, Offset innerOffset) {},
innerOffset);
},
);
}
Canvas canvas = context.canvas;
canvas.saveLayer(inflateRect, painter);
canvas.drawPath(innerPath, backgroundPainter);
canvas.drawPath(path, paintBorderPainter);
canvas.restore();
}