什么是“线”的高度?在轮子事件? (deltaMode = DOM_DELTA_LINE) [英] What is the height of a "line" in a wheel event? (deltaMode = DOM_DELTA_LINE)

查看:298
本文介绍了什么是“线”的高度?在轮子事件? (deltaMode = DOM_DELTA_LINE)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<>在Firefox> = 17中的 wheel 事件有一个 deltaMode 属性。使用我使用的操作系统/鼠标,它设置为 1 (或 DOM_DELTA_LINE )。此设置意味着 deltaX deltaY 事件值是以行而不是像素来衡量的。果然,如果我假设三角洲是像素,滚动速度比Firefox通常慢得多。



Chrome 31相比较,使用 deltaMode 0 (或 DOM_DELTA_PIXEL ),这使我可以模拟正常速度的滚动。

如果我可以将行值转换为像素值,我将被设置。但是我找不到有关线路的文档。我尝试在Firefox中更改 font-size line-height ,这并没有改变滚动行为。 / p>

任何人都知道一个行是如何定义的? W3C只是说,许多表单控件都是这种情况。



这意味着要正确检测滚动中使用的行高,您必须使用完全不带风格的行内元素来检测计算的渲染高度。由于页面上的CSS几乎肯定会干扰,所以我们必须在iframe中创建一个新的干净的窗口来检测。



检测<$使用的行高c $ c> DOM_DELTA_LINE 触发滚动事件:

为了这个目的,我创建了以下小函数来同步检测纯粹的,不变的行

  function getScrollLineHeight(){
var r;
var iframe = document.createElement('iframe');
iframe.src ='#';
document.body.appendChild(iframe);
var iwin = iframe.contentWindow;
var idoc = iwin.document;
idoc.open();
idoc.write('<!DOCTYPE html>< html>< head>< / head>< body>< span> a< / span>< / body>< / html> ;');
idoc.close();
var span = idoc.body.firstElementChild;
r = span.offsetHeight;
document.body.removeChild(iframe);
return r;
}

//获取本地滚动行高度。
console.log(getScrollLineHeight());好的,现在我们知道线高度增量应该以像素为单位转换多少。但是,在Window上,还有一件事情你可能需要考虑。在Windows上,默认的滚动速度被覆盖,默认情况下,它的速度提高了2倍,但是仅限于根元素。





激活此功能后,只需点击一下即可滚动几乎整页,这意味着滚动面板的高度减去滚动条。我差不多说了,因为Firefox会考虑一些其他的事情来减少滚动的数量。也就是说,减少一些线,百分比,并以某种方式减去固定位置的页眉和页脚。看到下面的代码块的一些逻辑。



摘自 layout / generic / nsGfxScrollFrame.cpp
$ b


  nsSize 
ScrollFrameHelper :: GetPageScrollAmount()const
{
nsSize lineScrollAmount = GetLineScrollAmount();
nsSize effectiveScrollPortSize;
if(mIsRoot){
//将有效的scrollport高度降低任何fixed-pos
//页眉或页脚的高度
nsIFrame * root = mOuter-> PresContext ) - > PresShell() - > GetRootFrame();
effectiveScrollPortSize =
GetScrollPortSizeExcludingHeadersAndFooters(root,mScrollPort);
} else {
effectiveScrollPortSize = mScrollPort.Size();
}
//页面增量是页面的大小,减去
中的较小值//大小的10%或2行。
return nsSize(
effectiveScrollPortSize.width -
std :: min(effectiveScrollPortSize.width / 10,2 * lineScrollAmount.width),
effectiveScrollPortSize.height -
std :: min(effectiveScrollPortSize.height / 10,2 * lineScrollAmount.height));

$ / code>


我不是100%完全被检测为一个固定位置的页眉和页脚元素,而不是,但是这应该给出一个相当不错的 DOM_DELTA_PAGE 模式的工作方式,除了 DOM_DELTA_LINE 这个问题就是关于这个问题的。


The wheel event in Firefox >= 17 has a deltaMode property. With the OS/mouse I'm using, it's set to 1 (or DOM_DELTA_LINE). This setting means that the deltaX and deltaY event values are measured in lines and not pixels. Sure enough, if I pretend the deltas are pixels, scroll speeds are much slower than they normally are in Firefox.

Chrome 31 by contrast uses a deltaMode of 0 (or DOM_DELTA_PIXEL), which allows me to simulate scrolling with normal speeds.

If I could convert the line values to pixel values, I'd be all set. But I can't find a scrap of documentation about what a "line" is. I tried changing the font-size and line-height in Firefox, which didn't change the scrolling behavior.

Anyone know how a "line" is defined? W3C just says, "This is the case for many form controls."

W3C deltaMode

MDN WheelEvent

MDN wheel

Edit: here's a fiddle to demonstrate the oddity. When Firefox is in DOM_DELTA_LINE mode, there's no consistent ratio between pixels and lines – it's all over the place. And when I switch to using a trackpad instead of a mouse, causing Firefox to switch to DOM_DELTA_PIXEL mode, there's also no consistent ratio. On the other hand, in Chrome 31, the ratio is almost always very close to 1:1 in DOM_DELTA_PIXEL mode.

Chromium issue: implement DOM3 wheel event

Bugzilla bug: implement DOM3 wheel event

Update: Scrolling by single ticks of a mouse wheel in Firefox where deltaMode is DOM_DELTA_LINE, the pixel delta is dependent on the CSS font-size, but not on line-height. See this fiddle for a demonstration. This behavior only holds when ticking the wheel very slowly. With speed or momentum, the line to pixel ratio isn't predictable at any particular instance or in aggregate. As far as I can tell, there's no way to emulate Firefox's scroll behavior using the delta measurements provided in DOM_DELTA_LINE mode.

In DOM_DELTA_PIXEL mode, the behavior is nearly pixel-perfect. That is, the ratio between actual pixels scrolled and the reported pixel delta value is almost exactly 1, which is demonstrated in the the same fiddle.

I filed a bug with Mozilla, arguing that the behavior of the wheel event in DOM_DELTA_LINE mode isn't useful because it isn't predictable (i.e., it's an equation where both the unit and the magnitude are variables). The issue has been marked invalid because the expected behavior is for the wheel event to pass through the native deltas provided by the OS, despite the fact that Firefox itself doesn't honor these deltas.

I'll leave this question open in the hope that DOM_DELTA_LINE will be defined by a spec somewhere. As far as I know, the dependence on font-size (and not line-height) isn't yet described anywhere.

解决方案

Overview:

While the scroll value resulting from DOM_DELTA_LINE may not be specifically defined by any specification, based on the following comment from the Chromium issue tracker and my own observations, it appears that Firefox is presently the only browser that will report wheel events with anything other than deltaMode as DOM_DELTA_PIXEL (0).

Comment from Chromium issue Implement DOM3 wheel event:

We ended up doing what IE does and report the exact number of pixels we would scroll the element.

The following asserts are always true (given that the element can be scrolled).

element.scrollTop = 0;
element.addEventListener('wheel', function(e) {
  assert(e.deltaMode === MouseEvent. DOM_DELTA_PIXEL);
  assert(element.scrollTop === e.deltaY);
});
// scroll

This way you know exactly how much to scroll at all times.

We never set the deltaMode to anything else but DOM_DELTA_PIXEL.

According to that comment, Chromium matches IE's only-pixel deltas. Though not covered, this almost certainly extends directly to modern Opera and Safari. My own observations from testing on Window, Mac, and Linux with multiple input devices did not disprove this.

So since Firefox is the only browser that will report a deltaMode of DOM_DELTA_LINE (1) or DOM_DELTA_PAGE (2), for the time being anyway, we only need to know what Firefox computes these values as. Well, that's where things get a bit tricky, but through searching through the Firefox source and some trial and error, I've determined it directly corresponds the default font and default font-size. Specifically those configured in the following preferences, ignoring any CSS on the page.

That means that to correctly detect the line-height used in scrolling, you must have a completely un-styled inline element to detect the computed rendering height from. Since CSS on the page will almost certainly interfere, we must create a new and clean window in an iframe to do the detection.

Detecting the line-height used by DOM_DELTA_LINE triggered scroll events:

For this purpose, I have created the following little function to synchronously detect the pure, unaltered line-height.

function getScrollLineHeight() {
    var r;
    var iframe = document.createElement('iframe');
    iframe.src = '#';
    document.body.appendChild(iframe);
    var iwin = iframe.contentWindow;
    var idoc = iwin.document;
    idoc.open();
    idoc.write('<!DOCTYPE html><html><head></head><body><span>a</span></body></html>');
    idoc.close();
    var span = idoc.body.firstElementChild;
    r = span.offsetHeight;
    document.body.removeChild(iframe);
    return r;
}

// Get the native croll line height.
console.log(getScrollLineHeight());

Ok, so now we know just how much a line-height delta should translate to in pixels. However, on Window, there is one other thing that you may need to take into consideration. On Windows, the default scroll speed is overridden to make it 2x faster by default, but only for the root element.

Override system of system scroll speed:

We're providing an override mechanism of system scroll speed because the default system scrolling speed of Windows is slower than WebKit's scrolling speed. This was suggested for alternative way of the acceleration system (see next section).

This is enabled in default settings only on Windows. mousewheel.system_scroll_override_on_root_content.enabled can switch it.

On Windows, only when the system scroll speed settings are not customized by user or mouse driver, this overrides the scrolling speed. On the others, this always overrides the speed.

The ratio can be specified by hidden prefs. mousewheel.system_scroll_override_on_root_content.vertical.factor is for vertical scrolling event. mousewheel.system_scroll_override_on_root_content.horizontal.factor is for horizontal scrolling event. The values are used as 1/100 (i.e., the default value 200 means 2.0).

nsEventStateManager multiplies the scrolling speed by the ratio when it executes to scroll a root scrollable view of a document. So, DOMMouseScroll event's delta value has never been overwritten by this.

See also bug 513817.

This is only applicable by default to the root of the document, scrolling elements within the document like a textarea are not affected (except maybe iframes?). There's also no way to get the specified value if the default 2x is reconfigured, so if you deem this value important, you will have to resort to user-agent OS sniffing, perhaps with the technically non-standard yet popular navigator.platform.

What about DOM_DELTA_PAGE?:

Windows also has an alternate setting for vertical scrolling where instead of scrolling by the number of lines, it scroll by an almost full page. To clarify, this is the dialog with the "One screen at a time" setting controlling this in Windows 7.

When this is activated, a single click will scroll almost a full page, here meaning the height of the scrolling panel, minus the scroll bars. I say almost, because Firefox takes some other things into consideration to reduce the amount of scrolling. Namely, reducing by some lines, a percentage, and somehow subtracting the fixed position headers and footers. See the following block of code for some of the logic.

Excerpt from layout/generic/nsGfxScrollFrame.cpp:

nsSize
ScrollFrameHelper::GetPageScrollAmount() const
{
  nsSize lineScrollAmount = GetLineScrollAmount();
  nsSize effectiveScrollPortSize;
  if (mIsRoot) {
    // Reduce effective scrollport height by the height of any fixed-pos
    // headers or footers
    nsIFrame* root = mOuter->PresContext()->PresShell()->GetRootFrame();
    effectiveScrollPortSize =
      GetScrollPortSizeExcludingHeadersAndFooters(root, mScrollPort);
  } else {
    effectiveScrollPortSize = mScrollPort.Size();
  }
  // The page increment is the size of the page, minus the smaller of
  // 10% of the size or 2 lines.
  return nsSize(
    effectiveScrollPortSize.width -
      std::min(effectiveScrollPortSize.width/10, 2*lineScrollAmount.width),
    effectiveScrollPortSize.height -
      std::min(effectiveScrollPortSize.height/10, 2*lineScrollAmount.height));
}

I'm not 100% sure what exactly is detected as a fixed position header and footer element and what isn't, but this should give a pretty good overview of how the DOM_DELTA_PAGE mode also works, in addition to the DOM_DELTA_LINE which this question asks about.

这篇关于什么是“线”的高度?在轮子事件? (deltaMode = DOM_DELTA_LINE)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆