【问题标题】:How to trigger a keypress with pure javascript?如何用纯javascript触发按键?
【发布时间】:2020-07-14 17:21:43
【问题描述】:

我正在尝试在单击 HTML 按钮时根据其 ID 获取要按下的键,在本例中为 NumPad0、Alt、PageUp、PageDown 或 Ctrl+A 之类的组合。

例如,

<button id="myButton">Button</button>

当按钮被点击时,

function simulateClick(id) {
    var clickEvent = document.createEvent("MouseEvents");
    clickEvent.initMouseEvent("click", true, true, window, 1, 0, 0, 0, 0,
        false, false, false, false, 0, null);

    var element = document.getElementById('myButton');
    element.dispatchEvent(new KeyboardEvent('keypress',{'key':'PageDown'}));
}

但是,当我单击时,没有任何反应。

最终目标是运行一个绑定到某些键和组合键的自动热键脚本,以便有效地单击按钮将运行自动热键脚本的该部分,就像我按下了键盘按钮一样。

我看到了如何用 jquery 来做,但我需要使用纯 js。如何使用纯 javascript 触发按键?

【问题讨论】:

  • JQuery 是开源的。您可以通过深入了解内部结构来检查幕后发生的事情
  • 你的意思是你想以程序方式触发在 JavaScript 中按下的键,即“按下用户的键”。如果是这种情况,出于明显的安全原因,您不能在 JavaScript 中执行此操作...
  • 您真的需要触发keypress 还是只是调用实际按下键会调用的处理程序?
  • 根据@Enijar,JavaScript 无法将操作系统级别的关键事件发送到浏览器。
  • @ScottMarcus 无论哪种解决方案最适合触发查找按键的 AutoHotKey 脚本。

标签: javascript events keypress


【解决方案1】:

如果你想模拟按键,你就在正确的轨道上。

首先将您要模拟的事件添加到文档/元素,然后您可以向按钮添加点击侦听器以触发您正在侦听的事件。

触发关键事件实际上不会为您滚动文档,您需要一种以编程方式滚动页面的方法。这篇文章,标题为"Page scrolling in vanilla JavaScript",有一个模拟滚动的功能。我在下面对其进行了改编。我让它一次滚动文档高度的 25%。 Page Down 按钮会随着文档的滚动量而变化。

请注意,作者更新了他们的帖子以表明有一个polyfill 用于window.scroll 可能会更好。

const AUTO_SCROLL = false

const btn = document.querySelector('#my-button')
const ara = document.querySelector('#my-textarea')

document.addEventListener('keydown', onKeyPress)
btn.addEventListener('click', simulateClick)

function onKeyPress(e) {
  if (e.key === 'PageDown') {
    ara.value += 'DOWN\n'
  }
}

function simulateClick(e) {
  // Scroll the document
  if (AUTO_SCROLL) {
    const documentHeight = Math.max(document.body.scrollHeight,
      document.body.offsetHeight, document.documentElement.clientHeight,
      document.documentElement.scrollHeight, document.documentElement.offsetHeight);
    scrollIt(window.pageYOffset + (documentHeight * 0.25))
  }
  // Fire the event to handle the rest...
  document.dispatchEvent(new KeyboardEvent('keydown', {
    key: 'PageDown'
  }))
}

/** Source: https://pawelgrzybek.com/page-scroll-in-vanilla-javascript/ */
function scrollIt(destination, duration = 200, easing = 'linear', callback) {
  const easings = {
    linear(t) {
      return t;
    },
    easeInQuad(t) {
      return t * t;
    },
    easeOutQuad(t) {
      return t * (2 - t);
    },
    easeInOutQuad(t) {
      return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
    },
    easeInCubic(t) {
      return t * t * t;
    },
    easeOutCubic(t) {
      return (--t) * t * t + 1;
    },
    easeInOutCubic(t) {
      return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
    },
    easeInQuart(t) {
      return t * t * t * t;
    },
    easeOutQuart(t) {
      return 1 - (--t) * t * t * t;
    },
    easeInOutQuart(t) {
      return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
    },
    easeInQuint(t) {
      return t * t * t * t * t;
    },
    easeOutQuint(t) {
      return 1 + (--t) * t * t * t * t;
    },
    easeInOutQuint(t) {
      return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t;
    }
  };

  const start = window.pageYOffset;
  const startTime = 'now' in window.performance
    ? performance.now() : new Date().getTime();

  const documentHeight = Math.max(document.body.scrollHeight,
    document.body.offsetHeight, document.documentElement.clientHeight,
    document.documentElement.scrollHeight, document.documentElement.offsetHeight);
  const windowHeight = window.innerHeight ||
    document.documentElement.clientHeight ||
    document.getElementsByTagName('body')[0].clientHeight;
  const destOffset = typeof destination === 'number'
    ? destination : destination.offsetTop;
  const destOffScroll = Math.round(documentHeight - destOffset < windowHeight
    ? documentHeight - windowHeight : destOffset);

  if ('requestAnimationFrame' in window === false) {
    window.scroll(0, destOffScroll);
    if (callback) {
      callback();
    }
    return;
  }

  function scroll() {
    const now = 'now' in window.performance ? performance.now() : new Date().getTime();
    const time = Math.min(1, ((now - startTime) / duration));
    const timeFunction = easings[easing](time);
    window.scroll(0, Math.ceil((timeFunction * (destOffScroll - start)) + start));

    if (window.pageYOffset === destOffScroll) {
      if (callback) {
        callback();
      }
      return;
    }
    
    requestAnimationFrame(scroll);
  }

  scroll();
}
#my-button {
  position: fixed;
  right: 4em;
  top: 1.33em;
}
<textarea id="my-textarea" rows="100" cols="62"></textarea>
<button id="my-button">Button</button>

【讨论】:

  • 请注意,我不想进行任何滚动。我希望能够选择要按下的特定键,以便 autohotkey 将其作为按键拾取并运行相应的脚本。例如,我选择了很少使用的 PageDown 键来分配给宏。如果我可以在单击页面按钮后触发按键,那么我应该能够实现我的目标。
  • @coder9328 如果您不想要程序化滚动,那么只需将该部分保留。该事件仍按预期触发。
  • 我不确定要省略什么。您可以使用我需要的内容更新或附加您的答案,以便仅在按钮单击时触发关键事件吗?谢谢。
  • @coder9328 我将您可以删除的代码包装在AUTO_SCROLL 标志中。该条件内的代码可以省略。连同整个 scrollIt 函数声明。我将其默认为false,因此它实际上不会滚动。
  • 这实际上使它变得更加复杂。附加两个答案会更容易 - 一个有滚动,一个没有。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 2020-02-10
  • 1970-01-01
相关资源
最近更新 更多