Implementação da Função de Rotação em Editor de Imagens Flutter

Conceitos Fundamentais da Rotação

A operação de rotação em um editor de imagens envolve girar a imagem ao redor do seu ponto central. Para simplificar a implementação e garantir performance, a rotação é realizada em incrementos de 90 graus. Esta abordagem é suficiente para converter uma imagem de paisagem para retrato ou corrigir sua orientação, e é computacionalmente mais eficiente do que suportar ângulos arbitrários.

Gerenciamento de Estado com Mixin

O estado da rotação é controlado por um valor inteiro que indica quantos quartos de volta (90°) a imagem sofreu. Um mixin é utilizado para encapsular essa lógica de estado e os métodos associados.

mixin ControleRotacaoMixin<T extends StatefulWidget> on State<T> {
  int _quantidadeGiros = 0;

  void aplicarRotacao() {
    setState(() {
      _quantidadeGiros++;
    });
  }

  void zerarRotacao() {
    setState(() {
      _quantidadeGiros = 0;
    });
  }
}

O campo _quantidadeGiros é incrementado a cada rotação. O componente RotatedBox da Flutter automaticamente aplica a operação módulo 4 ao valor fornecido, portanto, um valor de 4 equivale a 0 (sem rotação), evitando overflow.

Componente RotatedBox para Rotação

O widget RotatedBox é projetado para rotações em múltiplos de 90 graus. Sua principal vantagem é que ele recalcula o layout após a rotação. Por exemplo, um container de 300x200 pixels se tornará 200x300 pixels após uma rotação de 90 graus. Isso é crucial para o editor, pois garante que todas as camadas (imagem, camada de desenho e texto) sejam tratadas como uma unidade no layout.

RotatedBox(
  quarterTurns: _quantidadeGiros,
  child: Stack(
    alignment: Alignment.center,
    children: [
      ImagemFundo(),
      CanvasDesenho(),
      CanvasTexto(),
    ],
  ),
)

Envolver o Stack inteiro garante a coesão das camadas. Se apenas a imagem fosse rotacionada, as anotações do usuário perderiam o posicionamento relativo.

Comparação: RotatedBox vs Transform.rotate

O Transform.rotate permite ângulos arbitários, mas não interfere no layout. Isso pode causar conteúdo transbordando do container pai. Para um editor de imagens com camadas, o RotatedBox é preferível pois seu comportamento de layout é previsível e o desempenho é superior, pois evita cálculos de matriz complexos para transformações livres.

Adicionando Animação de Rotação

Para uma rotação suave, é necessário substituir o RotatedBox por um Transform animado. Um AnimationController controla a transição.

late final AnimationController _controladorAnimacao;
late Animation<double> _animacaoAngulo;
double _alvoAngulo = 0.0;

@override
void initState() {
  super.initState();
  _controladorAnimacao = AnimationController(
    duration: const Duration(milliseconds: 350),
    vsync: this,
  );
}

void iniciarRotacaoAnimada() {
  _alvoAngulo += math.pi / 2;
  _animacaoAngulo = Tween<double>(
    begin: _alvoAngulo - math.pi / 2,
    end: _alvoAngulo,
  ).animate(CurvedAnimation(
    parent: _controladorAnimacao,
    curve: Curves.easeInOutCubic,
  ));
  _controladorAnimacao.forward(from: 0);
}

@override
Widget build(BuildContext context) {
  return AnimatedBuilder(
    animation: _animacaoAngulo,
    builder: (_, child) {
      return Transform.rotate(
        angle: _animacaoAngulo.value,
        child: child,
      );
    },
    child: ConteudoEditor(),
  );
}

Ao salvar a imagem, o RepaintBoundary deve envolver o widget já rotacionado para capturar o resultado correto.

Adaptação para OpenHarmony: Obtendo Orientação do Dispositivo

Embora a rotação em si seja puramente Flutter, obter a orientação física do dispositivo requer comunicação com a plataforma nativa.

Definição no Dart (via MethodChannel):

import 'package:flutter/services.dart';

const _plataforma = MethodChannel('canal_editor_imagens');

Future<int> buscarOrientacaoAparelho() async {
  final resultado = await _plataforma.invokeMethod('orientacaoAtual');
  return resultado as int;
}

Implementação no lado OpenHarmony (ArkTS):

import { MethodChannel, MethodCall, MethodResult } from '@ohos/flutter_ohos';
import { window } from '@kit.ArkUI';

class ManipuladorPlugin {
  private canal: MethodChannel | null = null;

  configurarCanal(binding: any) {
    this.canal = new MethodChannel(binding.getBinaryMessenger(), 'canal_editor_imagens');
    this.canal.setMethodCallHandler(this.tratarChamada.bind(this));
  }

  async tratarChamada(chamada: MethodCall, resultado: MethodResult): Promise<void> {
    if (chamada.method === 'orientacaoAtual') {
      const janela = await window.getLastWindow(getContext(this));
      const propriedades = janela.getWindowProperties();
      const orientacao = propriedades.displayOrientation;
      resultado.success(orientacao);
    } else {
      resultado.notImplemented();
    }
  }
}

A orientação retornada pode ser usada para ajustar automaticamente a rotação inicial da imagem no editor.

Considerações de Implementação

  • Garantir que o RotatedBox sempre envolva todas as camadas interativas do editor.
  • Utilizar Transform.rotate para rotações suaves, reservando RotatedBox para rotações discretas instantâneas.
  • Para grandes volumes de dados, isolar a região de desenho com RepaintBoundary pode melhorar o desempenho das animações.

Tags: Flutter Dart rotação editor-imagens OpenHarmony

Publicado em 7-8 20:26