昼夜节律下的肝脏代谢清除率演算仪:基于鸿蒙Flutter的双路流场与酶解粒子对照架构

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net




一、 肝小叶迷宫与细胞色素 P450 的微观战争

在生物组学与系统生物学的视野中,人体的每一次心跳、每一轮代谢都伴随着内源性废料(如氨、胆红素)与外源性毒素(如酒精、药物代谢产物)的生成。肝脏(Liver),作为人体最核心的生化反应堆,通过其数以百万计的肝小叶(Hepatic Lobules)进行着精密的向心过滤。而这场过滤战役的主力军,便是大名鼎鼎的细胞色素 P450(CYP450)超家族酶类。

然而,最新的临床代谢组学数据无情地揭示了一条铁律:CYP450的合成与活性,深度受制于宿主的昼夜节律(Circadian Rhythm)与深度睡眠时长。在睡眠剥夺的极端状态下,酶的转录被阻断,毒素如同脱缰的野马,从汇管区侵入肝血窦,却无法被有效地中和,最终导致脂质过氧化(Lipid Peroxidation)与不可逆的肝纤维化(Hepatic Fibrosis)。

本文将以极致的跨端前端架构为载体,通过 Flutter 的底图 Canvas 原语结合数据驱动模型,构建一台拥有双路环境(对照组 vs 干预实验组)的《肝脏代谢清除率演算仪》。在本项目中,我们将彻底驯服横跨桌面、平板、手机的 Overflow 布局溢出痛点,以严谨的代码与申论般的逻辑,向您呈现昼夜节律干预下的微观流体力学悲歌。


二、 数学建模: CYP450 活性与流场渗透概率

为了在前端内存中重构肝脏代谢系统,我们需要构建一套独立于后端的微积分演进模型。

2.1 CYP450 活性的 Sigmoid 衰减拟合

传统的线性衰减无法反映生物酶在面临压力时的"崩溃点"。我们采用类 Sigmoid 变种函数来拟合 CYP450 活性( E c y p E_{cyp} Ecyp)与实际睡眠时长( S t i m e S_{time} Stime)之间的非线性关系:

E c y p ( S t i m e ) = 100 ⋅ 1 1 + e − 1.2 ⋅ ( S t i m e − 4.5 ) E_{cyp}(S_{time}) = 100 \cdot \frac{1}{1 + e^{-1.2 \cdot (S_{time} - 4.5)}} Ecyp(Stime)=100⋅1+e−1.2⋅(Stime−4.5)1

通过该函数,当 S t i m e ≥ 8 S_{time} \ge 8 Stime≥8 时,酶活性趋于健康的 100%;而当睡眠跌破 4.5 小时的生死线时,酶活性将发生雪崩式断崖下降。

2.2 毒素粒子向心流场中的解毒概率

每一颗由周边向中心(中央静脉)渗透的毒素粒子(Toxin Particle),在流经肝索的每一个时间积分( d t dt dt)内,都有被 CYP450 酶中和转化为无毒水溶性物质的概率( P d e t o x P_{detox} Pdetox)。这表现为一个离散的泊松过程:

P d e t o x = α ⋅ E c y p 100 ⋅ d t P_{detox} = \alpha \cdot \frac{E_{cyp}}{100} \cdot dt Pdetox=α⋅100Ecyp⋅dt

若粒子在到达中央静脉前未命中该概率,则会在肝血窦中滞留并淤积,引发周围肝星状细胞的活化,即 UI 界面上呈现的【脂化/纤维化指数】的飙升。


三、 双环境隔离流水的系统工程抽象

为防止两组数据的交叉污染以及避免 Widget 构建树的冗余计算,本系统在工程架构上引入了严格的 MVC 隔离模式。
图 1:生化双引擎与渲染管线拓扑图
S_time 更新
写保护隔离
Tick dt 积分
Tick dt 积分
Slider 昼夜节律控制板
实验组肝脏环境
对照组肝脏环境 S_time=8.0
实验组向心流场演算: 酶活性降低, 毒素拥堵
对照组向心流场演算: 酶解迅速, 通畅排空
实验组 CustomPainter 重绘
对照组 CustomPainter 重绘


四、 跨端架构深度解剖:四点核心源码决战防溢出

在 Flutter 开发界,伴随多端分辨率剧变而来的 RIGHT OVERFLOWED BY XX PIXELS 犹如梦魇。在本系统的四段核心代码中,我们将展示如何通过弹性力学容器与底层 Canvas 逃逸,彻底消灭这一宿敌。

4.1 核心源码一:领域环境的内存级封装与生化推演

所有业务逻辑全部前置,且被封装于独立的 LiverEnvironment 类中。通过 isControlGroup 标识,我们将对照组的数据彻底锁死在最佳生理态,保障了生物学比对的严谨性。

dart 复制代码
// -----------------------------------------------------
// 核心源码一:肝脏生化流场与清除率方程
// -----------------------------------------------------
class LiverEnvironment {
  final bool isControlGroup;
  double targetSleepDuration; 
  double cyp450EnzymeLevel = 100.0; 
  double toxinLoadPercentage = 0.0; 
  
  void _updateBiochemicalField() {
    // 强制防呆:防止对照组被外部 Slider 污染
    if (isControlGroup) {
      targetSleepDuration = 8.0; 
    }

    // Sigmoid 酶活性衰减数学拟合
    cyp450EnzymeLevel = 100.0 * (1.0 / (1.0 + exp(-1.2 * (targetSleepDuration - 4.5))));

    // 毒素滞留浓度计算
    if (particles.isNotEmpty) {
      int toxicCount = particles.where((p) => !p.isNeutralized).length;
      toxinLoadPercentage = (toxicCount / particles.length) * 100.0;
    }
  }
}

4.2 核心源码二:微积分粒子流体动力学

我们绕开了繁重的 AnimatedBuilder 或海量的组件堆叠,在每一帧的回调(Tick)中直接利用三角函数推演粒子的向心渗透。同时,融入纤维化带来的微观流速阻力。

dart 复制代码
// -----------------------------------------------------
// 核心源码二:毒素粒子的向心渗透碰撞检测
// -----------------------------------------------------
    for (int i = particles.length - 1; i >= 0; i--) {
      var p = particles[i];
      p.lifetime += dt;

      // CYP450 酶促概率判定:睡眠越少,解毒概率越趋近于零
      if (!p.isNeutralized) {
        double detoxProbability = (cyp450EnzymeLevel / 100.0) * 0.02; 
        if (_rnd.nextDouble() < detoxProbability) {
          p.isNeutralized = true;
          p.speed *= 2.5; // 水溶化后加速通过中央静脉
        }
      }

      // 根据纤维化危机的渗透阻力模型
      double resistance = p.isNeutralized ? 1.0 : max(0.2, 1.0 - (fibrosisRiskIndex * 0.005));
      p.x += cos(p.angle) * p.speed * dt * resistance + (_rnd.nextDouble() - 0.5) * 2.0;
      p.y += sin(p.angle) * p.speed * dt * resistance + (_rnd.nextDouble() - 0.5) * 2.0;
      
      // [...] 中央静脉排空判定
    }

4.3 核心源码三:双路对照视窗与弹性降维打击

这是解决屏幕溢出问题的核武器。我们不能假设宿主设备拥有无限宽度。通过 LayoutBuilder 嗅探物理极限,当宽度跌破 750px(如手机竖屏)时,立刻从水平比对(Row)降维为垂直比对(Column)。而无处不在的 Expanded 则彻底吞噬了任何向外延展的不稳定边界。

dart 复制代码
// -----------------------------------------------------
// 核心源码三:防溢出响应式双态视窗管线
// -----------------------------------------------------
  Expanded(
    child: LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth > 750) {
          return Row(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Expanded(child: _buildHepaticViewport('标准对照组', _controlEnv)),
              const SizedBox(width: 16),
              Expanded(child: _buildHepaticViewport('干预实验组', _experimentEnv)),
            ],
          );
        } else {
          // 窄屏触发降维防御:纵向层叠
          return Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Expanded(child: _buildHepaticViewport('标准对照组', _controlEnv)),
              const SizedBox(height: 16),
              Expanded(child: _buildHepaticViewport('干预实验组', _experimentEnv)),
            ],
          );
        }
      },
    ),
  ),

不仅在主框架中,哪怕是小如数据播报面板的局部,我们也严禁使用具有无限横向延展风险的 Row,转而使用 Wrap 组件,辅以 spacingrunSpacing。如此一来,纵使内部数字跳跃导致长度剧增,也会被安全折流进下一行。

4.4 核心源码四:高维 Canvas 直接绘制与发光滤镜

由于粒子数量在极端拥堵时会达到数百,且其坐标与颜色透明度每 16.6ms 都在狂暴重塑,必须祭出原生的 Canvas。利用 MaskFilter.blur 模拟了毒素粒子的放射性与酶促反应的生命光晕。

dart 复制代码
// -----------------------------------------------------
// 核心源码四:高频粒子流场原语绘制
// -----------------------------------------------------
  @override
  void paint(Canvas canvas, Size size) {
    // [...] 省略背景与肝索线绘制
    final Paint particlePaint = Paint();
    
    for (var p in env.particles) {
      if (p.isNeutralized) {
        // 清洁水分子
        particlePaint.color = const Color(0xFF42A5F5).withOpacity(0.6);
        particlePaint.maskFilter = null; 
      } else {
        // 剧毒代谢废料堆积:荧光亮黄绿
        double toxicIntensity = (p.lifetime / 10.0).clamp(0.0, 1.0);
        int r = (100 + 155 * toxicIntensity).toInt();
        int g = (255 - 100 * toxicIntensity).toInt();
        particlePaint.color = Color.fromARGB(220, r, g, 50);
        particlePaint.maskFilter = const MaskFilter.blur(BlurStyle.solid, 3.0); 
      }
      double radius = p.isNeutralized ? 2.5 : 3.5 + (env.fibrosisRiskIndex * 0.05);
      canvas.drawCircle(Offset(p.x, p.y), radius, particlePaint);
    }
  }

五、 结尾:从代码架构审视生命哲学的必然

这套由 main.dart 单文件承载的宏大代谢演算仪,向我们直观而冷酷地揭露了一个事实:

在代码的世界里,只要做好弹性布局(Expanded),内存就不再轻易越界;而在生命系统的架构中,一旦对生物钟(Circadian Rhythm)的约束失去敬畏,毒素必将淤积成无可挽回的纤维化灾变。

当您在系统右侧滑动干预条,将虚拟生命的睡眠剥离殆尽时,满屏凄厉的荧光绿粒子淤积与紫红色警告光晕,其实也是生命对碳基体躯发出的最沉痛控诉。我们所设计的每一个 clamp(0.0, 1.0) 与边界检测判断,也是在祈愿每一位开发者在浩瀚的项目周期中,依然能找到属于自己生命的平衡原点。


源码

bash 复制代码
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';

void main() {
  runApp(const HepaticDetoxSimulatorApp());
}

class HepaticDetoxSimulatorApp extends StatelessWidget {
  const HepaticDetoxSimulatorApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '肝脏代谢演算仪',
      theme: ThemeData(
        brightness: Brightness.dark,
        scaffoldBackgroundColor: const Color(0xFF070B14), // 极深暗黑
        fontFamily: 'Courier',
        sliderTheme: SliderThemeData(
          activeTrackColor: const Color(0xFF00FFCC),
          inactiveTrackColor: Colors.white24,
          thumbColor: const Color(0xFF00FFCC),
          overlayColor: const Color(0xFF00FFCC).withOpacity(0.2),
        ),
      ),
      home: const HepaticHomeScreen(),
    );
  }
}

// ==========================================
// 领域模型:肝小叶微循环与毒素渗透流场
// ==========================================

class ToxinParticle {
  double x;
  double y;
  double angle;     // 朝向中心的角度
  double speed;     // 径向向心流速
  bool isNeutralized; // 是否已被酶解
  double lifetime;    // 存在时间,用于淤积变色判定

  ToxinParticle({
    required this.x,
    required this.y,
    required this.angle,
    required this.speed,
    this.isNeutralized = false,
  }) : lifetime = 0;
}

class LiverEnvironment {
  final bool isControlGroup;
  double targetSleepDuration; // 用户给定的睡眠时长 (Control 组固定为 8)
  
  // 核心演算指标
  double cyp450EnzymeLevel = 100.0; // 细胞色素 P450 活性基线 (0-100)
  double toxinLoadPercentage = 0.0; // 毒素淤积率 (0-100%)
  double fibrosisRiskIndex = 0.0;   // 纤维化/脂质过氧化风险指数
  
  List<ToxinParticle> particles = [];
  final Random _rnd = Random();

  LiverEnvironment({this.isControlGroup = false, this.targetSleepDuration = 8.0});

  // 更新肝脏生化流场方程
  void _updateBiochemicalField() {
    if (isControlGroup) {
      targetSleepDuration = 8.0; 
    }

    // 数学拟合:睡眠不足导致酶合成显著受阻
    // 采用 S 型曲线 (Sigmoid-like) 或指数衰减拟合
    // S=8 时酶活性最高(100), S=4 时大约剩余(30)
    cyp450EnzymeLevel = 100.0 * (1.0 / (1.0 + exp(-1.2 * (targetSleepDuration - 4.5))));

    // 毒素淤积计算:未被中和的粒子占比
    if (particles.isEmpty) {
      toxinLoadPercentage = 0;
    } else {
      int toxicCount = particles.where((p) => !p.isNeutralized).length;
      toxinLoadPercentage = (toxicCount / particles.length) * 100.0;
    }

    // 纤维化风险:淤积率持续居高引发
    fibrosisRiskIndex = max(0.0, toxinLoadPercentage - 20.0) * 1.5;
  }

  // 向心流体物理积分与酶解碰撞检测
  void tickUpdate(double dt, double width, double height) {
    if (width <= 0 || height <= 0) return;
    _updateBiochemicalField();

    double centerX = width / 2;
    double centerY = height / 2;
    double maxRadius = sqrt(width*width + height*height) / 2;

    // 1. 生成外源性代谢废料 (从血管汇管区向中心肝静脉流动)
    // 高应激(睡眠少)或者正常态都会产生代谢物,但基数是一样的
    double spawnRate = 2.0; 
    if (_rnd.nextDouble() < spawnRate * dt * 60) {
      // 沿圆周随机位置生成
      double spawnAngle = _rnd.nextDouble() * pi * 2;
      particles.add(ToxinParticle(
        x: centerX + cos(spawnAngle) * (maxRadius + 20),
        y: centerY + sin(spawnAngle) * (maxRadius + 20),
        angle: spawnAngle + pi, // 指向中心
        speed: 15.0 + _rnd.nextDouble() * 10.0, // 缓慢向心渗透
      ));
    }

    // 2. 积分演算粒子位移与酶促反应
    for (int i = particles.length - 1; i >= 0; i--) {
      var p = particles[i];
      p.lifetime += dt;

      // 如果未被中和,基于 CYP450 浓度进行概率性解毒
      // 酶活性越高,越容易在半途中和
      if (!p.isNeutralized) {
        double detoxProbability = (cyp450EnzymeLevel / 100.0) * 0.02; // 每帧的解毒命中率
        if (_rnd.nextDouble() < detoxProbability) {
          p.isNeutralized = true;
          p.speed *= 2.5; // 被解毒变为水溶性后,流出速度加快
        }
      }

      // 纤维化阻力模型:如果纤维化高,中心区域流速变慢(淤滞)
      double resistance = p.isNeutralized ? 1.0 : max(0.2, 1.0 - (fibrosisRiskIndex * 0.005));
      
      // 更新位移 (加入微小的布朗运动扰动)
      p.x += cos(p.angle) * p.speed * dt * resistance + (_rnd.nextDouble() - 0.5) * 2.0;
      p.y += sin(p.angle) * p.speed * dt * resistance + (_rnd.nextDouble() - 0.5) * 2.0;

      // 3. 淘汰判定:到达中央静脉(中心点极小范围内)则排入大循环并消失
      double distToCenter = sqrt(pow(p.x - centerX, 2) + pow(p.y - centerY, 2));
      if (distToCenter < 15.0) {
        particles.removeAt(i);
      }
    }

    // 粒子上限熔断,防止极端情况卡死
    if (particles.length > 500) {
      particles.removeRange(0, particles.length - 500);
    }
  }
}

// ==========================================
// 主视图控制器
// ==========================================

class HepaticHomeScreen extends StatefulWidget {
  const HepaticHomeScreen({Key? key}) : super(key: key);

  @override
  State<HepaticHomeScreen> createState() => _HepaticHomeScreenState();
}

class _HepaticHomeScreenState extends State<HepaticHomeScreen> with SingleTickerProviderStateMixin {
  late Ticker _ticker;
  Duration _lastElapsed = Duration.zero;

  // 实例化双引擎隔离架构
  final LiverEnvironment _controlEnv = LiverEnvironment(isControlGroup: true);
  final LiverEnvironment _experimentEnv = LiverEnvironment(isControlGroup: false);

  @override
  void initState() {
    super.initState();
    _ticker = createTicker((elapsed) {
      double dt = (elapsed.inMilliseconds - _lastElapsed.inMilliseconds) / 1000.0;
      if (dt > 0.1) dt = 0.016; 
      _lastElapsed = elapsed;

      if (!mounted) return;
      setState(() {
        // 全局驱动画布高频重绘,但不重建深层 Widget 树
      });
    });
    _ticker.start();
  }

  @override
  void dispose() {
    _ticker.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: const BoxDecoration(
          image: DecorationImage(
            image: AssetImage('assets/images/explore_ohos.png'),
            fit: BoxFit.cover,
            opacity: 0.05,
          ),
        ),
        child: SafeArea(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 12.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                _buildHeader(),
                const SizedBox(height: 12),
                
                // 核心防溢出区域:Expanded 吸收纵向弹性空间,LayoutBuilder 吸纳横向
                Expanded(
                  child: LayoutBuilder(
                    builder: (context, constraints) {
                      // 响应式截断降维:当宽度小于 750 时改为上下叠放,彻底杜绝 Right Overflow
                      if (constraints.maxWidth > 750) {
                        return Row(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            Expanded(child: _buildHepaticViewport('标准对照组 (稳态)', _controlEnv)),
                            const SizedBox(width: 16),
                            Expanded(child: _buildHepaticViewport('干预实验组 (剥夺)', _experimentEnv)),
                          ],
                        );
                      } else {
                        return Column(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            Expanded(child: _buildHepaticViewport('标准对照组 (稳态)', _controlEnv)),
                            const SizedBox(height: 16),
                            Expanded(child: _buildHepaticViewport('干预实验组 (剥夺)', _experimentEnv)),
                          ],
                        );
                      }
                    },
                  ),
                ),
                
                const SizedBox(height: 16),
                _buildControlPanel(),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildHeader() {
    return Row(
      children: [
        const Icon(Icons.hub, color: Color(0xFF00FFCC), size: 30),
        const SizedBox(width: 12),
        // 对长标题进行横向溢出防御
        Expanded(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: const [
              Text(
                'HEPATIC CLEARANCE ENGINE // 肝脏代谢清除率演算仪',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white, letterSpacing: 1.1),
                softWrap: true,
              ),
              Text(
                'Circadian Rhythm Disruption vs CYP450 Enzymatic Detoxification',
                style: TextStyle(fontSize: 11, color: Colors.white54),
                softWrap: true,
              ),
            ],
          ),
        ),
      ],
    );
  }

  // 肝小叶向心流场观测视窗
  Widget _buildHepaticViewport(String title, LiverEnvironment env) {
    return Container(
      decoration: BoxDecoration(
        color: const Color(0xFF161B22).withOpacity(0.8),
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: env.isControlGroup ? const Color(0xFF00FFCC).withOpacity(0.4) : const Color(0xFFE2B93B).withOpacity(0.4)),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          // 面板数据输出区:强烈依赖 Wrap 防治内部文本撑爆宽度
          Container(
            padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
            decoration: const BoxDecoration(
              color: Colors.black45,
              borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
            ),
            child: Wrap(
              spacing: 12,
              runSpacing: 8,
              children: [
                Text(
                  title, 
                  style: TextStyle(color: env.isControlGroup ? const Color(0xFF00FFCC) : const Color(0xFFE2B93B), fontWeight: FontWeight.bold, fontSize: 13)
                ),
                Text('睡眠: ${env.targetSleepDuration.toStringAsFixed(1)} h', style: const TextStyle(color: Colors.white70, fontSize: 12)),
                Text('CYP450: ${env.cyp450EnzymeLevel.toStringAsFixed(1)}%', style: TextStyle(color: env.cyp450EnzymeLevel < 50 ? Colors.redAccent : Colors.white70, fontSize: 12)),
                Text('淤积率: ${env.toxinLoadPercentage.toStringAsFixed(1)}%', style: TextStyle(color: env.toxinLoadPercentage > 40 ? Colors.redAccent : Colors.white70, fontSize: 12)),
                Text('脂化/纤维化: ${env.fibrosisRiskIndex.toStringAsFixed(1)}', style: TextStyle(color: env.fibrosisRiskIndex > 20 ? Colors.deepPurpleAccent : Colors.white70, fontSize: 12)),
              ],
            ),
          ),
          
          // 原生 Canvas 渲染区,彻底吸收所有高度,无 Widget 树膨胀
          Expanded(
            child: LayoutBuilder(
              builder: (context, constraints) {
                // 每帧都在此触发积分推演
                env.tickUpdate(0.016, constraints.maxWidth, constraints.maxHeight);
                return ClipRect( // 防治粒子越界绘制
                  child: CustomPaint(
                    painter: HepaticLobulePainter(env),
                  ),
                );
              },
            ),
          ),
        ],
      ),
    );
  }

  // 底部睡眠干预操作台
  Widget _buildControlPanel() {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
      decoration: BoxDecoration(
        color: Colors.black54,
        borderRadius: BorderRadius.circular(12),
        border: Border.all(color: Colors.white12),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const Text('CIRCADIAN RHYTHM OVERRIDE // 昼夜节律干预: 强制缩短宿主睡眠周期 (0-12 Hrs)', 
            style: TextStyle(color: Color(0xFFE2B93B), fontWeight: FontWeight.bold, fontSize: 13)),
          Row(
            children: [
              const Icon(Icons.nights_stay, color: Colors.indigoAccent),
              // 滑动条外裹 Expanded,自适应填充
              Expanded(
                child: Slider(
                  value: _experimentEnv.targetSleepDuration,
                  min: 0.0,
                  max: 12.0,
                  divisions: 24,
                  label: '${_experimentEnv.targetSleepDuration.toStringAsFixed(1)} H',
                  onChanged: (val) {
                    setState(() {
                      _experimentEnv.targetSleepDuration = val;
                    });
                  },
                ),
              ),
              const Icon(Icons.wb_sunny, color: Colors.orangeAccent),
            ],
          ),
        ],
      ),
    );
  }
}

// ==========================================
// 肝小叶生化流场高性能渲染器
// ==========================================

class HepaticLobulePainter extends CustomPainter {
  final LiverEnvironment env;

  HepaticLobulePainter(this.env);

  @override
  void paint(Canvas canvas, Size size) {
    double centerX = size.width / 2;
    double centerY = size.height / 2;

    // 1. 绘制肝小叶背景与六边形边界骨架抽象
    final Paint bgPaint = Paint()..color = const Color(0xFF1E1116).withOpacity(0.4);
    canvas.drawRect(Offset.zero & size, bgPaint);

    final Paint veinPaint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 1.0
      ..color = Colors.white10;

    // 绘制肝索发散状抽象虚线
    for (int i = 0; i < 12; i++) {
      double angle = (i * pi) / 6;
      canvas.drawLine(
        Offset(centerX, centerY),
        Offset(centerX + cos(angle) * size.width, centerY + sin(angle) * size.width),
        veinPaint
      );
    }

    // 2. 绘制微粒流场
    final Paint particlePaint = Paint();
    
    for (var p in env.particles) {
      // 未被中和的毒素呈现荧光黄绿,已被中和的水溶代谢物呈现暗蓝色
      if (p.isNeutralized) {
        particlePaint.color = const Color(0xFF42A5F5).withOpacity(0.6);
        particlePaint.maskFilter = null; // 干净的水分子
      } else {
        // 毒素滞留越久(lifetime长),荧光越亮且趋向于有害的亮黄/橙色
        double toxicIntensity = (p.lifetime / 10.0).clamp(0.0, 1.0);
        int r = (100 + 155 * toxicIntensity).toInt();
        int g = (255 - 100 * toxicIntensity).toInt();
        particlePaint.color = Color.fromARGB(220, r, g, 50);
        particlePaint.maskFilter = const MaskFilter.blur(BlurStyle.solid, 3.0); // 散发毒素光晕
      }

      // 纤维化阻力导致的大毒素结节:若纤维化高且未解毒,粒子表现为肿大
      double radius = p.isNeutralized ? 2.5 : 3.5 + (env.fibrosisRiskIndex * 0.05);
      canvas.drawCircle(Offset(p.x, p.y), radius, particlePaint);
    }

    // 3. 绘制中央静脉 (Central Vein)
    final Paint centerPaint = Paint()..color = const Color(0xFF6B1D25).withOpacity(0.8);
    canvas.drawCircle(Offset(centerX, centerY), 12.0, centerPaint);
    
    // 如果酶浓度高,中央静脉附近散发健康的生命光晕
    if (env.cyp450EnzymeLevel > 80) {
      final Paint glowPaint = Paint()
        ..color = const Color(0xFF00FFCC).withOpacity(0.15)
        ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 10.0);
      canvas.drawCircle(Offset(centerX, centerY), 20.0 + sin(DateTime.now().millisecondsSinceEpoch/200)*2, glowPaint);
    } else if (env.fibrosisRiskIndex > 30) {
      // 纤维化危机光晕:深红/紫色报警
      final Paint dangerPaint = Paint()
        ..color = Colors.deepPurpleAccent.withOpacity(0.3)
        ..maskFilter = const MaskFilter.blur(BlurStyle.normal, 15.0);
      canvas.drawCircle(Offset(centerX, centerY), 30.0, dangerPaint);
    }
  }

  // 全时重绘
  @override
  bool shouldRepaint(covariant HepaticLobulePainter oldDelegate) => true;
}
相关推荐
Hello__77771 小时前
开源鸿蒙 Flutter 实战|自定义开关组件全流程实现
flutter·开源·harmonyos
candyTong6 小时前
一觉醒来,大模型就帮我排查完页面性能问题
前端·javascript·架构
空中海9 小时前
Kubernetes 入门基础与核心架构
贪心算法·架构·kubernetes
米高梅狮子10 小时前
08.CronJob和Service
云原生·容器·架构·kubernetes·自动化
maaath11 小时前
【maaath】Flutter for OpenHarmony 跨平台工程集成密码加密能力
flutter·华为·harmonyos
yeziyfx11 小时前
Flutter 纯色矩形
flutter
liulian091611 小时前
Flutter for OpenHarmony 混合开发实践:用户反馈功能的实现与适配
flutter·华为·学习方法·harmonyos
SamDeepThinking12 小时前
中小团队需要一个资源微服务
后端·微服务·架构
两万五千个小时12 小时前
为什么你的 Agent 读了文件,却好像什么都没读到?
人工智能·程序员·架构
非优秀程序员12 小时前
智能体的构成--深入探讨Anthropic、OpenAI、Perplexity和LangChain究竟在构建什么。
人工智能·架构·开源