Flutter displays the guide page of the bottom control

Requirements: Two different entrances to the same page, the position of the same control changes, and the position of the guidance content corresponding to this control also needs to be changed when the guidance page is displayed; at the same time, the translucent bottom displays the real page content.
If you need to cut the picture and then paste it on the page, the position cannot be accurately aligned.
Idea: First draw a layer of semi-transparent mask to cover the page, draw it fully transparent at the position of the control that needs to be displayed, and then draw the guide content on the mask (there are three layers, real page, transparent mask. Those corresponding to the control Description content), get the position of the control and determine where it is fully transparent.

Upon entering the entrance:

When entering through entrance two:

import 'package:common/sp_util.dart';
import 'package:jade/configs/CommonConfig.dart';
import 'package:jade/configs/PathConfig.dart';
import 'package:jade/utils/JadeColors.dart';
import 'package/jade/utils/Utils.dart';
import 'package:util/navigator_util.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/*
* Guide pages
* */
class SharedPurchaseGuidePage extends StatelessWidget {<!-- -->
  final double width;
  final double height;
  final Offset offset;
  const SharedPurchaseGuidePage({<!-- -->this.width,this.height,this.offset});

  @override
  Widget build(BuildContext context) {<!-- -->
    return WillPopScope(
      child: Stack(
        children: [
          CustomPaint(
            size: Size(Utils().screenWidth(context), Utils().screenHeight(context)), // Customize the size of the Widget
            painter: MyCustomPainter(width,height,offset),
          ),
          Positioned(
              left: offset.dx + width,
              top: offset.dy,
              child: _leftView(context))
        ],
      ),
      onWillPop: () async => false,);
  }

  _leftView(context){<!-- -->
    return Container(
      width: Utils().screenWidth(context) * 0.68,
      height: 210.w,
      padding: EdgeInsets.symmetric(vertical: 28.w),
      decoration: BoxDecoration(
          image: DecorationImage(
              image: AssetImage(PathConfig.imageSharedPurchaseGuideBg),
              fit: BoxFit.fill)
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          Row(
            mainAxisAlignment: MainAxisAlignment.end,
            children: [
              Text('Click to learn about shared shopping',style: TextStyle(color: Colors.white,fontSize: 28.sp,fontWeight: FontWeight.w600)),
              SizedBox(width: 54.w),
              GestureDetector(
                child: Container(
                  width: 100.w,
                  height: 40.w,
                  alignment:Alignment.center,
                  margin: EdgeInsets.only(right: 20.w),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(20),
                  ),
                  child: Text('got it',style: TextStyle(color: JadeColors.blue,fontSize: 22.sp,fontWeight: FontWeight.w600),),
                ),
                onTap: (){<!-- -->
                  SpUtil.putBool(CommonConfig.havePostDetailSharedPurchaseGuide, true);
                  NavigatorUtil.pop();
                },
              )
            ],
          ),
          Container(
            margin: EdgeInsets.only(right: 20.w,top: 26.w),
            child: Text('In order to promote transactions, this section has added a unique shared purchase function, which is very different from traditional group purchases and ordering. Welcome to experience it!', style: TextStyle(color: Colors.white, fontSize: 22.sp))
          )
        ],
      ),
    );
  }
}

class MyCustomPainter extends CustomPainter {<!-- -->
  final double width;
  final double height;
  final Offset offset;
  const MyCustomPainter(this.width,this.height,this.offset);
  @override
  void paint(Canvas canvas, Size size) {<!-- -->
    //background
    Paint backgroundPaint = Paint()
      ..color = Colors.black45
      ..style = PaintingStyle.fill;

    //Add a background path
    Path path = Path()
      ..addRect(Rect.fromLTWH(0, 0, size.width, size.height));


    //Blank rounded rectangular path
    Path holePath = Path()
     // ..addRect(Rect.fromLTWH(offset.dx, offset.dy, width, height));
      ..addRRect(RRect.fromRectAndRadius(Rect.fromLTWH(offset.dx-5, offset.dy, width + 5, height), Radius.circular(5)));

    Path combinedPath = Path.combine(PathOperation.difference, path, holePath);
    canvas.drawPath(combinedPath, backgroundPaint);

  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {<!-- -->
    return false; // No need to redraw because we are only drawing once and there is no animation or state change
  }
}
GlobalKey _sharedPurchaseKey = new GlobalKey();
//Requires fully transparent controls
Row(
                  key: _sharedPurchaseKey,
                  children: [
                    Text(S.current.sharedPurchase,style: TextStyle(color: JadeColors.blue,fontSize: 24.sp,fontWeight: FontWeight.bold)),
                    GestureDetector(
                      child: Container(
                        color: Colors.transparent,
                        padding: EdgeInsets.all(4),
                        child: Image.asset(PathConfig.iconQuestion,width: 34.w,height: 34.w),
                      ),
                      onTap: (){<!-- -->
                        NavigatorUtil.push(SharedPurchaseDesc());
                      },
                    ),
                  ],
                ),

//Get the coordinates of the shared purchase text plus question mark and jump (this method needs to be called after the page is loaded)
  _getOffset() {<!-- -->
    if(_sharedPurchaseKey.currentContext != null){<!-- -->
      _sharedPurchaseWidth = _sharedPurchaseKey.currentContext.size.width;
      _sharedPurchaseHeight = _sharedPurchaseKey.currentContext.size.height;
      _offset = WidgetUtil.getWidgetLocalToGlobal(_sharedPurchaseKey.currentContext);
      bool sharedPurchaseGuide = SpUtil.getBool(CommonConfig.havePostDetailSharedPurchaseGuide,defValue: false);
      if(!sharedPurchaseGuide){<!-- -->
      //Jump to a transparent page
        NavigatorUtil.pushTransparentRoute(SharedPurchaseGuidePage(width: _sharedPurchaseWidth,height: _sharedPurchaseHeight,offset: _offset));
      }
    }
  }
  
 ///Get the coordinates of the widget on the screen. Widgets must be rendered completely.
  ///Get the coordinates of the widget on the screen. The widget must be rendered.
  static Offset getWidgetLocalToGlobal(BuildContext context) {<!-- -->
    RenderBox box = context.findRenderObject();
    return box == null ? Offset.zero : box.localToGlobal(Offset.zero);
  }