Эх сурвалжийг харах

Merge branch 'master' into more_items_dev

melon.yin 2 жил өмнө
parent
commit
c686e574e8

+ 10 - 4
assets/items.json

@@ -1,11 +1,17 @@
 [
   {
-    "Name": "SV Diam",
-    "Description": "SV Diam",
-    "IsWorking": false,
+    "Name": "M_Distance",
+    "Description": "SV D",
     "ChildItems": [],
     "Calculator": { "AvailableOutputs": [{ "Name": "Distance", "Description": "Distance", "Unit": 11, "IsWorking": true }] },
-    "MeasureTypeName": "Distance"
+    "MeasureTypeName": "VerticalDistance"
+  },
+  {
+    "Name": "Timespan",
+    "Description": "SV Time",
+    "ChildItems": [],
+    "Calculator": { "AvailableOutputs": [{ "Name": "Timespan", "Description": "Time", "Unit": 20, "IsWorking": true }] },
+    "MeasureTypeName": "TimeSpan"
   },
   {
     "Name": "SV",

+ 21 - 0
lib/interfaces/process/items/terms.dart

@@ -12,6 +12,27 @@ class MeasureUnsupportedTerms {
 }
 
 class MeasureTerms {
+  /// M 模式(TissueTM)下的测量项
+  /// 见 Vinno.Modules.MeasureModule 内
+  /// ItemMetas\MeasureAppMetas.Config.cs
+  /// Line: 846-856
+  /// 距离 TODO: 因为当前使用的是 switchItemByName ,所以此处name先不与普通Distance重复
+  static const String MVerticalDistance = "M_Distance";
+
+  /// 心率
+  static const String Hr = "HR";
+
+  /// 狭窄率
+  static const String StenosisTwoVerticalDistance = "M_%Stenosis";
+
+  /// A/B比值 TODO ? See: Line: 858
+  // static const String CreateMAbRatio = "M_A/B Ratio";
+
+  /// 深度
+  static const String MDepth = "M_Depth";
+
+  ///////////////////////////////////////////////////////////////////////////////////////////////////////
+
   /* AI [begin]*/
   /// 前壁
   static const AntCCA_IMT = "Ant.CCA IMT";

+ 2 - 0
lib/interfaces/process/items/types.dart

@@ -89,4 +89,6 @@ class MeasureTypes {
 
   /// 残余尿
   static const ResidualUrine = "ResidualUrine";
+
+  static const TimeSpan = "TimeSpan";
 }

+ 5 - 3
lib/measure_page_test.dart

@@ -19,6 +19,7 @@ import 'package:fis_measure/process/workspace/measure_data_controller.dart';
 import 'package:fis_measure/view/measure/measure_main_view.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
+import 'package:vid/us/vid_us_mode.dart';
 
 import 'item_create_test.dart';
 import 'process/workspace/measure_handler.dart';
@@ -97,7 +98,8 @@ class _MeasureTestPageState extends State<MeasureTestPage> {
   static const C_LINEAR_TISSUE =
       // "http://cdn-bj.fis.plus/9F066341FA874E21B48CDE247C13D495.vid"; //B TVI TD
       // "http://cdn-bj.fis.plus/974BABA5113640639FD749E06DD7DA5B.vid"; //B CF CW
-      "http://cdn-bj.fis.plus/0B344F48BA574ECD82B7FEDB8848421A.vid"; //单幅TM
+      // "http://cdn-bj.fis.plus/0B344F48BA574ECD82B7FEDB8848421A.vid"; //单幅TM
+      "http://cdn-bj.fis.plus/3379F38302884C2991D90FBDFB0DEA7E.dat"; //单幅TM(2)
   // "http://cdn-bj.fis.plus/F26C6E5D57A7472A97E9EB543DF0D16C.vid"; // 单幅Convex
   // "http://cdn-bj.fis.plus/6B6E069659D14E7299EB9F6EFCDE9C8C.vid"; //双幅单TissueConvex
   // "http://cdn-bj.fis.plus/062643B82365437DB95F3811580AF3ED.vid"; //四幅单模式
@@ -359,8 +361,8 @@ class _MeasureLeftBoardState extends State<_MeasureLeftBoard> {
   ];
   // ignore: non_constant_identifier_names
   static final C_SUPPORTED_M_ITEMS = <String>[
-    // MeasureTerms.VerticalDistance,
-    "SV Diam",
+    MeasureTerms.MVerticalDistance,
+    MeasureTerms.Timespan,
   ];
 
   late final List<String> passeItems;

+ 40 - 0
lib/process/calcuators/time_motion.dart

@@ -0,0 +1,40 @@
+import '../primitives/straightline.dart';
+import 'calculator.dart';
+
+class VerticalDistanceCal extends Calculator<StraightLine, double> {
+  VerticalDistanceCal(StraightLine ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    final feature = ref.feature!;
+    final viewport = feature.hostVisualArea!.viewport!;
+    final p1 = feature.startPoint;
+    final p2 = feature.endPoint;
+    final pp1 = viewport.convert(p1);
+    final pp2 = viewport.convert(p2);
+
+    final value = (pp2.y - pp1.y).abs();
+    updateFloatValue(value);
+  }
+}
+
+class TimeSpanCal extends Calculator<StraightLine, double> {
+  TimeSpanCal(StraightLine ref) : super(ref);
+
+  @override
+  void calculate() {
+    if (ref.feature == null) return;
+
+    final feature = ref.feature!;
+    final viewport = feature.hostVisualArea!.viewport!;
+    final p1 = feature.startPoint;
+    final p2 = feature.endPoint;
+    final pp1 = viewport.convert(p1);
+    final pp2 = viewport.convert(p2);
+
+    final value = (pp2.x - pp1.x).abs();
+    updateFloatValue(value);
+  }
+}

+ 4 - 0
lib/process/items/factory.dart

@@ -85,6 +85,10 @@ class MeasureItemFactory {
     // Angle
     _singleton._register(
         MeasureTypes.PolyLineAngle, PolylineAngle.createPolyAngle);
+    // TissueTM
+    _singleton._register(
+        MeasureTypes.VerticalDistance, StraightLine.createVerticalDistance);
+    _singleton._register(MeasureTypes.TimeSpan, StraightLine.createTimeSpan);
 
     // Area Perimeter
     _singleton._register(

+ 7 - 0
lib/process/items/item_feature.dart

@@ -206,6 +206,13 @@ abstract class MeasureItemFeature implements IMeasureItemFeature {
     canvas.drawVertex(offset, vertexSize, active: active);
   }
 
+  /// 画短横标记
+  void drawMark(Canvas canvas, Offset offset,
+      [bool active = false, bool ifHorizontal = true]) {
+    canvas.drawMark(offset, vertexSize,
+        active: active, ifHorizontal: ifHorizontal);
+  }
+
   /// 计算文本长度
   static Size boundingTextSize(
     String text,

+ 74 - 1
lib/process/primitives/straightline.dart

@@ -4,15 +4,23 @@ import 'package:fis_measure/interfaces/date_types/point.dart';
 import 'package:fis_measure/interfaces/enums/items.dart';
 import 'package:fis_measure/interfaces/process/items/item.dart';
 import 'package:fis_measure/interfaces/process/items/item_metas.dart';
+import 'package:fis_measure/interfaces/process/items/terms.dart';
+import 'package:fis_measure/interfaces/process/items/types.dart';
 import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
+import 'package:fis_measure/process/calcuators/time_motion.dart';
 import 'package:fis_measure/process/items/item.dart';
 import 'package:fis_measure/utils/canvas.dart';
+import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
+import 'package:fis_measure/view/gesture/positioned_cursor.dart';
+import 'package:get/get.dart';
+import 'package:vid/us/vid_us_mode.dart';
 
 import '../calcuators/distance.dart';
 import '../items/item_feature.dart';
 
 /// 直线
 class StraightLine extends MeasureItem<StraightLineFeature> {
+  late final mouseState = Get.find<IMouseState>();
   StraightLine(ItemMeta meta, IMeasureItem? parent) : super(meta, parent);
 
   static StraightLine createDistance(ItemMeta meta, [IMeasureItem? parent]) {
@@ -21,6 +29,19 @@ class StraightLine extends MeasureItem<StraightLineFeature> {
     return sraightLine;
   }
 
+  static StraightLine createVerticalDistance(ItemMeta meta,
+      [IMeasureItem? parent]) {
+    StraightLine sraightLine = StraightLine(meta, parent);
+    sraightLine.calculator = VerticalDistanceCal(sraightLine);
+    return sraightLine;
+  }
+
+  static StraightLine createTimeSpan(ItemMeta meta, [IMeasureItem? parent]) {
+    StraightLine sraightLine = StraightLine(meta, parent);
+    sraightLine.calculator = TimeSpanCal(sraightLine);
+    return sraightLine;
+  }
+
   @override
   bool onExecuteMouse(PointInfo args) {
     if (state == ItemStates.finished) {
@@ -40,6 +61,10 @@ class StraightLine extends MeasureItem<StraightLineFeature> {
       doCalculate();
       if (args.pointType == PointInfoType.mouseDown) {
         doFeatureFinish();
+
+        ///重置十字样式
+        mouseState.crossIndicatorStyleChanged
+            .emit(this, CrossIndicatorStyle.nomal);
       }
     }
     return true;
@@ -83,12 +108,35 @@ class StraightLine extends MeasureItem<StraightLineFeature> {
     // TODO: 判断是否当前area
     // 转换为Area逻辑位置
     final point = args.toAreaLogicPoint();
-    feature = StraightLineFeature(this, point, point);
+    // feature = StraightLineFeature(this, point, point);
     if (args.hostVisualArea != null) {
+      handleTissueTM(args.hostVisualArea!.mode.modeType, point);
       feature!.hostVisualArea = args.hostVisualArea;
     }
     state = ItemStates.running;
   }
+
+  /// 处理TissueTimeMotion模式
+  void handleTissueTM(VidUsModeType mode, DPoint point) {
+    if (mode == VidUsModeType.TissueTM) {
+      switch (meta.measureType) {
+        case MeasureTypes.TimeSpan:
+          feature = StraightLineTimeMotionFeature(this, point, point,
+              ifHorizontal: false);
+          mouseState.crossIndicatorStyleChanged
+              .emit(this, CrossIndicatorStyle.vertical);
+          break;
+        case MeasureTypes.VerticalDistance:
+          feature = StraightLineTimeMotionFeature(this, point, point);
+          mouseState.crossIndicatorStyleChanged
+              .emit(this, CrossIndicatorStyle.horizontal);
+          break;
+        default:
+      }
+    } else {
+      feature = StraightLineFeature(this, point, point);
+    }
+  }
 }
 
 class StraightLineFeature extends MeasureItemFeature {
@@ -127,3 +175,28 @@ class StraightLineFeature extends MeasureItemFeature {
     drawVertex(canvas, endOffset, isActive);
   }
 }
+
+class StraightLineTimeMotionFeature extends StraightLineFeature {
+  StraightLineTimeMotionFeature(
+      IMeasureItem refItem, DPoint startPoint, DPoint endPoint,
+      {this.ifHorizontal = true})
+      : super(refItem, startPoint, endPoint);
+  final bool ifHorizontal;
+  @override
+  void paint(Canvas canvas, Size size) {
+    if (startPoint == endPoint) return;
+    var idText = '$id';
+    drawId(canvas, size, idText);
+
+    final startOffset = convert2ViewPoint(size, startPoint).toOffset();
+    final endOffset = convert2ViewPoint(size, endPoint).toOffset();
+    if (ifHorizontal) {
+      drawMark(canvas, startOffset);
+      drawMark(canvas, Offset(startOffset.dx, endOffset.dy), isActive);
+    } else {
+      drawMark(canvas, startOffset, false, ifHorizontal);
+      drawMark(
+          canvas, Offset(endOffset.dx, startOffset.dy), isActive, ifHorizontal);
+    }
+  }
+}

+ 29 - 0
lib/process/workspace/application.dart

@@ -418,6 +418,35 @@ class Application implements IApplication {
       return;
     }
 
+    if (name == MeasureTypes.VerticalDistance) {
+      activeMeasureItem = MeasureItemFactory.createItem(
+        ItemMeta(
+          MeasureTerms.MVerticalDistance,
+          measureType: MeasureTypes.VerticalDistance,
+          description: MeasureTypes.VerticalDistance,
+          outputs: [
+            ItemOutputMeta(MeasureTypes.VerticalDistance,
+                MeasureTypes.VerticalDistance, VidUsUnit.cm),
+          ],
+        ),
+      );
+      return;
+    }
+    if (name == MeasureTerms.Timespan) {
+      activeMeasureItem = MeasureItemFactory.createItem(
+        ItemMeta(
+          MeasureTerms.Timespan,
+          measureType: MeasureTypes.TimeSpan,
+          description: MeasureTerms.Timespan,
+          outputs: [
+            ItemOutputMeta(
+                MeasureTerms.Timespan, MeasureTerms.Timespan, VidUsUnit.s),
+          ],
+        ),
+      );
+      return;
+    }
+    print("Unknown measure type: $name");
     activeMeasureItem = null;
   }
 

+ 32 - 0
lib/utils/canvas.dart

@@ -254,4 +254,36 @@ extension MeasureCanvasExt on Canvas {
     drawPath(path, _vertexPaint);
     restore();
   }
+
+  static final Paint _markPaint = Paint()
+    ..strokeWidth = 1
+    ..style = PaintingStyle.stroke
+    ..isAntiAlias = false;
+
+  ///绘制短横标记
+  ///ifHorizontal true:横向标记 false:纵向标记
+  void drawMark(
+    Offset offset,
+    double size, {
+    bool active = false,
+    bool ifHorizontal = true,
+  }) {
+    final radius = size / 3.0;
+    double x = offset.dx, y = offset.dy;
+    save();
+    final path = Path();
+    // top_left -> bottom_right
+    if (ifHorizontal) {
+      path.moveTo(x - radius, y);
+      path.lineTo(x + radius, y);
+    } else {
+      path.moveTo(x, y - radius);
+      path.lineTo(x, y + radius);
+    }
+
+    _markPaint.color =
+        active ? MeasureColors.ActiveCaliper : MeasureColors.Primary;
+    drawPath(path, _markPaint);
+    restore();
+  }
 }

+ 5 - 3
lib/values/strings.dart

@@ -1,8 +1,10 @@
 // ignore_for_file: constant_identifier_names
+import 'package:flutter/foundation.dart';
 
 class MeasureStrings {
   static const PackageName = "fis_measure";
-  static const LayoutConfigurationAsset =
-      "packages/$PackageName/assets/layout.json";
-  // "assets/layout.json"; //TODO: melon - wait remove
+  // ignore: non_constant_identifier_names
+  static const LayoutConfigurationAsset = kIsWeb
+      ? "packages/$PackageName/assets/layout.json"
+      : "assets/layout.json"; // win debug 用
 }

+ 129 - 0
lib/view/gesture/cross_position_indicator.dart

@@ -0,0 +1,129 @@
+import 'package:fis_measure/values/colors.dart';
+import 'package:fis_measure/view/gesture/positioned_cursor.dart';
+import 'package:flutter/material.dart';
+import 'package:get/get.dart';
+import 'package:path_drawing/path_drawing.dart';
+
+class CrossIndicator extends StatefulWidget {
+  const CrossIndicator({Key? key, required this.areaRegion}) : super(key: key);
+  final Rect areaRegion;
+
+  @override
+  State<StatefulWidget> createState() => _CrossIndicatorState();
+}
+
+class _CrossIndicatorState extends State<CrossIndicator> {
+  final mouseState = Get.find<IMouseState>();
+  CrossIndicatorStyle indicatorStyle = CrossIndicatorStyle.nomal;
+
+  @override
+  void initState() {
+    mouseState.mousePositionChanged.addListener(mousePositionChanged);
+    mouseState.crossIndicatorStyleChanged
+        .addListener(_crossIndicatorStyleChanged);
+    super.initState();
+  }
+
+  @override
+  void dispose() {
+    mouseState.mousePositionChanged.removeListener(mousePositionChanged);
+    mouseState.crossIndicatorStyleChanged
+        .removeListener(_crossIndicatorStyleChanged);
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final position = mouseState.mousePosition;
+    if (position == null) return Container();
+    return Positioned(
+      top: widget.areaRegion.top,
+      width: widget.areaRegion.width,
+      height: widget.areaRegion.height,
+      child: RepaintBoundary(
+        child: CustomPaint(
+            painter: _CrossIndicatorPainter(
+                color: MeasureColors.Primary,
+                centerOffset:
+                    Offset(position.dx, position.dy - widget.areaRegion.top),
+                style: indicatorStyle)),
+      ),
+    );
+  }
+
+  void mousePositionChanged(Object sender, dynamic e) {
+    onUpdate();
+  }
+
+  void _crossIndicatorStyleChanged(Object sender, dynamic e) {
+    setState(() {
+      indicatorStyle = e;
+    });
+  }
+
+  void onUpdate() {
+    setState(() {});
+  }
+}
+
+class _CrossIndicatorPainter extends CustomPainter {
+  const _CrossIndicatorPainter(
+      {this.color, this.centerOffset, this.style = CrossIndicatorStyle.nomal});
+  final Color? color;
+  final Offset? centerOffset;
+  final CrossIndicatorStyle style;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    final paint = Paint()
+      ..color = color ?? const Color.fromARGB(255, 255, 255, 0)
+      ..strokeWidth = 2
+      ..style = PaintingStyle.stroke
+      ..isAntiAlias = false;
+    final center = centerOffset ?? Offset(size.width / 2, size.height / 2);
+    //绘制十字点路径
+    final path = Path();
+
+    switch (style) {
+      case CrossIndicatorStyle.nomal:
+        path
+          ..moveTo(center.dx, 0)
+          ..lineTo(center.dx, size.height)
+          ..moveTo(0, center.dy)
+          ..lineTo(size.width, center.dy);
+        break;
+      case CrossIndicatorStyle.vertical:
+        path
+          ..moveTo(center.dx, 0)
+          ..lineTo(center.dx, size.height);
+        break;
+      case CrossIndicatorStyle.horizontal:
+        path
+          ..moveTo(0, center.dy)
+          ..lineTo(size.width, center.dy);
+        break;
+    }
+    canvas.drawPath(
+        dashPath(
+          path,
+          dashArray: CircularIntervalList<double>([5, 10]),
+        ),
+        paint);
+  }
+
+  @override
+  bool shouldRepaint(covariant _CrossIndicatorPainter oldDelegate) {
+    return oldDelegate.color != color ||
+        oldDelegate.centerOffset != centerOffset ||
+        oldDelegate.style != style;
+  }
+}
+
+enum CrossIndicatorStyle {
+  ///标准状态
+  nomal,
+  //仅横指示线
+  horizontal,
+  //仅纵指示线
+  vertical,
+}

+ 85 - 2
lib/view/gesture/mouse_gesture.dart

@@ -1,7 +1,12 @@
+import 'package:fis_measure/interfaces/date_types/point.dart';
+import 'package:fis_measure/interfaces/date_types/rect.dart';
+import 'package:fis_measure/interfaces/date_types/rect_region.dart';
 import 'package:fis_measure/interfaces/process/workspace/application.dart';
 import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
+import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
+import 'package:vid/us/vid_us_visual_area_type.dart';
 
 import 'positioned_cursor.dart';
 
@@ -18,11 +23,15 @@ class _MeasureMouseGesturePanelState extends State<MeasureMouseGesturePanel> {
 
   final mouseState = Get.put<IMouseState>(MouseState());
   late final application = Get.find<IApplication>();
+  bool ifContainerTissueTM = false;
+  CursorDisplayType displayType = CursorDisplayType.none;
+  RectRegion tissueTMPixelRegion = RectRegion();
 
   @override
   void initState() {
     // TODO: from config
     mouseState.cursorSize = 32;
+    _findMultiRegions();
     super.initState();
   }
 
@@ -62,13 +71,87 @@ class _MeasureMouseGesturePanelState extends State<MeasureMouseGesturePanel> {
             event.localPosition,
             PointInfoType.mouseMove,
           );
+          _handleAreaChange(event.localPosition);
+        },
+        onEnter: (e) {
+          setState(() {
+            displayType = CursorDisplayType.normal;
+          });
+        },
+        onExit: (e) {
+          setState(() {
+            displayType = CursorDisplayType.none;
+          });
         },
         child: Stack(
-          children: const [
-            PositionedCursor(),
+          children: [
+            _buildCursor(),
           ],
         ),
       ),
     );
   }
+
+  Widget _buildCursor() {
+    switch (displayType) {
+      case CursorDisplayType.none:
+        return Container();
+      case CursorDisplayType.normal:
+        return const PositionedCursor();
+      case CursorDisplayType.cross:
+        return CrossIndicator(
+          areaRegion: Rect.fromLTRB(
+              tissueTMPixelRegion.left,
+              tissueTMPixelRegion.top,
+              tissueTMPixelRegion.right,
+              tissueTMPixelRegion.bottom),
+        );
+    }
+  }
+
+  void _handleAreaChange(Offset pointerOffset) {
+    if (ifContainerTissueTM) {
+      if (tissueTMPixelRegion
+          .containsPoint(DPoint.parseOffset(pointerOffset))) {
+        if (displayType != CursorDisplayType.cross) {
+          setState(() {
+            displayType = CursorDisplayType.cross;
+          });
+        }
+      } else {
+        if (displayType != CursorDisplayType.normal) {
+          setState(() {
+            displayType = CursorDisplayType.normal;
+          });
+        }
+      }
+    }
+  }
+
+  void _findMultiRegions() {
+    final displaySize = application.displaySize;
+    for (var visual in application.visuals) {
+      for (var area in visual.visualAreas) {
+        if (area.visualAreaType == VidUsVisualAreaType.TissueTimeMotion) {
+          ifContainerTissueTM = true;
+
+          ///TODO 此处选择用严格区域来作为 TissueTM 区域,也可以放宽到边界,以获得更好的体验
+          ///TODO Left 好像不准?需要其他相关组进行调整
+          tissueTMPixelRegion = RectRegion.rect(DRect(
+            // area.displayRegion.left * displaySize.width,
+            0,
+            area.displayRegion.top * displaySize.height,
+            area.displayRegion.width * displaySize.width,
+            area.displayRegion.height * displaySize.height,
+          ));
+        }
+      }
+    }
+  }
+}
+
+enum CursorDisplayType {
+  none,
+  cross,
+  normal,
 }

+ 5 - 0
lib/view/gesture/positioned_cursor.dart

@@ -1,6 +1,7 @@
 import 'package:fis_common/event/event_type.dart';
 import 'package:fis_measure/values/colors.dart';
 import 'package:fis_measure/view/cursor.dart';
+import 'package:fis_measure/view/gesture/cross_position_indicator.dart';
 import 'package:flutter/material.dart';
 import 'package:get/get.dart';
 
@@ -19,6 +20,7 @@ abstract class IMouseState {
   late FEventHandler<Offset?> mousePositionChanged;
   late FEventHandler<MeasureCursorType> cursorTypeChanged;
   late FEventHandler<double> cursorSizeChanged;
+  late FEventHandler<CrossIndicatorStyle> crossIndicatorStyleChanged;
 }
 
 class MouseState implements IMouseState {
@@ -35,6 +37,9 @@ class MouseState implements IMouseState {
   @override
   var cursorTypeChanged = FEventHandler<MeasureCursorType>();
 
+  @override
+  var crossIndicatorStyleChanged = FEventHandler<CrossIndicatorStyle>();
+
   @override
   Offset? get mousePosition => _mousePosition;
   @override

+ 17 - 10
lib/view/measure/measure_player.dart

@@ -18,6 +18,7 @@ class _MeasureRightBoardState extends State<MeasureRightBoard> {
   /// 数据
   final measureData = Get.find<MeasureDataController>();
   final measure3DViewController = Get.find<Measure3DViewController>();
+  bool get isShell => measure3DViewController.isShell;
 
   ///是否开启3D窗口
   bool enableMeasure3DView = false;
@@ -62,17 +63,23 @@ class _MeasureRightBoardState extends State<MeasureRightBoard> {
   FWidget buildView() {
     return FStack(
       children: [
-        // FOffstage(
-        //   offstage: !enableMeasure3DView,
-        //   child: Measure3DView(
-        //     key: ValueKey(measureData.itemCurrentImage),
-        //   ),
-        // ),
-        FOffstage(
-            offstage: enableMeasure3DView,
-            child: MeasureMainView(
+        if (isShell) ...[
+          FOffstage(
+            offstage: !enableMeasure3DView,
+            child: Measure3DView(
               key: ValueKey(measureData.itemCurrentImage),
-            )),
+            ),
+          ),
+          FOffstage(
+              offstage: enableMeasure3DView,
+              child: MeasureMainView(
+                key: ValueKey(measureData.itemCurrentImage),
+              )),
+        ] else ...[
+          MeasureMainView(
+            key: ValueKey(measureData.itemCurrentImage),
+          )
+        ]
       ],
     );
   }