首页 > 解决方案 > Flutter:如何在平面内对角旋转矩形以进行绘画

问题描述

我有一个单词搜索应用程序,我在其中使用 Rect 在网格上绘画。

我有一个手势检测器,它允许我通过全局键识别已选择的网格字段,并使用 onPanStart、onPanUpdate 和 onPanEnd 我可以看到所有已标记的单词。

一切正常,但我不知道如何添加对角线标记。

我目前得到这个结果:

我想实现这个对角线绘画

打标目前的演示,ps:Gesture Detector 还是需要改进才能画,对角线

我尝试添加 RotationTransition,但行为看起来不太好,如下所示。

RotationTransition(
    alignment: Alignment.centerLeft,
    turns: new AlwaysStoppedAnimation(45 / 360),
    child: Container(
      padding: const EdgeInsets.all(2.0),
      child: DecoratedBox(
        decoration: BoxDecoration(
          color: colorSelection!.withOpacity(0.4),
          border: Border.all(
            color: colorSelection!.withOpacity(0.1),
            //width: width,
          ),
          borderRadius: BorderRadius.circular(radius),
        ),
      ),
    ),
  )

重要部分概述

Widget build(BuildContext context) {
return Stack(
  children: [
    GridView.count(
      physics: NeverScrollableScrollPhysics(),
      childAspectRatio: letterWidth / letterHeight,
      crossAxisCount: nCols,
      children: puzzle.asMap().map(
            (index, letter) => MapEntry(
              index,
              BoardLetter(
                letter,
                isSelected: selection.contains(index),
                isHit: hitIndexes.contains(index),
                key: uniqueLetters[index]['key'],
              ),
            ),
          )
          .values
          .toList(),
    ),
    ...markers,
    Positioned(
      width: widget.width,
      height: widget.height,
      child: RotationTransition(
        turns: new AlwaysStoppedAnimation(360 / 360),
        child: GestureDetector(
          behavior: HitTestBehavior.opaque,
          onPanStart: onPanStart,
          onPanEnd: onPanEnd,
          onPanUpdate: onPanUpdate,
        ),
      ),
    ),

  ],
);

选择检查单词和标记。最后绘制区域。

void onPanUpdate(DragUpdateDetails details) {
final currentIndex = computeLetterIndex(details.localPosition);

if(currentIndex >= 0 && currentIndex <= 99){

  final key = uniqueLetters[currentIndex]['key'];
  final RenderBox renderBox = key.currentContext.findRenderObject();

  print("render box size ${renderBox.localToGlobal(Offset.zero, ancestor: context.findRenderObject())}");
  markerRect = renderBox.localToGlobal(Offset.zero, ancestor: context.findRenderObject()) & renderBox.size;

  List<int> _selection = [];
  if (checkSameRow(startIndex, currentIndex)) {

    if(direction == "horizontal"){
      markers.last = adjustedMarker(markers.last, markerRect!);
      _selection = genSelection(startIndex, currentIndex, 1);
    }

  } else if (checkSameCol(startIndex, currentIndex)) {
    //print("direction $direction");
    if(direction == "vertical"){

      markers.last = adjustedMarker(markers.last, markerRect!);
      _selection = genSelection(startIndex, currentIndex, nCols);
    }

  } else if (checkSameMainDiagonal(startIndex, currentIndex)) {
    markers.last = adjustedMarker(markers.last, markerRect!);
    _selection = genSelection(startIndex, currentIndex, nCols + 1);

  } else if (checkSameCounterDiagonal(startIndex, currentIndex)) {
    markers.last = adjustedMarker(markers.last, markerRect!);
    _selection = genSelection(startIndex, currentIndex, nCols - 1);
  }

  setState(() {
    selection = _selection;
  });


}

}

检查是否找到了一个单词,否则它会删除油漆(markers.last)

void onPanEnd(DragEndDetails details) {
final word = selection
    .map((index) => puzzle[index])
    .fold("", (dynamic value, letter) => value + letter);

// Check if this is a valid word
var reversedWord = word.split('').reversed.join();
var wordIndex = widget.words
    .indexWhere((gameWord) => gameWord == word || gameWord == reversedWord);


if (wordIndex != -1) {
  print("word $word/$reversedWord was hit");
  widget.onHitWord(word, wordIndex);

  this.setState(() {
    direction = "";
    colorNumber = colorNumber + 1 ;
    hitIndexes = List.from(hitIndexes)..addAll(selection);
  });
}else{
  setState(() {
    direction = "";
    markers.removeLast();
    selection = [];
  });
}

}

初始位置被捕获并标记。

void onPanStart(DragStartDetails details) {
startIndex = computeLetterIndex(details.localPosition);
final currentIndex = computeLetterIndex(details.localPosition);
final key = uniqueLetters[currentIndex]['key'];
final renderBox = key.currentContext.findRenderObject();

print(uniqueLetters[currentIndex]['letter']);
setState(() {
  markerRect = renderBox.localToGlobal(Offset.zero, ancestor: context.findRenderObject()) & renderBox.size;
  addMarker(markerRect, currentIndex);
});

}

书签已添加

void addMarker(Rect rect, int startIndex) {
markers.add(
    WordMarker(
  rect: rect,
  startIndex: startIndex,
  colorSelection: getColor(context),
  color: getColor(context),
));

}

标记用 rect 调整

WordMarker adjustedMarker(WordMarker originalMarker, Rect endRect) {
originalMarker.colorSelection = getColor(context);
originalMarker.copyWith(rect: originalMarker.rect!.inflate(20.0));

return originalMarker.copyWith(rect: originalMarker.rect!.expandToInclude(endRect));

}

标签: flutterdartflutter-layoutflutter-animation

解决方案


推荐阅读