diff --git a/lib/src/shape/bubble_shape_border.dart b/lib/src/shape/bubble_shape_border.dart index 45b26ff..d3ed282 100644 --- a/lib/src/shape/bubble_shape_border.dart +++ b/lib/src/shape/bubble_shape_border.dart @@ -187,12 +187,13 @@ class BubbleShapeBorder extends ShapeBorder { @override Path getOuterPath(Rect rect, {TextDirection? textDirection}) { // 修正塞贝尔曲线高度 - var arrowQuadraticBezierLength = - this.arrowQuadraticBezierLength > arrowHeight - ? arrowHeight - : this.arrowQuadraticBezierLength; + var arrowQuadraticBezierLength = this.arrowQuadraticBezierLength > arrowHeight ? arrowHeight : this.arrowQuadraticBezierLength; Size size = Size(rect.width, rect.height); + + //修改radius安全范围 + BorderRadius radius = _radius(size); + var path = Path(); //高度 double ah = arrowHeight; @@ -211,16 +212,12 @@ class BubbleShapeBorder extends ShapeBorder { /// 左上角半径 path.moveTo( leftMargin, - topMargin + - math.min(_min(position.start, radius.topLeft.y, BubbleDirection.left), - size.height), + topMargin + math.min(_min(position.start, radius.topLeft.y, BubbleDirection.left), size.height), ); path.quadraticBezierTo( leftMargin, topMargin, - leftMargin + - math.min(_min(position.start, radius.topLeft.x, BubbleDirection.top), - size.width), + leftMargin + math.min(_min(position.start, radius.topLeft.x, BubbleDirection.top), size.width), topMargin, ); @@ -232,33 +229,25 @@ class BubbleShapeBorder extends ShapeBorder { var x = arrowAngle * arrowQuadraticBezierLength / ah; - path.quadraticBezierTo(p - arrowAngle + smooth, topMargin, p - x, - arrowQuadraticBezierLength); + path.quadraticBezierTo(p - arrowAngle + smooth, topMargin, p - x, arrowQuadraticBezierLength); // path.lineTo(p - x, arrowQuadraticBezierLength); path.quadraticBezierTo(p, 0, p + x, arrowQuadraticBezierLength); - path.quadraticBezierTo(p + arrowAngle - smooth, topMargin, - p + arrowAngle + smooth, topMargin); + path.quadraticBezierTo(p + arrowAngle - smooth, topMargin, p + arrowAngle + smooth, topMargin); // path.lineTo(p + arrowAngle, topMargin); } /// 右上角半径 path.lineTo( - size.width - - rightMargin - - math.min(_min(position.end, radius.topRight.x, BubbleDirection.top), - size.width), + size.width - rightMargin - math.min(_min(position.end, radius.topRight.x, BubbleDirection.top), size.width), topMargin, ); path.quadraticBezierTo( size.width - rightMargin, topMargin, size.width - rightMargin, - topMargin + - math.min( - _min(position.start, radius.topRight.y, BubbleDirection.right), - size.height), + topMargin + math.min(_min(position.start, radius.topRight.y, BubbleDirection.right), size.height), ); /// 右尖角 @@ -269,82 +258,52 @@ class BubbleShapeBorder extends ShapeBorder { var x = ah * arrowQuadraticBezierLength / arrowAngle; - path.quadraticBezierTo(size.width - rightMargin, p - arrowAngle + smooth, - size.width - arrowQuadraticBezierLength, p - x); + path.quadraticBezierTo(size.width - rightMargin, p - arrowAngle + smooth, size.width - arrowQuadraticBezierLength, p - x); // path.lineTo(size.width - arrowQuadraticBezierLength, p - x); - path.quadraticBezierTo( - size.width, p, size.width - arrowQuadraticBezierLength, p + x); + path.quadraticBezierTo(size.width, p, size.width - arrowQuadraticBezierLength, p + x); - path.quadraticBezierTo(size.width - rightMargin, p + arrowAngle - smooth, - size.width - rightMargin, p + arrowAngle + smooth); + path.quadraticBezierTo(size.width - rightMargin, p + arrowAngle - smooth, size.width - rightMargin, p + arrowAngle + smooth); // path.lineTo(size.width - rightMargin, p + arrowAngle); } /// 右下角半径 path.lineTo( size.width - rightMargin, - size.height - - bottomMargin - - math.min( - _min(position.end, radius.bottomRight.y, BubbleDirection.right), - size.height), + size.height - bottomMargin - math.min(_min(position.end, radius.bottomRight.y, BubbleDirection.right), size.height), ); path.quadraticBezierTo( size.width - rightMargin, size.height - bottomMargin, - size.width - - rightMargin - - math.min( - _min( - position.end, radius.bottomRight.x, BubbleDirection.bottom), - size.width), + size.width - rightMargin - math.min(_min(position.end, radius.bottomRight.x, BubbleDirection.bottom), size.width), size.height - bottomMargin); /// 下尖角 if (direction == BubbleDirection.bottom) { double p = _getTopBottomPosition(size); - path.lineTo( - p + arrowAngle - rightMargin + smooth, size.height - bottomMargin); + path.lineTo(p + arrowAngle - rightMargin + smooth, size.height - bottomMargin); var x = arrowAngle * arrowQuadraticBezierLength / ah; // path.lineTo(p + x - rightMargin, size.height - arrowQuadraticBezierLength); path.quadraticBezierTo( - p + arrowAngle - rightMargin - smooth, - size.height - bottomMargin, - p + x - rightMargin, - size.height - arrowQuadraticBezierLength); + p + arrowAngle - rightMargin - smooth, size.height - bottomMargin, p + x - rightMargin, size.height - arrowQuadraticBezierLength); - path.quadraticBezierTo(p - rightMargin, size.height, p - rightMargin - x, - size.height - arrowQuadraticBezierLength); + path.quadraticBezierTo(p - rightMargin, size.height, p - rightMargin - x, size.height - arrowQuadraticBezierLength); // path.lineTo(p - arrowAngle - rightMargin, size.height - bottomMargin); path.quadraticBezierTo( - p - arrowAngle - rightMargin + smooth, - size.height - bottomMargin, - p - arrowAngle - rightMargin - smooth, - size.height - bottomMargin); + p - arrowAngle - rightMargin + smooth, size.height - bottomMargin, p - arrowAngle - rightMargin - smooth, size.height - bottomMargin); } /// 左下角半径 - path.lineTo( - leftMargin + - math.min( - _min(position.start, radius.bottomLeft.x, - BubbleDirection.bottom), - size.width), - size.height - bottomMargin); + path.lineTo(leftMargin + math.min(_min(position.start, radius.bottomLeft.x, BubbleDirection.bottom), size.width), size.height - bottomMargin); path.quadraticBezierTo( leftMargin, size.height - bottomMargin, leftMargin, - size.height - - bottomMargin - - math.min( - _min(position.end, radius.bottomLeft.y, BubbleDirection.left), - size.height), + size.height - bottomMargin - math.min(_min(position.end, radius.bottomLeft.y, BubbleDirection.left), size.height), ); /// 左尖角 @@ -353,24 +312,17 @@ class BubbleShapeBorder extends ShapeBorder { path.lineTo(leftMargin, p + arrowAngle + smooth); var x = ah * arrowQuadraticBezierLength / arrowAngle; - path.quadraticBezierTo(leftMargin, p + arrowAngle - smooth, - arrowQuadraticBezierLength, p + x); + path.quadraticBezierTo(leftMargin, p + arrowAngle - smooth, arrowQuadraticBezierLength, p + x); // path.lineTo(arrowQuadraticBezierLength, p + x); path.quadraticBezierTo(0, p, arrowQuadraticBezierLength, p - x); // path.lineTo(leftMargin, p - arrowAngle); - path.quadraticBezierTo(leftMargin, p - arrowAngle + smooth, leftMargin, - p - arrowAngle - smooth); + path.quadraticBezierTo(leftMargin, p - arrowAngle + smooth, leftMargin, p - arrowAngle - smooth); } /// 收尾 - path.lineTo( - leftMargin, - topMargin + - math.min( - _min(position.start, radius.topRight.y, BubbleDirection.left), - size.height)); + path.lineTo(leftMargin, topMargin + math.min(_min(position.start, radius.topRight.y, BubbleDirection.left), size.height)); path.close(); return path; } @@ -453,6 +405,54 @@ class BubbleShapeBorder extends ShapeBorder { return math.min(v1, v2); } + /// 对radius值做处理,防越界 + BorderRadius _radius(Size size) { + double topLeftX = 0, topLeftY = 0, topRightX = 0, topRightY = 0, bottomLeftX = 0, bottomLeftY = 0, bottomRightX = 0, bottomRightY = 0; + switch(direction){ + case BubbleDirection.left: + topLeftY = size.height - _getLeftRightPosition(size) - arrowAngle / 2 + smooth; + bottomLeftY = _getLeftRightPosition(size) - arrowAngle / 2 + smooth; + break; + case BubbleDirection.right: + topRightY = size.height - _getLeftRightPosition(size) - arrowAngle / 2 + smooth; + bottomRightY = _getLeftRightPosition(size) - arrowAngle / 2 + smooth; + break; + case BubbleDirection.top: + topLeftX = size.width - _getTopBottomPosition(size) - arrowAngle / 2 + smooth; + topRightX = _getTopBottomPosition(size) - arrowAngle / 2 + smooth; + break; + case BubbleDirection.bottom: + bottomLeftX = size.width - _getTopBottomPosition(size) - arrowAngle / 2 + smooth; + bottomRightX = _getTopBottomPosition(size) - arrowAngle / 2 + smooth; + break; + default: + } + BorderRadius _radius = radius.copyWith( + topLeft: Radius.elliptical( + _s(radius.topLeft.x, radius.topRight.x, size.width - topLeftX), + _s(radius.topLeft.y, radius.bottomLeft.y, size.height - topLeftY), + ), + topRight: Radius.elliptical( + _s(radius.topRight.x, radius.topLeft.x, size.width - topRightX), + _s(radius.topRight.y, radius.bottomRight.y, size.height - topRightY), + ), + bottomLeft: Radius.elliptical( + _s(radius.bottomLeft.x, radius.bottomRight.x, size.width - bottomLeftX), + _s(radius.bottomLeft.y, radius.topLeft.y, size.height - bottomLeftY), + ), + bottomRight: Radius.elliptical( + _s(radius.bottomRight.x, radius.bottomLeft.x, size.width - bottomRightX), + _s(radius.bottomRight.y, radius.topRight.y, size.height - bottomRightY), + ), + ); + return _radius; + } + + /// 比例最小值 + double _s(double s1, double s2, double length) { + return math.min(math.min(s1, s1 / (s1 + s2) * length), length); + } + /// copyWith the border BubbleShapeBorder copyWith({ final BubbleDirection? direction, @@ -471,8 +471,7 @@ class BubbleShapeBorder extends ShapeBorder { direction: direction ?? this.direction, arrowHeight: arrowHeight ?? this.arrowHeight, arrowAngle: arrowAngle ?? this.arrowAngle, - arrowQuadraticBezierLength: - arrowQuadraticBezierLength ?? this.arrowQuadraticBezierLength, + arrowQuadraticBezierLength: arrowQuadraticBezierLength ?? this.arrowQuadraticBezierLength, position: position ?? this.position, border: border ?? this.border, radius: radius ?? this.radius,