【问题标题】:Temporarily make element invisible暂时使元素不可见
【发布时间】:2017-04-06 07:04:41
【问题描述】:

我正在使用document.elementFromPoint API 来获取位于某个点的元素。但我不想拥有所有元素——有些是不合格的,比如inline 元素。因此,我让不合格的元素暂时不可见,以便抓住它下面的元素。

这是一段代码摘录。

import { elementQualified, elementFromPoint } from './utils';

function makeInvisible(element) {
  let oldVisibility = element.style.visibility;

  /* this is supposed to make the element invisible immediately, without
   * any delay. When a `transition` property is set which includes the
   * `visibility` property, this is sometimes unfortunately not the case. */
  element.style.visibility = "hidden";

  /* this is the undo function being called at the end. */
  return () => {
    element.style.visibility = oldVisibility;
  };
}

export default function(x, y) {
  var undo = [], element, last;

  /* in a loop, we grab the top-most element that is at a certain coordinate
   * inside the viewport. The `last` variable is preventing an infinite loop
   * in cases, where `makeInvisible()` does not work. */
  while (((element = elementFromPoint(x, y)) !== null) && (last !== element)) {
    /*
     * In order to be qualified, this element including its ancestors must
     * all be qualified. For instance, if this is a block element but the
     * parent for some reason is an inline element, this is not desired. */
    if (withAncestors(element).every(elementQualified)) {
        break;
    }

    /* if the element is not qualified, we make it invisible and add it to the
     * start of the `undo` array which is being batch-called after this loop. */
    undo.unshift(makeInvisible(element));

    /* and the loop protection */
    last = element;
  }

  /* undo all changes */
  undo.forEach((fn) => fn());

  /* check if we broke the loop or we have selected the topmost element
   * in which case we discard the result. */
  if ((last === element) || (element === document.documentElement)) {
    return null;
  }

  return element;
}

如果应该变为不可见的元素具有包含visibility 属性的transition 属性集,则它不会立即变为不可见。以transition: all 0.3s ease-in-out 为例。将element.style.visibility 设置为hidden 后,将需要0.3s,之后该元素实际上是不可见的,document.elementFromPoint 将选择它下面的元素。结果,循环中断了,因为document.elementFromPoint 返回了两倍的相同元素。

我不打算临时设置 display 属性,因为它会导致布局更改,我正在构建一个布局更改不起作用的工具。

【问题讨论】:

  • 您不能在将元素设置为不可见之前删除过渡并在完成后将其重新设置吗?
  • "... 显示属性 ... 导致布局更改" 当您同步执行所有 DOM 处理并将所有内容设置回原样时,它不会在让浏览器有机会呈现页面之前。因此,如果您在脚本结束之前删除样式,则在脚本中设置 display: none 将不会显示在页面上。
  • 我之前尝试过display: none 选项。它会给我带来一些布局变化和滚动问题。

标签: javascript html dom


【解决方案1】:

正如 Lain 在 cmets 中建议的那样,makeInvisible 中的元素上的 disable transitions,然后有一个超时(1ms 应该足够)重置转换属性

【讨论】:

  • 我发现可以在没有超时的情况下重新启用转换。我只是将visibility 设置为旧值,然后在设置transition 属性之前导致布局重排。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-22
相关资源
最近更新 更多