首页 > 解决方案 > 如何从元素的中心旋转堆栈?

问题描述

我有以下代码:

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:math' as math;

void main() {
  debugPaintSizeEnabled = true;
  return runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.grey,
        body: SafeArea(
          child: ImageRotate(),
        ),
      ),
    );
  }
}

class ImageRotate extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Transform.rotate(
      angle: (math.pi / 180) * 45,
      child: Stack(
        children: [
          Positioned(
            top: 100,
            left: 50,
            child: Image.network(
              "https://via.placeholder.com/300x200",
              height: 200,
              width: 300,
            ),
          ),
        ],
      ),
    );
  }
}

现在我期望的是像这样从图像中心执行旋转,

在此处输入图像描述

相反,它像这样旋转,

在此处输入图像描述

我还尝试研究变换原点。但是我自己无法弄清楚原点的偏移量。任何帮助,将不胜感激。

标签: flutterdarttransform

解决方案


您在尝试获取图像的位置时处于正确的方向(您还需要它的大小才能根据center的功能旋转)。

为了做到这一点,Flutter 中的经典方法是使用键。这是您使用此方法的问题:

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:math' as math;

void main() {
  debugPaintSizeEnabled = true;
  return runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          backgroundColor: Colors.grey,
          body: ImageRotate(),
        ),
      ),
    );
  }
}

class ImageRotate extends StatefulWidget {
  @override
  _ImageRotateState createState() => _ImageRotateState();
}

class _ImageRotateState extends State<ImageRotate> {
  final GlobalKey imageKey = GlobalKey();
  Size imageSize = Size(0, 0);
  Offset imagePos = Offset.zero;

  @override
  void initState() {
    WidgetsBinding.instance.addPostFrameCallback((_) {
      imageSize = (imageKey.currentContext.findRenderObject() as RenderBox).size;
      imagePos =
          (imageKey.currentContext.findRenderObject() as RenderBox).localToGlobal(Offset.zero);
      setState(() {});
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    print(imagePos);
    print(imageSize);
    return Transform.rotate(
      angle: imagePos == Offset.zero ? 0 : (math.pi / 180) * 45,
      origin:
          -Offset(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) / 2 +
              (imagePos + Offset(imageSize.width / 2, imageSize.height / 2)),
      child: Stack(
        children: [
          Positioned(
            top: 200,
            left: 300,
            child: Image.network(
              "https://via.placeholder.com/300x200",
              key: imageKey,
              height: 100,
              width: 100,
            ),
          ),
        ],
      ),
    );
  }
}

微积分解释:原点是中心的偏移量。这就是为什么您必须将其移动-Offset(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height)/2. 它将中心放在屏幕的左上角。然后你移动到图像的中心,所以在这里你使用从 GlobalKey 获得的尺寸:(imagePos + Offset(imageSize.width / 2, imageSize.height / 2))

imagePos == Offset.zero ? 0 : (math.pi / 180) * 45解释:你必须先得到图像在没有旋转时的位置,所以你首先将旋转设置为零,然后计算imagePos,然后你可以应用你想要的旋转角度。


推荐阅读