Skip to content

平台

¥Platform

在任何可以执行 JavaScript 的平台上使用 Floating UI 的定位逻辑。

¥Use Floating UI’s positioning logic on any platform that can execute JavaScript.

Floating UI 的核心本质上是在矩形上执行的一系列数学计算。这些计算是纯粹且无关的,允许 Floating UI 在任何可以执行 JavaScript 的平台上工作。

¥Floating UI’s core is essentially a bunch of mathematical calculations performed on rectangles. These calculations are pure and agnostic, allowing Floating UI to work on any platform that can execute JavaScript.

为了使其能够在给定平台上工作,可以使用一些方法来允许它连接到测量 API,例如测量给定元素的边界框。

¥To make it work with a given platform, methods are used to allow it to hook into measurement APIs, for instance, to measure the bounding box of a given element.

除了 DOM 之外,可能的平台还包括 React Native、Canvas/WebGL 等。

¥Possible platforms other than the DOM include React Native, Canvas/WebGL, etc.

这是在纯 <canvas /> 元素中运行的 Floating UI!

¥This is Floating UI running in a pure <canvas /> element!

CodeSandbox 上查看一下。

¥Check it out on CodeSandbox.

自定义平台对象

¥Custom platform object

如果你从头开始构建一个平台,例如 你自己的微型自定义 DOM 平台,你将使用 @floating-ui/core 包 — 请参阅 方法

¥If you’re building a platform from scratch, e.g. your own tiny custom DOM platform, you’ll be using the @floating-ui/core package — see Methods.

如果你正在扩展或自定义现有的 DOM 方法,并且正在使用 @floating-ui/dom,则可以通过 platform 导入来访问:

¥If you’re extending or customizing the existing DOM methods, and are using @floating-ui/dom, this is accessible via the platform import:

import {platform} from '@floating-ui/dom';
 
computePosition(referenceEl, floatingEl, {
  platform: {
    ...platform,
    // Overwrite the methods above with your own.
  },
});

Shadow DOM 修复

¥Shadow DOM fix

不幸的是,offsetParent 存在一个平台差距,规范中规定将实际的 CSS offsetParent 隐藏在影子 DOM 层次结构中,这在使用 Web 组件时值得注意。当定位的父元素具有阴影子浮动元素时,这会导致位置错误。从 Chrome 109 开始,offsetParent 属性现在与规范匹配,Safari 和 Firefox 在相当长的一段时间内也与规范匹配,这导致了定位问题。

¥There’s an unfortunate platform gap regarding offsetParent where the spec says to hide the actual CSS offsetParent inside shadow DOM hierarchies, notable when using web components. This causes the position to be wrong when a positioned parent has a shadowed child floating element. Since Chrome 109, the offsetParent property now matches the spec, as well as Safari and Firefox for quite some time, which causes the positioning issue.

在许多情况下,使用 'fixed' 策略而不是 'absolute' 可以解决此定位问题,但如果不能解决问题,你可以添加以下 “ponyfill”:

¥In many cases, using the 'fixed' strategy instead of 'absolute' will fix this positioning issue, but in case it does not, you can add the following “ponyfill”:

npm i composed-offset-position
import {platform} from '@floating-ui/dom';
import {offsetParent} from 'composed-offset-position';
 
computePosition(referenceEl, floatingEl, {
  platform: {
    ...platform,
    getOffsetParent: (element) =>
      platform.getOffsetParent(element, offsetParent),
  },
});

概念

¥Concepts

该库主要与 Rect 配合使用:

¥The library works largely with a Rect:

interface Rect {
  width: number;
  height: number;
  x: number;
  y: number;
}

这些数据可以来自任何地方,并且库将执行正确的计算。xy 表示元素相对于另一个元素的坐标。

¥This data can come from anywhere, and the library will perform the right computations. x and y represent the coordinates of the element relative to another one.

import {computePosition} from '@floating-ui/core';
 
computePosition(referenceElement, floatingElement, {
  platform: {
    // ...
  },
});

方法

¥Methods

platform 是一个普通对象,由 3 个必需方法和 7 个可选方法组成。这些方法允许平台与 Floating UI 的逻辑进行交互。

¥A platform is a plain object consisting of 3 required and 7 optional methods. These methods allow the platform to interface with Floating UI’s logic.

这些方法中的每一个都可以是异步的或同步的。这可以支持测量 API 是异步的平台,例如 React Native。

¥Each of these methods can be either async or sync. This enables support of platforms whose measurement APIs are async, like React Native.

必需方法

¥Required methods

getElementRects

接收元素和定位 strategy 并返回元素 Rect 对象。

¥Takes in the elements and the positioning strategy and returns the element Rect objects.

function getElementRects({reference, floating, strategy}) {
  return {
    reference: {width: 0, height: 0, x: 0, y: 0},
    floating: {width: 0, height: 0, x: 0, y: 0},
  };
}

reference

如果需要,参考 Rectxy 值应该是其相对于浮动元素的 offsetParent 元素的坐标,而不是相对于视口的坐标。

¥The x and y values of a reference Rect should be its coordinates relative to the floating element’s offsetParent element if required rather than the viewport.

floating

xy 最初都不相关,因此你可以将这两者设置为 0

¥Both x and y are not relevant initially, so you can set these both of these to 0.

getDimensions

返回元素的尺寸。

¥Returns the dimensions of an element.

function getDimensions(element) {
  return {width: 0, height: 0};
}

getClippingRect

返回 Rect(相对于视口),其外部边界将裁剪给定元素。例如,视口本身。

¥Returns the Rect (relative to the viewport) whose outside bounds will clip the given element. For instance, the viewport itself.

function getClippingRect({element, boundary, rootBoundary}) {
  return {
    width: 0,
    height: 0,
    x: 0,
    y: 0,
  };
}

可选方法

¥Optional methods

根据你使用的平台,这些可能是必需的,也可能不是必需的。

¥Depending on the platform you’re working with, these may or may not be necessary.

convertOffsetParentRelativeRectToViewportRelativeRect

此函数将采用相对于给定 offsetParent 元素的 Rect 并转换其 xy 值,使其相对于视口。

¥This function will take a Rect that is relative to a given offsetParent element and convert its x and y values such that it is instead relative to the viewport.

function convertOffsetParentRelativeRectToViewportRelativeRect({
  rect,
  offsetParent,
  strategy,
}) {
  return rect;
}

getOffsetParent

返回给定元素的 offsetParent。以下四个属性是在 offsetParent 上访问的内容。

¥Returns the offsetParent of a given element. The following four properties are what is accessed on an offsetParent.

function getOffsetParent(element, polyfill) {
  return {
    clientWidth: 0,
    clientHeight: 0,
    clientLeft: 0,
    clientTop: 0,
  };
}

polyfill 参数仅适用于 @floating-ui/dom,对于修复 Shadow DOM 错误 是可选的。

¥The polyfill parameter exists only for @floating-ui/dom and is optional to fix the Shadow DOM bug.

getDocumentElement

返回文档元素。

¥Returns the document element.

function getDocumentElement(element) {
  return {};
}

getClientRects

返回 ClientRect 的数组。

¥Returns an array of ClientRects.

function getClientRects(element) {
  return [];
}

isElement

确定当前值是否为元素。

¥Determines if the current value is an element.

function isElement(value) {
  return true;
}

isRTL

确定元素是否处于 RTL 布局中。

¥Determines if an element is in RTL layout.

function isRTL(element) {
  return false;
}

getScale

确定元素的比例。

¥Determines the scale of an element.

function getScale(element) {
  return {x: 1, y: 1};
}

用法

¥Usage

所有这些方法都传递给 platform

¥All these methods are passed to platform:

import {computePosition} from '@floating-ui/core';
 
computePosition(referenceEl, floatingEl, {
  platform: {
    // Required
    getElementRects,
    getDimensions,
    getClippingRect,
 
    // Optional
    convertOffsetParentRelativeRectToViewportRelativeRect,
    getOffsetParent,
    getDocumentElement,
    getClientRects,
    isElement,
    isRTL,
    getScale,
  },
});