You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中点击SVG圆形路径跳转至对应页面的实现方法

实现SVG圆形点击跳转对应页面的方案

1. 准备依赖与资源

  • 在pubspec.yaml中添加flutter_svg依赖(用于解析和渲染SVG):
    dependencies:
      flutter:
        sdk: flutter
      flutter_svg: ^2.0.9 # 建议使用最新稳定版本
    
  • 将你的SVG文件放入项目assets/svg/目录,同时在pubspec.yaml配置资源路径:
    assets:
      - assets/svg/your_svg_file.svg
    

2. 核心实现代码

通过解析SVG路径、监听点击位置匹配路径,实现点击圆形跳转对应页面:

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class SvgCircleNavigator extends StatefulWidget {
  const SvgCircleNavigator({super.key});

  @override
  State<SvgCircleNavigator> createState() => _SvgCircleNavigatorState();
}

class _SvgCircleNavigatorState extends State<SvgCircleNavigator> {
  final List<Map<String, dynamic>> _circleData = [];

  @override
  void initState() {
    super.initState();
    _parseSvgCircles();
  }

  // 解析SVG中的所有圆形路径
  Future<void> _parseSvgCircles() async {
    final parser = SvgParser();
    final svgRoot = await parser.parseAsset('assets/svg/your_svg_file.svg');

    for (final element in svgRoot.children) {
      Path? circlePath;
      // 处理<circle>标签
      if (element is SvgCircle) {
        circlePath = Path()
          ..addOval(Rect.fromCircle(
            center: Offset(element.cx, element.cy),
            radius: element.r,
          ));
      }
      // 处理用<path>绘制的圆形
      else if (element is SvgPath) {
        circlePath = element.path;
      }

      if (circlePath != null) {
        _circleData.add({
          'path': circlePath,
          'page': _getTargetPage(_circleData.length),
        });
      }
    }
  }

  // 根据索引返回对应页面
  Widget _getTargetPage(int index) {
    switch (index) {
      case 0:
        return const Page1();
      case 1:
        return const Page2();
      case 2:
        return const Page3();
      case 3:
        return const Page4();
      case 4:
        return const Page5();
      default:
        return const SizedBox.shrink();
    }
  }

  // 处理点击事件,匹配路径并跳转
  void _onTap(TapUpDetails details) {
    final tapPos = details.localPosition;
    for (final item in _circleData) {
      final path = item['path'] as Path;
      if (path.contains(tapPos)) {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (_) => item['page'] as Widget),
        );
        break;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _parseSvgCircles(),
      builder: (ctx, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          return GestureDetector(
            onTapUp: _onTap,
            child: SvgPicture.asset('assets/svg/your_svg_file.svg'),
          );
        }
        return const Center(child: CircularProgressIndicator());
      },
    );
  }
}

// 替换成你自己的页面类
class Page1 extends StatelessWidget {
  const Page1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('页面1')));
  }
}

class Page2 extends StatelessWidget {
  const Page2({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('页面2')));
  }
}

class Page3 extends StatelessWidget {
  const Page3({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('页面3')));
  }
}

class Page4 extends StatelessWidget {
  const Page4({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('页面4')));
  }
}

class Page5 extends StatelessWidget {
  const Page5({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(appBar: AppBar(title: const Text('页面5')));
  }
}

3. 关键注意点

  • 确保SVG中每个圆形路径独立,避免重叠(重叠区域会触发第一个匹配的路径跳转)
  • 若使用命名路由,可将_getTargetPage改为返回路由名称,替换跳转逻辑为Navigator.pushNamed(context, routeName)
  • 若SVG存在坐标系偏移,可调整tapPos的计算(比如加上偏移量)

内容的提问来源于stack exchange,提问作者user17647683

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 13:10:28