getOuterPath method

  1. @override
Path getOuterPath(
  1. Rect rect, {
  2. TextDirection? textDirection,
})
override

Create a Path that describes the outer edge of the border.

This path must not cross the path given by getInnerPath for the same Rect.

To obtain a Path that describes the area of the border itself, set the Path.fillType of the returned object to PathFillType.evenOdd, and add to this object the path returned from getInnerPath (using Path.addPath).

The textDirection argument must be provided non-null if the border has a text direction dependency (for example if it is expressed in terms of "start" and "end" instead of "left" and "right"). It may be null if the border will not need the text direction to paint itself.

See also:

Implementation

@override
Path getOuterPath(Rect rect, {TextDirection? textDirection}) {
  // 修正塞贝尔曲线高度
  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;
  //角度
  double leftMargin = 0, rightMargin = 0, topMargin = 0, bottomMargin = 0;
  if (direction == BubbleDirection.left) {
    leftMargin += ah;
  } else if (direction == BubbleDirection.top) {
    topMargin += ah;
  } else if (direction == BubbleDirection.right) {
    rightMargin += ah;
  } else if (direction == BubbleDirection.bottom) {
    bottomMargin += ah;
  }

  /// 左上角半径
  path.moveTo(
    leftMargin,
    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),
    topMargin,
  );

  /// 上尖角
  if (direction == BubbleDirection.top) {
    double p = _getTopBottomPosition(size);

    path.lineTo(p - arrowAngle - smooth, topMargin);

    var x = arrowAngle * arrowQuadraticBezierLength / ah;

    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.lineTo(p + arrowAngle, topMargin);
  }

  /// 右上角半径
  path.lineTo(
    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),
  );

  /// 右尖角
  if (direction == BubbleDirection.right) {
    double p = _getLeftRightPosition(size);

    path.lineTo(size.width - rightMargin, p - arrowAngle - smooth);

    var x = ah * arrowQuadraticBezierLength / arrowAngle;

    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 - 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),
  );
  path.quadraticBezierTo(
      size.width - rightMargin,
      size.height - bottomMargin,
      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);

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

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

  /// 左下角半径
  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),
  );

  /// 左尖角
  if (direction == BubbleDirection.left) {
    double p = _getLeftRightPosition(size);
    path.lineTo(leftMargin, p + arrowAngle + smooth);
    var x = ah * arrowQuadraticBezierLength / arrowAngle;

    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.lineTo(
      leftMargin,
      topMargin +
          math.min(
              _min(position.start, radius.topRight.y, BubbleDirection.left),
              size.height));
  path = path.shift(rect.topLeft);
  path.close();
  return path;
}