canvas_map 0.0.2 copy "canvas_map: ^0.0.2" to clipboard
canvas_map: ^0.0.2 copied to clipboard

High performance 2d map for flutter that render with canvas, provide smooth scrolling and zooming with pinch/double tap support.

example/lib/main.dart

import 'dart:ui';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:canvas_map/canvas_map.dart';
import 'package:flutter/material.dart' hide Image;
import 'package:universal_platform/universal_platform.dart';

import 'api.dart';

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

class ScrollBehavior extends MaterialScrollBehavior {
  const ScrollBehavior();

  @override
  Set<PointerDeviceKind> get dragDevices => PointerDeviceKind.values.toSet();
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      scrollBehavior: const ScrollBehavior(),
      theme: ThemeData(
        useMaterial3: true,
        fontFamily: UniversalPlatform.isWindows ? 'Microsoft YaHei' : null,
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        brightness: Brightness.dark,
        fontFamily: UniversalPlatform.isWindows ? 'Microsoft YaHei' : null,
      ),
      home: const Home(),
    );
  }
}

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

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  late final CanvasMapController controller;
  final icons = <String, dynamic>{};
  final images = <String, Image>{};
  var markers = <String, List>{};

  @override
  void initState() {
    super.initState();
    api.fetchIcons().then((icons) async {
      this.icons.addAll(icons);
      markers = await api.fetchMarkers(
        areaIdList: [6, 17, 2, 3, 12, 13, 14, 19, 21, 22, 23, 28],
        typeIdList: [5],
      );
      setState(() {});
    });
  }

  void onTap(TapDetails details) {
    final data = details.data;
    if (data is MarkerItem) {
      final marker = data.data;
      showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: Text(marker['markerTitle']),
            content: SingleChildScrollView(
              child: Column(mainAxisSize: MainAxisSize.min, children: [
                if (marker['content']?.isNotEmpty ?? false)
                  Container(
                    alignment: Alignment.centerLeft,
                    padding: const EdgeInsets.only(bottom: 16),
                    child: Text(marker['content'].replaceAll('\\n', '\n')),
                  ),
                if (marker['picture']?.isNotEmpty ?? false)
                  CachedNetworkImage(
                    imageUrl: marker['picture'],
                    fit: BoxFit.fitWidth,
                  ),
              ]),
            ),
          );
        },
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: CanvasMap(
        size: const Size(18432, 18432),
        origin: const Offset(3568 + 6144, 6969 + 2048),
        maxZoom: 1,
        onTap: onTap,
        layers: [
          TileLayer(
            getImageProvider: (x, y, z) => CachedNetworkImageProvider(
              'https://assets.yuanshen.site/tiles_twt411/$z/${x}_$y.png',
            ),
            minZoom: 10,
            maxZoom: 13,
            offset: const Offset(-6144, -2048),
          ),
          ...markers.keys.map((icon) {
            final items = markers[icon] ?? [];
            return AreaItemLayer(icon: icons[icon]['url'], items: items);
          }),
        ],
      ),
    );
  }
}

class AreaItemLayer extends StatefulWidget {
  final String icon;
  final List items;

  const AreaItemLayer({super.key, required this.icon, this.items = const []});

  @override
  State<AreaItemLayer> createState() => _AreaItemLayerState();
}

class _AreaItemLayerState extends State<AreaItemLayer> {
  Image? image;

  @override
  void initState() {
    super.initState();
    queue.run(() async {
      final image = await resolveImage(CachedNetworkImageProvider(widget.icon));
      setState(() {
        this.image = image;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    if (image == null) return const SizedBox();

    return MarkerLayer(
      items: [
        ...widget.items.map((i) => MarkerItem(Offset(i['x'], i['y']), i))
      ],
      child: Padding(
        padding: const EdgeInsets.all(2),
        child: Container(
          decoration: const BoxDecoration(
            border: Border.fromBorderSide(
              BorderSide(color: Colors.white),
            ),
            borderRadius: BorderRadius.all(Radius.circular(20)),
            boxShadow: [
              BoxShadow(blurRadius: 2),
              BoxShadow(blurRadius: 2, blurStyle: BlurStyle.inner),
            ],
          ),
          child: RawImage(image: image, width: 20, height: 20),
        ),
      ),
    );
  }
}

class TaskQueue {
  final tasks = <Future<void> Function()>[];
  var running = false;

  void run(Future<void> Function() task) async {
    tasks.add(task);
    if (running) return;

    running = true;
    while (tasks.isNotEmpty) {
      await tasks.removeLast()();
    }
    running = false;
  }
}

final queue = TaskQueue();
0
likes
150
pub points
0%
popularity

Publisher

unverified uploader

High performance 2d map for flutter that render with canvas, provide smooth scrolling and zooming with pinch/double tap support.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on canvas_map