Crop and Fit

 

The part that displays the content of the video in fijkplayer library is class FijkView.

FijkView

FijkView is a StatefulWidget that internally calculates the final areas to display the video based on the video aspect ratio and crop mode parameters, it also will construct a component tree containing Texture in the build method of the State class.

In an actual application, the relative relationship between the actual video display area (hereafter referred to as the video area) and the size of the FijkView area may be adjusted as needed. The adjustments allow the video to be displayed within a portion of the FijkView, the entire Fijkview, or exceeding the display area of the Fijkview(which will be cut) as required for the application.

The three most common cases are listed in the figure below. The blue wireframe in the figure represents the FijkView area, the gray rectangle and the circular texture in it represent the Video area. As the right part of the figure shows, the area over the blue wireframe is not actually displayed. fitmode

The constructor for FijkView is as follows (the optional parameters that are not concerned in this section are omitted):

FijkView({
    @required FijkPlayer player,
    double width,
    double height,
    Color color = Colors.blueGrey,
    FijkFit fit = FijkFit.contain,
});
  • The parameter player is the actual kernel player. FijkView will call the video output interface of the player to get the video frame to display.
  • The parameter width controls the width of the FijkView, which is optional and can be empty. When width == null, the FijkView width will be as large as possible, and FijkView’s BuildContext must set a maximum width.
  • The parameter height controls the height of the FijkView, which is optional and can be empty. When height == null, the FijkView height will be as large as possible, and the FijkView’s BuildContext must set a maximum height.
  • The parameter color is the background color of FijkView. When the Video area is smaller than the FijkView area, the area outside the Video inside FijkView is displayed as the background color.
  • The parameter fit actually controls the display fill and crop mode of FijkView. It is the key point of this section.

FijkFit

const FijkFit({
    double aspectRatio = -1,
    double sizeFactor = 1.0,
    Alignment alignment = Alignment.center,
});

The three steps of layout calculation

FijkView completely controls the fill crop mode of the actual video content in FijkView with three parameters in FijkFit. The layout calculation can also be performed step by step according to these three parameters.

  1. aspectRatio calculation
    Let’s take the actual code as an example to illustrate how the final aspectRatio is calculated. The Video area is scaled according to the final calculated aspectRatio.
    double getAspectRatio(BoxConstraints constraints) {
     double ar = widget.fit.aspectRatio;
     if (ar == null || ar < 0) {
         ar = _vWidth / _vHeight;
     } else if (ar.isInfinite) {
         ar = constraints.maxWidth / constraints.maxHeight;
     }
     return ar;
    }
    

    The parameter constraints is the BoxConstraints of FijkView , dynamically obtained through LayoutBuilder .
    _vWidth _vHeight is the pixel width and height of the actual video。
    If aspectRatio in fit is negative or null, the final aspectRatio will be the actual video aspect ratio. If aspectRatio in fit is infinity, the final aspectRatio will be the aspect ratio of the FijkView region. If aspectRatio don’t match any of the above, then the final aspectRatio is the aspectRatio value set in fit.

  2. Size calculation
    The size of FijkView is as large as possible within the given width , height or BoxConstraints limits. Upon setting the size of the FijkView, the aspectRatio and sizeFactor variables will determine the video area size. The function determing a suitable Video area size through the aspectRatio and the BoxConstraints, it’s implementation took inspiration from the method Size _applyAspectRatio (BoxConstraints constraints) of the Flutter sdk class RenderAspectRatio; The base video area size multiplied by the sizeFactor results in the video area size. This size may exceed the size of the FijkView on one or both axes in which case the excess will be cut from the final drawing. The countable special values ​​of sizeFactor will be recalculated at this stage: (-1.0, -0.0) => max(FijkView.size.width / video.size.width , FijkView.size.height / video.size.heigit)
    (-2.0, -1.0) => FijkView.size.width / video.size.width
    (-3.0, -2.0) => FijkView.size.height / video.size.heigit

  3. Position adjusting
    After determining FijkView size and Video size, the final step is to determine the relative position of the Video area in FijkView.
    final Alignment resolvedAlignment = widget.fit.alignment;
    final Offset diff = constraints.biggest - childSize;
    final Offset offset = resolvedAlignment.alongOffset(diff);
    final Rect pos = Rect.fromLTWH(offset.dx, offset.dy, childSize.width, childSize.height);
    

    In the above snippet, constraints.biggest is the size of FijView, and childSize is the size of the Video area. The calculated pos is the position information of the Video display area relative to FijkView. Fijk implements a relative position layout by harnessing both the Stack and Positioned widgets.

    Positioned.fromRect(
     rect: pos,
     child: buildVideoDisplay(),
    );
    

Layout sample

Original video content.

原始比例视频内容

  • FijkFit.contain
static const FijkFit contain = FijkFit(
    sizeFactor: 1.0,
    aspectRatio: -1,
    alignment: Alignment.center,
);


  • FijkFit.fill
static const FijkFit fill = FijkFit(
    sizeFactor: 1.0,
    aspectRatio: double.infinity,
    alignment: Alignment.center,
);


  • FijkFit.cover
static const FijkFit cover = FijkFit(
    sizeFactor: -0.5,
    aspectRatio: -1,
    alignment: Alignment.center,
);

You can freely combine the construction parameters of FijkFit to achieve the video fill effect you want after understanding the layout process of FijkFit.


Support me in the following ways:

  • Star this project   给该项目点赞
  • Follow me on Github   关注我的 Github
  • Buy me a coffee. Tip Me via PayPal