Flutter交互式图片处理插件interactive_image的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter交互式图片处理插件interactive_image的使用

交互式图片插件 interactive_image

interactive_image 是一个在 Flutter 中创建的交互式图片处理插件。源代码为 100% Dart,并且所有文件都位于 /lib 文件夹中。

支持项目

GitHub 关注者 开源软件

安装

dependencies: 部分的 pubspec.yaml 文件中,添加以下行:

dependencies:
  interactive_image: <latest_version>

然后在你的项目中导入:

import 'package:interactive_image/interactive_image.dart';

基本用法

以下是一个简单的示例,展示如何使用 InteractiveImage 插件:

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

class HomeScreen extends StatefulWidget {
  [@override](/user/override)
  _HomeScreenState createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  bool status = false;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Interactive Image Example'),
      ),
      body: InteractiveImage(
        // 可以通过 URL 加载配置文件
        url: 'interactive_image.json',
      ),
    );
  }
}

完整示例

下面是一个更完整的示例,展示如何使用 interactive_image 插件来实现图片的交互处理。此示例包括从网络加载配置文件、处理点击事件以及保存配置文件的功能。

主页面

import 'dart:io';

import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:interactive_image/interactive_image.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';

InteractiveImageController interactiveImageController = InteractiveImageController();

String _itemid = '';
String globalurl =
    'https://s3-eu-west-1.amazonaws.com/mkspresprod.suggesto.eu/mdgcaritro/mappe/mdg/configuration.json';

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Interactive Image Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomeScreen(),
    );
  }
}

class ConfigStorage {
  Future<String> get _localPath async {
    final directory = await getDownloadsDirectory();
    return directory?.path ?? '.';
  }

  Future<File> get _localFile async {
    final path = await _localPath;
    String? selectedDirectory = await FilePicker.platform.getDirectoryPath();
    if (selectedDirectory == null) {
      return File('$path/interactiveimageconfig.json');
    } else {
      return File('$selectedDirectory/interactiveimageconfig.json');
    }
  }

  Future<String> readConfig() async {
    try {
      final file = await _localFile;
      final content = await file.readAsString();
      return content;
    } catch (e) {
      return '';
    }
  }

  Future<File> writeConfig(String config) async {
    final file = await _localFile;
    return file.writeAsString(config);
  }
}

class HomeScreen extends StatefulWidget {
  final ConfigStorage storage = ConfigStorage();

  HomeScreen({super.key});

  [@override](/user/override)
  HomeScreenState createState() => HomeScreenState();
}

class HomeScreenState extends State<HomeScreen> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Interactive Image Edit'),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.arrow_forward),
            tooltip: 'Go to test page',
            onPressed: () {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) {
                  return TestScreen(itemid: _itemid);
                }),
              );
            },
          ),
        ],
      ),
      body: InteractiveImageMap(
        clearcache: false,
        interactive: true,
        toolbarPosition: ToolbarPosition.right,
        iicontroller: interactiveImageController,
        openstreetmap: false,
        itemtitle: 'Name of the poi',
        mypositionlabel: 'Posizione',
        url: globalurl,
        onGenerateConfig: (value) async {
          widget.storage.writeConfig(value);
        },
        onAddNewItem: (value) {
          print('onAddNewItem: $value');
        },
        onItemClick: (value) async {
          print('onItemClick: $value');

          _itemid = value.id;
          interactiveImageController.msitem.id = value.id;
          interactiveImageController.msitem.number = value.number;
          interactiveImageController.msitem.title = value.title;
          interactiveImageController.msitem.subtitle = value.subtitle;
          interactiveImageController.msitem.description = value.description;
          interactiveImageController.msitem.type = value.type;
          interactiveImageController.msitem.latLng = value.latLng;
          interactiveImageController.msitem.width = value.width;
          interactiveImageController.msitem.height = value.height;
          interactiveImageController.msitem.fillcolor = value.fillcolor;
          interactiveImageController.msitem.bordercolor = value.bordercolor;
          interactiveImageController.msitem.iconName = value.iconName;

          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => FormScreen()),
          );
        },
      ),
    );
  }
}

测试页面

class TestScreen extends StatefulWidget {
  final String itemid;

  TestScreen({Key? key, required this.itemid}) : super(key: key);

  [@override](/user/override)
  TestScreenState createState() => TestScreenState();
}

class TestScreenState extends State<TestScreen> {
  final InteractiveImageController interactiveImageController = InteractiveImageController();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Test'),
        actions: [
          Theme(
            data: Theme.of(context).copyWith(
              dividerColor: Colors.white,
              iconTheme: const IconThemeData(color: Colors.white),
              textTheme: const TextTheme().apply(bodyColor: Colors.white),
            ),
            child: PopupMenuButton<int>(
                color: Colors.orange,
                onSelected: (item) {
                  if (item < 99) {
                    interactiveImageController.setLocationId('00$item');
                  } else {
                    interactiveImageController.setLocationId('$item');
                  }
                },
                itemBuilder: (context) {
                  return List.generate(interactiveImageController.locationList.length, (index) {
                    return PopupMenuItem(
                      value: int.parse(interactiveImageController.locationList[index]),
                      child: Text('Item: ${interactiveImageController.locationList[index]}'),
                    );
                  });
                }),
          ),
        ],
      ),
      body: InteractiveImageMap(
        clearcache: false,
        interactive: false,
        iicontroller: interactiveImageController,
        itemid: widget.itemid,
        url: globalurl,
      ),
    );
  }
}

表单页面

class FormScreen extends StatelessWidget {
  final _formKey = GlobalKey<FormBuilderState>();

  FormScreen({super.key});

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Edit'),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.save),
            tooltip: 'Save',
            onPressed: () {
              Navigator.pop(context);
              interactiveImageController.setChangeId('test');
            },
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: <Widget>[
            FormBuilder(
              key: _formKey,
              child: Column(
                children: <Widget>[
                  FormBuilderTextField(
                    name: 'id',
                    initialValue: interactiveImageController.msitem.id,
                    decoration: const InputDecoration(
                      labelText: 'id',
                    ),
                    onChanged: (value) => {
                      interactiveImageController.msitem.id = value!,
                    },
                  ),
                  FormBuilderTextField(
                    name: 'number',
                    initialValue: interactiveImageController.msitem.number,
                    decoration: const InputDecoration(
                      labelText: 'number',
                    ),
                    onChanged: (value) => {
                      interactiveImageController.msitem.number = value!,
                    },
                  ),
                  FormBuilderTextField(
                    name: 'title',
                    initialValue: interactiveImageController.msitem.title,
                    decoration: const InputDecoration(
                      labelText: 'title',
                    ),
                    onChanged: (value) => {
                      interactiveImageController.msitem.title = value!,
                    },
                  ),
                  FormBuilderTextField(
                    name: 'subtitle',
                    initialValue: interactiveImageController.msitem.subtitle,
                    decoration: const InputDecoration(
                      labelText: 'subtitle',
                    ),
                    onChanged: (value) => {
                      interactiveImageController.msitem.subtitle = value!,
                    },
                  ),
                  FormBuilderTextField(
                    name: 'description',
                    initialValue: interactiveImageController.msitem.description,
                    decoration: const InputDecoration(
                      labelText: 'description',
                    ),
                    onChanged: (value) => {
                      interactiveImageController.msitem.description = value!,
                    },
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

更多关于Flutter交互式图片处理插件interactive_image的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter交互式图片处理插件interactive_image的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何使用Flutter中的interactive_image插件进行交互式图片处理的示例代码。这个插件允许用户对图片进行缩放、拖动等操作。请注意,在实际使用中,你需要先确保在pubspec.yaml文件中添加了对interactive_image插件的依赖。

首先,确保你的pubspec.yaml文件中包含以下依赖:

dependencies:
  flutter:
    sdk: flutter
  interactive_image: ^x.y.z  # 替换为最新版本号

然后,运行flutter pub get来安装依赖。

接下来是一个简单的示例代码,展示如何使用interactive_image插件:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Interactive Image Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final String imageUrl = 'https://example.com/your-image.jpg'; // 替换为你的图片URL

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Interactive Image Demo'),
      ),
      body: Center(
        child: InteractiveViewer(
          boundaryMargin: EdgeInsets.all(20.0),
          minScale: 0.5,
          maxScale: 3.0,
          child: Image.network(
            imageUrl,
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 导入必要的包:我们导入了flutter/material.dartinteractive_image/interactive_image.dart
  2. 定义应用入口MyApp是一个无状态小部件,它设置了应用的主题并定义了主页面MyHomePage
  3. 创建主页面MyHomePage是一个有状态小部件,它包含一个Scaffold,其中包含一个应用栏和一个居中的InteractiveViewer
  4. 使用InteractiveViewerInteractiveViewer是一个允许用户对子小部件进行缩放和拖动的小部件。我们设置了边界边距(boundaryMargin),最小缩放比例(minScale)和最大缩放比例(maxScale)。子小部件是一个网络图片(Image.network),你可以替换URL为你的图片地址。

这个示例展示了如何使用interactive_image插件实现基本的图片缩放和拖动功能。你可以根据需要进一步自定义和扩展这个示例,比如添加手势识别器来处理特定的用户交互,或者结合其他Flutter插件来实现更复杂的图片处理功能。

回到顶部