aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/visualviewport/index.html
blob: da9f74123eea2a824783a810412d6ad1b6ca1d1b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
---
title: VisualViewport
slug: Web/API/VisualViewport
tags:
  - API
  - Experimental
  - Interface
  - NeedsTranslation
  - Reference
  - TopicStub
  - Visual Viewport API
  - VisualViewport
  - viewport
translation_of: Web/API/VisualViewport
---
<p>{{SeeCompatTable}}{{APIRef("Visual Viewport")}}</p>

<p> <a href="/zh-CN/docs/Web/API/Visual_Viewport_API">Visual Viewport API</a> 提供了当前页面的视觉视口接口,即 <strong><code>VisualViewport</code></strong> 。对于每个页面容器来说(如 iframe),都存在有一个独立的 window 对象。每个页面容器的 window 对象都有一个独立的 <code>VisualViewport</code> 属性。</p>

<p>你可以使用 {{domxref("Window.visualViewport")}} 获得对应 window 的视觉视口 API。</p>

<div class="note">
<p><strong>注意</strong>:与布局视口(layout viewport)不同的是:只有最上层的 window 才有视觉视口(visual viewport)这一概念。因此只有最上层 window 的 <code>VisualViewport</code> 属性才是有效的,其他层的视觉视口属性可看作是布局视口属性的别名。比如,对于一个 {{htmlelement("iframe")}} ,其对应的视觉视口属性 {{domxref("VisualViewport.width")}} 相当于对应的布局视口属性,如 {{domxref("Element.clientWidth", "document.documentElement.clientWidth")}}.</p>
</div>

<h2 id="属性">属性</h2>

<p><em><code>VisualViewport</code></em> 从其父元素继承属性 <em>{{domxref("EventTarget")}}</em></p>

<dl>
 <dt>{{domxref("VisualViewport.offsetLeft")}} {{readonlyinline}}</dt>
 <dd>返回视觉视口的左边框到布局视口的左边框的 CSS 像素距离。</dd>
 <dt>{{domxref("VisualViewport.offsetTop")}} {{readonlyinline}}</dt>
 <dd>返回视觉视口的上边框到布局视口的上边框的 CSS 像素距离。</dd>
 <dt>{{domxref("VisualViewport.pageLeft")}} {{readonlyinline}}</dt>
 <dd>返回相对于初始的 viewport 属性的 X 轴坐标所对应的 CSS 像素数。</dd>
 <dt>{{domxref("VisualViewport.pageTop")}} {{readonlyinline}}</dt>
 <dd>返回相对于初始的 viewport 属性的 Y 轴坐标所对应的 CSS 像素数。</dd>
 <dt>{{domxref("VisualViewport.width")}} {{readonlyinline}}</dt>
 <dd>返回视觉视口的宽度所对应的 CSS 像素数。</dd>
 <dt>{{domxref("VisualViewport.height")}} {{readonlyinline}}</dt>
 <dd>返回视觉视口的高度所对应的 CSS 像素数。</dd>
 <dt>{{domxref("VisualViewport.scale")}} {{readonlyinline}}</dt>
 <dd>返回当前视觉视口所应用的缩放比例。</dd>
</dl>

<h2 id="Events">Events</h2>

<p>通过使用 <code><a href="/zh-CN/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> 或者将监听回调函数赋值给对应的 <code>on<em>eventname</em></code> 属性,可以为对应的视口事件添加监听。</p>

<dl>
 <dt><code><a href="/zh-CN/docs/Web/API/VisualViewport/resize_event">resize</a></code></dt>
 <dd>当视觉视口被改变时触发。</dd>
 <dd>也可以为 {{domxref("VisualViewport.onresize")}} 属性赋值来添加监听。</dd>
 <dt><code><a href="/zh-CN/docs/Web/API/VisualViewport/scroll_event">scroll</a></code></dt>
 <dd>当视觉视口滑动时触发。</dd>
 <dd>也可以为 {{domxref("VisualViewport.onscroll")}} 属性赋值来添加监听。</dd>
</dl>

<h2 id="例子">例子</h2>

<h3 class="highlight-spanned" id="缩放检测并隐藏元素"><span class="highlight-span">缩放检测并隐藏元素</span></h3>

<p>这个例子取自 <a href="https://github.com/WICG/visual-viewport">Visual Viewport README</a>,展示了如何在用户缩放时隐藏某个盒子(或元素)。这对于增强一个页面在缩放时的用户体验有重要意义。同样,你也可以查看另一个 <a href="https://wicg.github.io/visual-viewport/examples/hide-on-zoom.html">例子</a> 。</p>

<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> bottomBar <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">'bottombar'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">var</span> viewport <span class="operator token">=</span> window<span class="punctuation token">.</span>visualViewport<span class="punctuation token">;</span>

<span class="keyword token">function</span> <span class="function token">resizeHandler</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
   <span class="keyword token">if</span> <span class="punctuation token">(</span>viewport<span class="punctuation token">.</span>scale <span class="operator token">&gt;</span> <span class="number token">1.3</span><span class="punctuation token">)</span>
     bottomBar<span class="punctuation token">.</span>style<span class="punctuation token">.</span>display <span class="operator token">=</span> <span class="string token">"none"</span><span class="punctuation token">;</span>
   <span class="keyword token">else</span>
     bottomBar<span class="punctuation token">.</span>style<span class="punctuation token">.</span>display <span class="operator token">=</span> <span class="string token">"block"</span><span class="punctuation token">;</span>
<span class="punctuation token">}</span>

window<span class="punctuation token">.</span>visualViewport<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">'resize'</span><span class="punctuation token">,</span> resizeHandler<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<h3 class="highlight-spanned" id="模拟_position_属性:device-fixed"><span class="highlight-span">模拟 position 属性:device-fixed</span></h3>

<p>这个例子同样取自 <a href="https://github.com/WICG/visual-viewport">Visual Viewport README</a> ,展示了如何使用视觉视口 API,从而模拟 <code>position: device-fixed</code> 的 CSS 属性。类似于 <code>position: fixed</code> ,这一属性可将被设置的元素固定在视觉视口特定位置。此外,你也可以查看另一个 <a href="https://wicg.github.io/visual-viewport/examples/fixed-to-viewport.html">例子</a> 。</p>

<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> bottomBar <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">'bottombar'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>
<span class="keyword token">var</span> viewport <span class="operator token">=</span> window<span class="punctuation token">.</span>visualViewport<span class="punctuation token">;</span>
<span class="keyword token">function</span> <span class="function token">viewportHandler</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span>
  <span class="keyword token">var</span> layoutViewport <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">'layoutViewport'</span><span class="punctuation token">)</span><span class="punctuation token">;</span>

  <span class="comment token">// Since the bar is position: fixed we need to offset it by the visual</span>
  <span class="comment token">// viewport's offset from the layout viewport origin.</span>
  <span class="keyword token">var</span> offsetLeft <span class="operator token">=</span> viewport<span class="punctuation token">.</span>offsetLeft<span class="punctuation token">;</span>
  <span class="keyword token">var</span> offsetTop <span class="operator token">=</span> viewport<span class="punctuation token">.</span>height
              <span class="operator token">-</span> layoutViewport<span class="punctuation token">.</span><span class="function token">getBoundingClientRect</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">.</span>height
              <span class="operator token">+</span> viewport<span class="punctuation token">.</span>offsetTop<span class="punctuation token">;</span>

  <span class="comment token">// You could also do this by setting style.left and style.top if you</span>
  <span class="comment token">// use width: 100% instead.</span>
  bottomBar<span class="punctuation token">.</span>style<span class="punctuation token">.</span>transform <span class="operator token">=</span> <span class="string token">'translate('</span> <span class="operator token">+</span>
                              offsetLeft <span class="operator token">+</span> <span class="string token">'px,'</span> <span class="operator token">+</span>
                              offsetTop <span class="operator token">+</span> <span class="string token">'px) '</span> <span class="operator token">+</span>
                              <span class="string token">'scale('</span> <span class="operator token">+</span> <span class="number token">1</span><span class="operator token">/</span>viewport<span class="punctuation token">.</span>scale <span class="operator token">+</span> <span class="string token">')'</span>
<span class="punctuation token">}</span>
window<span class="punctuation token">.</span>visualViewport<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">'scroll'</span><span class="punctuation token">,</span> viewportHandler<span class="punctuation token">)</span><span class="punctuation token">;</span>
window<span class="punctuation token">.</span>visualViewport<span class="punctuation token">.</span><span class="function token">addEventListener</span><span class="punctuation token">(</span><span class="string token">'resize'</span><span class="punctuation token">,</span> viewportHandler<span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre>

<div class="blockIndicator note">
<p><strong>注意</strong>:应小心使用上述方案,使用这种方式模拟的 <code>position: device-fixed</code> 可能会导致其他元素在滚动页面时出现闪烁。</p>
</div>

<h2 id="规范">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">规范</th>
   <th scope="col">状态</th>
   <th scope="col">提交</th>
  </tr>
  <tr>
   <td>{{SpecName('Visual Viewport','#the-visualviewport-interface','VisualViewport')}}</td>
   <td>{{Spec2('Visual Viewport')}}</td>
   <td>Initial definition.</td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容性">浏览器兼容性</h2>

<p>{{Compat("api.VisualViewport")}}</p>

<h2 id="参照">参照</h2>

<ul>
 <li><a href="https://github.com/bokand/bokand.github.io/blob/master/web_viewports_explainer.md">Web 视口说明</a> — 解释了什么是浏览器视口和视觉视口和布局视口的区别。</li>
</ul>