Background: why develop this component? At present, video synthesis technology is used in our flitter app, which involves the clipping of video or picture materials. At present, the common components in the market are based on pictures, and basically use canvas for rendering and clipping, which does not meet our business needs, so we need to develop a clipping component ourselves.



Demand analysis

At the beginning of requirement design, considering the habit of gesture and referring to most editing tools, the following requirements are defined:

  • The clipping Box is fixed in a position on the screen. The position and size of the material can be adjusted by dragging with one finger and zooming with two fingers to frame the clipping range

  • The minimum edge of the material cannot be less than the corresponding edge of the clipping box, that is, the clipping Box can only move relatively within the range of the material

  • The types of supporting materials include pictures and videos


cropRectRectIf you do not fill in the initial clipping region, it will be filled and centered by default, which is similar to cover-
clipSizeSizeSize of material to be cutRequired
cropRatioSizeCrop box scale, default16:9Size(16, 9)
childWidgetMaterial to be cutRequired
maxCropSizeSizeThe maximum width and height of the current scale of the clipping box is mainly used when the size of the clipping box needs to be adjusted actively. If there is no special requirement, it does not need to be configuredCalculate based on parent component
maxScaleDoubleMaximum size allowed to enlarge10.0
borderColorColorCrop box border colorColors.White
cropRectUpdateStartFunctionCallback when crop region begins to change-
cropRectUpdateFunction(Rect rect)Callback when clipping region changes-
cropRectUpdateEndFunction(Rect rect)Callback when clipping region endRequired

Demo code

Can see example in github



  crop_box: ^0.1.0


import 'package:crop_box/crop_box.dart';

// ...

  // cropRect: Rect.fromLTRB(1 - 0.4083, 0.162, 1, 0.3078), // 2.4倍 随机位置
  // cropRect: Rect.fromLTRB(0, 0, 0.4083, 0.1457), //2.4倍,都是0,0
  cropRect: Rect.fromLTRB(0, 0, 1, 0.3572), // 1倍
  clipSize: Size(200, 315),
  cropRatio: Size(16, 9),
  cropRectUpdateEnd: (rect) {
    print("rect final $rect");
  cropRectUpdate: (rect) {
    print("rect change $rect");
    width: double.infinity,
    height: double.infinity,
    fit: BoxFit.cover,
    loadingBuilder: (BuildContext context, Widget child, ImageChunkEvent loadingProgress) {
      if (loadingProgress == null)
        return child;
      return Center(
        child: CircularProgressIndicator(
          value: loadingProgress.expectedTotalBytes != null
              ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes
              : null,


  • x Dynamically transform crop box scale

  • Optimize boundary calculation code

  • Support the drawing of fillet clipping box

  • Support rotation