簡體   English   中英

將坐標空間轉換為 Alignment 的更好方法

[英]A better way to convert a coordinate space to Alignment

我正在嘗試將父項內子項的基於像素的 x 和 y 值轉換為 Flutter 的 Alignment x 和 y。

這段代碼是根據 Flutter 自己的Alignment.inscribe function 改編和啟發的:

(打字稿)

function convertPositionToAlignment(
  parentWidth: number,
  parentHeight: number,
  childX: number,
  childY: number,
  childWidth: number,
  childHeight: number
): AlignmentModel {
  const halfWidthDelta = (parentWidth - childWidth) / 2;
  const halfHeightDelta = (parentHeight - childHeight) / 2;

  let x;
  if (halfWidthDelta != 0) {
    x = (childX - halfWidthDelta) / halfWidthDelta;
  } else {
    x = 0;
  }
  let y;
  if (halfHeightDelta != 0) {
    y = (childY - halfHeightDelta) / halfHeightDelta;
  } else {
    y = 0;
  }

  return new AlignmentModel(new AlignmentData(x, y));
}

作為對比,這里是 Flutter 的Alignment.inscribe function:

(鏢)

  /// Returns a rect of the given size, aligned within given rect as specified
  /// by this alignment.
  ///
  /// For example, a 100×100 size inscribed on a 200×200 rect using
  /// [Alignment.topLeft] would be the 100×100 rect at the top left of
  /// the 200×200 rect.
  Rect inscribe(Size size, Rect rect) {
    final double halfWidthDelta = (rect.width - size.width) / 2.0;
    final double halfHeightDelta = (rect.height - size.height) / 2.0;
    return Rect.fromLTWH(
      rect.left + halfWidthDelta + x * halfWidthDelta,
      rect.top + halfHeightDelta + y * halfHeightDelta,
      size.width,
      size.height,
    );
  }

代碼很簡單,但有一個問題是邊緣情況,如果孩子的大小等於父母的大小,那么這會產生零值(如果沒有 if 語句,它會產生無限/NaN)。

我想知道如果大小恰好相同,是否有任何方法可以計算 alignment。 這不是坐標空間的問題,而是 alignment 的問題。

我們希望消除這種邊緣情況的原因是針對這樣的情況:

圖片 1

相對:

圖 2

當圖像在坐標空間中很容易實現時,圖像與容器框大小相同的這種邊緣情況將立即導致 ay alignment 為零。

相反,我們可以考慮孩子的中心在內部矩形空間中的偏移量,其中 0,0 是孩子的左上角接觸父級的左上角且其右下角接觸父級的右下角的位置。 這樣我們就可以避免那種尷尬的分裂。

在這種情況下,我們的觀點

childCenterX = childX + childWidth / 2;
childCenterY = childY + childHeight / 2;

在一個矩形內

minOffsetX = childWidth / 2;
minOffsetY = childHeight / 2;
maxOffsetX = parentWidth - minOffsetX;
maxOffsetY = parentHeight - minOffsetY;

偏移量是

offset = childCenter - minOffset;

並在 -1..1 之間歸一化

innerWidth = maxOffsetX - minOffsetX;
innerHeight = maxOffsetY - minOffsetY;
offsetNormal = offset / innerSize * 2 - 1; // innerSize ≠ 0

編輯:如果父母和孩子在一個或多個軸上的大小完全相同,則內部大小仍然可以為零,因此這是一種快速而骯臟的解決方案:

double x, y;
if (innerWidth == 0) {
  x = child.x / child.width * 2 - 1;
} else {
  x = offsetX / innerWidth * 2 - 1;
}
if (innerHeight == 0) {
  y = child.y / child.height * 2 - 1;
} else {
  y = offsetY / innerHeight * 2 - 1;
}

Edit2:更緊湊的 typescript 版本:

const deltaWidth = (parentWidth - childWidth) / 2;
const deltaX = deltaWidth === 0 ? childWidth : deltaWidth;
const x = (childX - deltaX) / deltaX;
    
const deltaHeight = (parentHeight - childHeight) / 2;
const deltaY = deltaHeight === 0 ? childHeight : deltaHeight;
const y = (childY - deltaY) / deltaY;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM