IFrame 中 ExtJS 5 应用程序的滚动问题
Scrolling issues with ExtJS 5 app inside IFrame
嗨,
这是我的测试页的样子:
蓝色区域是父页面,绿色区域是运行 ExtJS 应用程序的 IFrame(内部带有标签的简单视口)。
如果站点在触摸设备(IPad、Android 平板电脑等)上运行,则无法在 IFrame(绿色区域)上按 "wiping" 滚动页面.必须在蓝色区域擦拭才能滚动页面。
这在 ExtJS v4.2.1 中工作正常(见下面的链接)。
测试站点:
https://skaface.leo.uberspace.de/ScrollTest/Ext510/(未按预期工作,使用 ExtJS v5.1.1)
https://skaface.leo.uberspace.de/ScrollTest/Ext421/(按预期工作,代码相同但使用 ExtJS v4.2.1)
测试代码:
父网站(index.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body style="margin: 50px; background-color: blue;">
<iframe src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
</html>
IFrame (frame.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="https://extjs.cachefly.net/ext/gpl/5.1.0/packages/ext-theme-neptune/build/resources/ext-theme-neptune-all-debug.css" />
<script type="text/javascript" src="https://extjs.cachefly.net/ext/gpl/5.1.0/build/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.onReady(function() {
Ext.create('Ext.container.Viewport', {
style: { 'background-color': 'yellowgreen' },
layout: 'fit',
items: [{
xtype: 'label',
text: 'Ext version: ' + Ext.versions.extjs.version,
margin: 16
}]
});
});
</script>
</head>
<body>
</body>
</html>
我真的很感激这个问题的解决方法,因为它实际上使我的网站在移动设备上毫无用处,即使它们在 ExtJS 4.2.1 上工作得很好。
谢谢并致以最诚挚的问候
Ps.: 我已经发布了一个错误报告 in the sencha forums,但是因为我在那里没有得到任何帮助直到知道,所以我也在 Whosebug 上试试运气.. .
行为很奇怪,我在使用niceScroll插件之前已经看到它,许多其他插件也与iframe
有同样的问题,无论如何检查this workaround
我已经使用 Hammer.js jQuery 插件来检测您 iframe
上的触摸手势,如果您发现任何关于灵敏度的问题(如我不知道你在寻找什么约束),你可以调整 hammer.js 在他们的 repo 上找到的选项(比如 pan threshold ,pointers ..etc )
并且代码非常简单:
<body id="mainbody" style="margin: 50px; background-color: blue;">
<iframe id="myframe" src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
<script>
var myBody
$('iframe').load(function(){
myBody=$(this).contents().find("body");
myBody.css({"height":"100%","overflow":"hidden"}).hammer({threshold:1}).bind("pan", myPanHandler);
});
function myPanHandler(ev)
{
$("#mainbody").scrollTop($("#mainbody").scrollTop()-ev.gesture.deltaY)
console.log(($("#mainbody").scrollTop()-ev.gesture.deltaY*0.5)+".."+$("#mainbody").scrollTop())
}
</script>
在框架内部进行了大量挖掘之后,我终于找到了一个至少对我有用的解决方案,它包含 2 个步骤:
1) ExtJS 将视口的 CSS 属性 touch-action
(IFrame 的基本 html 元素)及其主体设置为值 none
.
我只是用值 auto
:
覆盖了它
.x-viewport, .x-viewport > .x-body {
touch-action: auto;
}
2) class Ext.container.Viewport
在其创建回调中调用 Ext.plugin.Viewport.decorate(this);
,这会向视口本身的 touchmove
事件添加一个侦听器。
侦听器所做的一切都是调用事件的 preventDefault();
,这就是滚动在父页面或 IFrame 本身上不再起作用的原因。
我的修复只是从 touchmove
事件处理程序中删除了 preventDefault()
而不是 returns false
让事件在浏览器链中冒泡:
Ext.define('Cbn.overrides.container.Viewport', {
override: 'Ext.container.Viewport'
}, function() {
Ext.override(this, {
onRender: function() {
this.mon(Ext.getDoc(), {
touchmove: function(e) {
// e.preventDefault(); // Original ExtJS code
return false;
},
translate: false,
delegated: false
});
this.callParent(arguments);
}
});
});
我不太确定这 2 个修复是否有任何负面影响,但到目前为止它们似乎对我有用。
我确实意识到的一件事是,在 IFrame-App 中使用带有配置 scrollable: true
的组件仍然会产生问题,但由于我几乎可以在任何地方避免这种情况,所以到目前为止对我来说这不是问题...
工作测试站点:https://skaface.leo.uberspace.de/ScrollTest/Ext510_fixed/
编辑:
稍微调整了解决方案,以免在触摸滚动期间不断抛出未处理的 JavaScript 错误(参见 )
嗨,
这是我的测试页的样子:
蓝色区域是父页面,绿色区域是运行 ExtJS 应用程序的 IFrame(内部带有标签的简单视口)。
如果站点在触摸设备(IPad、Android 平板电脑等)上运行,则无法在 IFrame(绿色区域)上按 "wiping" 滚动页面.必须在蓝色区域擦拭才能滚动页面。
这在 ExtJS v4.2.1 中工作正常(见下面的链接)。
测试站点:
https://skaface.leo.uberspace.de/ScrollTest/Ext510/(未按预期工作,使用 ExtJS v5.1.1)
https://skaface.leo.uberspace.de/ScrollTest/Ext421/(按预期工作,代码相同但使用 ExtJS v4.2.1)
测试代码:
父网站(index.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body style="margin: 50px; background-color: blue;">
<iframe src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
</html>
IFrame (frame.html):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
<title>Test</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="https://extjs.cachefly.net/ext/gpl/5.1.0/packages/ext-theme-neptune/build/resources/ext-theme-neptune-all-debug.css" />
<script type="text/javascript" src="https://extjs.cachefly.net/ext/gpl/5.1.0/build/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.onReady(function() {
Ext.create('Ext.container.Viewport', {
style: { 'background-color': 'yellowgreen' },
layout: 'fit',
items: [{
xtype: 'label',
text: 'Ext version: ' + Ext.versions.extjs.version,
margin: 16
}]
});
});
</script>
</head>
<body>
</body>
</html>
我真的很感激这个问题的解决方法,因为它实际上使我的网站在移动设备上毫无用处,即使它们在 ExtJS 4.2.1 上工作得很好。
谢谢并致以最诚挚的问候
Ps.: 我已经发布了一个错误报告 in the sencha forums,但是因为我在那里没有得到任何帮助直到知道,所以我也在 Whosebug 上试试运气.. .
行为很奇怪,我在使用niceScroll插件之前已经看到它,许多其他插件也与iframe
有同样的问题,无论如何检查this workaround
我已经使用 Hammer.js jQuery 插件来检测您 iframe
上的触摸手势,如果您发现任何关于灵敏度的问题(如我不知道你在寻找什么约束),你可以调整 hammer.js 在他们的 repo 上找到的选项(比如 pan threshold ,pointers ..etc )
并且代码非常简单:
<body id="mainbody" style="margin: 50px; background-color: blue;">
<iframe id="myframe" src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
<script>
var myBody
$('iframe').load(function(){
myBody=$(this).contents().find("body");
myBody.css({"height":"100%","overflow":"hidden"}).hammer({threshold:1}).bind("pan", myPanHandler);
});
function myPanHandler(ev)
{
$("#mainbody").scrollTop($("#mainbody").scrollTop()-ev.gesture.deltaY)
console.log(($("#mainbody").scrollTop()-ev.gesture.deltaY*0.5)+".."+$("#mainbody").scrollTop())
}
</script>
在框架内部进行了大量挖掘之后,我终于找到了一个至少对我有用的解决方案,它包含 2 个步骤:
1) ExtJS 将视口的 CSS 属性 touch-action
(IFrame 的基本 html 元素)及其主体设置为值 none
.
我只是用值 auto
:
.x-viewport, .x-viewport > .x-body {
touch-action: auto;
}
2) class Ext.container.Viewport
在其创建回调中调用 Ext.plugin.Viewport.decorate(this);
,这会向视口本身的 touchmove
事件添加一个侦听器。
侦听器所做的一切都是调用事件的 preventDefault();
,这就是滚动在父页面或 IFrame 本身上不再起作用的原因。
我的修复只是从 touchmove
事件处理程序中删除了 preventDefault()
而不是 returns false
让事件在浏览器链中冒泡:
Ext.define('Cbn.overrides.container.Viewport', {
override: 'Ext.container.Viewport'
}, function() {
Ext.override(this, {
onRender: function() {
this.mon(Ext.getDoc(), {
touchmove: function(e) {
// e.preventDefault(); // Original ExtJS code
return false;
},
translate: false,
delegated: false
});
this.callParent(arguments);
}
});
});
我不太确定这 2 个修复是否有任何负面影响,但到目前为止它们似乎对我有用。
我确实意识到的一件事是,在 IFrame-App 中使用带有配置 scrollable: true
的组件仍然会产生问题,但由于我几乎可以在任何地方避免这种情况,所以到目前为止对我来说这不是问题...
工作测试站点:https://skaface.leo.uberspace.de/ScrollTest/Ext510_fixed/
编辑:
稍微调整了解决方案,以免在触摸滚动期间不断抛出未处理的 JavaScript 错误(参见