Skip to content

Cropping and zooming doesn't work on Web #11

@stalko

Description

@stalko
  1. The image looks darkened then it has;
  2. Can't zoom image(trying with the mouse wheel);
  3. Got the error: "Unsupported operation: toImage is not supported on the Web" after pressing "Crop" button.

Tested on: Chrome(Version 80.0.3987.163 (Official Build) (64-bit)), Mozilla Firefox(75.0 (64-bit))
deps:

crop: ^0.3.1+1
image_picker_web: ^1.0.6
image_picker: ^0.6.5

Source code:

import 'package:flutter/material.dart';
import 'package:image_picker_web/image_picker_web.dart';
import './image.dart';
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'dart:ui';
import './centered_slider_track_shape.dart';
import 'package:flutter/material.dart';
import 'package:crop/crop.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:path/path.dart' as Path;
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'dart:io';
import 'dart:typed_data';
import 'dart:math';


class UserPage extends StatefulWidget {
  @override
  _UserPageState createState() => _UserPageState();
}

class _UserPageState extends State<UserPage> {
  Image pickedImage;

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

  Future getImageMobile() async {
    var image = await ImagePicker.pickImage(source: ImageSource.gallery);

    setState(() {
      pickedImage = Image.file(
        image,
        fit: BoxFit.cover,
      );
    });
  }

  getImageWeb() async {
    Image fromPicker =
        await ImagePickerWeb.getImage(outputType: ImageType.widget);
    if (fromPicker != null) {
      setState(() {
        pickedImage = fromPicker;
      });
    }
  }

  pickImage() async {
    if (kIsWeb) {
      await getImageWeb();
    } else {
      await getImageMobile();
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Image Picker Web Example'),
        ),
        body: Center(
            child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[
                  AnimatedSwitcher(
                    duration: Duration(milliseconds: 300),
                    switchInCurve: Curves.easeIn,
                    child: SizedBox(
                          width: 200,
                          child: pickedImage,
                        ) ??
                        Container(),
                  ),
                  SizedBox(
                    width: 15,
                  ),
                ],
              ),
              ButtonBar(alignment: MainAxisAlignment.center, children: <Widget>[
                RaisedButton(
                  onPressed: () => pickImage(),
                  child: Text('Select Image'),
                ),
                RaisedButton(
                  onPressed: () {
                    Navigator.of(context).push(
                      MaterialPageRoute<void>(
                          builder: (_) => ImagePage(
                                image: pickedImage,
                              )),
                    );
                  },
                  child: Text('Crop'),
                ),
              ]),
            ])),
      ),
    );
  }
}

class ImagePage extends StatefulWidget {
  ImagePage({Key key, @required this.image}) : super(key: key);

  final Image image;
  @override
  _ImagePageState createState() => _ImagePageState(image);
}

class _ImagePageState extends State<ImagePage> {
  _ImagePageState(this.image);
  final Image image;
  String _uploadedFileURL;
  final controller = CropController(aspectRatio: 1000 / 667.0);
  double _rotation = 0;

  @override
  void initState(){
    super.initState();
    controller.aspectRatio = 1;
    setState(() {

    });
  }

  void _cropImage() async {
    final pixelRatio = MediaQuery.of(context).devicePixelRatio;
    final cropped = await controller.crop(pixelRatio: pixelRatio);

    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => Scaffold(
          appBar: AppBar(
            title: Text('Crop Result'),
            centerTitle: true,
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.file_upload),
                tooltip: 'Upload',
                onPressed: () async {
                  // getting a directory path for saving
                  var dir = await getApplicationDocumentsDirectory();
                  final ByteData data = await cropped.toByteData(format: ImageByteFormat.png);
                  final buffer = data.buffer;

                  final String fileName = Random().nextInt(10000).toString() +'.png';
                  print(fileName);

                  final File newImage = await new File('${dir.path}/$fileName').writeAsBytes(
                      buffer.asUint8List(data.offsetInBytes, data.lengthInBytes));
                  await uploadFile(newImage);
                },
              ),
            ],
          ),
          body: Center(
            child: RawImage(
              image: cropped,
            ),
          ),
        ),
        fullscreenDialog: true,
      ),
    );
  }

  Future uploadFile(File img) async {
  }

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    return Scaffold(
      appBar: AppBar(
        title: Text('Crop Demo'),
        centerTitle: true,
        actions: <Widget>[
          IconButton(
            onPressed: _cropImage,
            tooltip: 'Crop',
            icon: Icon(Icons.crop),
          )
        ],
      ),
      body: Column(
        children: <Widget>[
          Expanded(
            child: Container(
              color: Colors.black,
              padding: EdgeInsets.all(8),
              child: Crop(
                controller: controller,
                child: image,
                helper: Container(
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.white, width: 2),
                  ),
                ),
              ),
            ),
          ),
          Row(
            children: <Widget>[
              IconButton(
                icon: Icon(Icons.undo),
                tooltip: 'Undo',
                onPressed: () {
                  controller.rotation = 0;
                  controller.scale = 1;
                  controller.offset = Offset.zero;
                  setState(() {
                    _rotation = 0;
                  });
                },
              ),
              Expanded(
                child: SliderTheme(
                  data: theme.sliderTheme.copyWith(
                    trackShape: CenteredRectangularSliderTrackShape(),
                  ),
                  child: Slider(
                    divisions: 361,
                    value: _rotation,
                    min: -180,
                    max: 180,
                    label: '$_rotation°',
                    onChanged: (n) {
                      setState(() {
                        _rotation = n.roundToDouble();
                        controller.rotation = _rotation;
                      });
                    },
                  ),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions