纸张页眉面板内的垂直滚动行为不当
Vertical scroll inside paper-header-panel behaving inappropriately
我目前正在处理一个页面。我使用了聚合物的纸抽屉面板和纸头面板组合。
基本上有两个容器,内层容器需要水平滚动,外层容器需要垂直滚动。当我没有使用 paper-header-panel 时,该行为是适当的。你可以看到演示here。如果您在移动浏览器(chrome 或 others/haven 未使用 Safari 进行检查)或在 chrome 中的移动模拟器上打开此站点,我可以水平和垂直滚动。这是我预期的行为。
但是,当我添加 paper-header-panel(自定义元素 <app-layout>
的一部分)时,我可以水平滚动(在移动浏览器中),但是当我触摸水平滚动 div 并尝试像以前的情况一样垂直滚动它,垂直滚动不再起作用。演示存在 here。
app-layout
元素的相关源代码如下。
html -
<dom-module id="app-layout">
<link rel="import" type="css" href="app-layout.css">
<template>
<paper-drawer-panel id="drawerPanel" responsive-width="1024px" drawer-width="280px">
<paper-header-panel class="list-panel" drawer>
<!-- List Toolbar -->
<div class="paper-header has-shadow layout horizontal center" id="navheader">
</div>
<!-- Menu -->
<div class="left-drawer">
<paper-menu class="list" selected="0" on-iron-activate="_listTap">
<template is="dom-repeat" items="{{menus}}">
<paper-item role="menu"><iron-icon class="menuitems" icon$={{item.icon}}></iron-icon><span>{{item.label}}</span></paper-item>
</template>
</paper-menu>
</div>
</paper-header-panel>
<paper-header-panel class$="{{positionClass}}" main mode="{{mainMode}}">
<!-- Main Toolbar -->
<paper-toolbar class$="{{toolbarClass}}">
<paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
<div style="width:60px" id="app-image"><iron-image style="width:40px; height:40px; background-color: lightgray;"
sizing="contain" preload fade src= "/images/app-icon-110.png"></iron-image></div>
<div hidden$="{{_isMobile}}" class="flex">{{label}}</div>
<div class="flex"></div>
<paper-icon-button icon="search" on-tap="toggleSearch"></paper-icon-button>
<paper-icon-button icon="more-vert"></paper-icon-button>
</paper-toolbar>
<div class="content">
<paper-material>
<content select=".main-content"></content>
</paper-material>
</div>
</paper-header-panel>
</paper-drawer-panel>
</template>
</dom-module>
CSS -
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
:host {
width: 100%;
height: 100%;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
display: block;
}
#drawerPanel {
--paper-drawer-panel-left-drawer-container: {
background-color: #eee;
};
}
paper-header-panel {
background-color: #eee;
}
paper-toolbar {
background-color: #00bcd4;
}
.left-drawer {
background-color: #eee;
}
paper-header-panel .content {
height: 100%;
}
paper-header-panel[mode=cover] .content {
padding: 0 90px 0 0px;
height: 100%;
}
paper-header-panel {
--paper-header-panel-cover-container: {
height: 100%;
left: 90px;
};
}
paper-header-panel[mode=cover] paper-toolbar {
color: #fff;
font-size: 20px;
font-weight: 400;
padding-right: 16px;
}
.paper-header-panel paper-toolbar #app-image {
margin-left: -15px;
}
paper-material {
overflow-y: auto;
height: auto;
background-color: #fff;
z-index: 1;
}
paper-header-panel[mode=cover] paper-material {
max-width: 1024px;
margin: 64px auto;
}
根据我们的评论,
作为替代解决方案,在您找到问题之前,您可以使用 Iscroll 5 测试卡片的水平滚动,看看它在应用程序中是否正常工作。
我在我的应用程序中使用了 Iscroll 5,它使用水平和垂直滚动条以及 100 个项目并且在 Polymer 上速度很快。到目前为止,我还没有遇到任何性能问题,尽管我关闭了 iscroll 选项中的反弹,例如 ,bounce: false
以获得额外的性能提升
如果您有卡片的点击事件,请将 ,click:true
添加到 Iscroll 选项
在此处滚动 5 指南 http://iscrolljs.com/
当用户在那里水平滚动以节省资源时,该演示会为任何行创建 Iscroll,我评论中的原始演示是针对内置滑动检测的 JQM 框架。
在 Polymer 版本 0.5 中,它内置了 Touch 功能,尚不确定版本 1,但我从未使用过 https://www.polymer-project.org/0.5/docs/polymer/touch.html
对于 Polymer,我创建了另一个使用 Javascript 触摸事件来检测水平移动的演示,因此您不需要任何其他触摸手势插件来添加到应用程序中
Demo 我为代码初始化设置了 5 秒延迟。几乎所有代码都用于处理 Touch。 function slide(x) {
里面是Iscroll代码,大约10行
http://codepen.io/anon/pen/pJRmLo
代码
var slides = 17; //how many items in a row
var totalwidth = slides * 80; //times that by the width of each item in a row
$(".scroller").css("width", totalwidth+"px"); //set the total width of the horizontal wrapper
// touch function
var startPos;
var handlingTouch = false;
var itemis;
setTimeout(function() {
document.addEventListener('touchstart', function(e) {
// Is this the first finger going down?
if (e.touches.length == e.changedTouches.length) {
startPos = {
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
}
});
document.addEventListener('touchmove', function(e) {
// If this is the first movement event in a sequence:
if (startPos) {
// Is the axis of movement horizontal?
if (Math.abs(e.changedTouches[0].clientX - startPos.x) > Math.abs(e.changedTouches[0].clientY - startPos.y)) {
handlingTouch = true;
e.preventDefault();
onSwipeStart(e);
}
startPos = undefined;
} else if (handlingTouch) {
e.preventDefault();
onSwipeMove(e);
}
});
document.addEventListener('touchend', function(e) {
if (handlingTouch && e.touches.length == 0) {
e.preventDefault();
onSwipeEnd(e);
handlingTouch = false;
}
});
function slide(x) {
var cclass = $(itemis).attr("class")
var ccclass = "."+cclass;
var newis = $(itemis).attr("data-id");
if (newis != "running") {
var cclass = new IScroll(ccclass, {
eventPassthrough: true,
scrollX: true,
scrollY: false,
preventDefault: false
});
cclass.scrollBy(-50, 0, 500);
//control here how many pixels to auto scroll uppon activating the scroll eg -50px
$(itemis).attr("data-id","running")
}
}
var swipeOrigin, x, itempos;
function onSwipeStart(e) {
// find what element is been touched. In your case it may be closest("swElement") but you need to test
itemis = $(e.target).closest("div");
// when touching over an element get its target, in this case the closest div of the row
swipeOrigin = e.touches[0].clientX;
}
function onSwipeMove(e) {
x = e.touches[0].clientX - swipeOrigin;
// slide(x);
}
function onSwipeEnd(e) {
//On Touch End if x (distance traveled to the right) is greater than +35 pixels then slide element +100 pixels.
if (x > 35) {
slide(0);
}
else {
slide(0);
}
}
}, 5000);
以上触摸功能我最初用于transforming/moving列表项,类似于Gmail App,用于JQM和Polymer列表项。在 Iscroll 并没有真正以这种方式使用的情况下,可以水平地用于任何东西,但它基本上说如果你触摸水平移动到一行上激活该行的 Iscroll
查看我在 Link 中的演示以了解该功能的替代用法。
出现此问题是因为在移动设备上,垂直滚动处于活动状态时水平滚动被禁用,反之亦然。我现在已经使用 Tasos 建议使用 iScroll 解决了这个问题。我使用聚合物的异步函数来延迟初始化滚动条。这是我用作聚合物就绪的一部分的代码。
<script>
Polymer ({
...
...
ready:function() {
this.async(function() {
this.setScroll();
}, null, 300);
},
setScroll: function() {
var nodeList = document.querySelectorAll('.wrapper');
if(nodeList.length == 0) {
this.async(function() { this.setScroll(); }, null, 300);
}
for (var i=0; i<nodeList.length; i++) {
// this.setScrollDirection ('y', nodeList[i]);
nodeList[i].id = 'wrapper'+i;
var myScroll = new IScroll('#'+nodeList[i].id, { eventPassthrough: true, scrollX: true, scrollY: false, preventDefault: false });
// myScroll.scrollBy(-50, 0, 500);
}
}
})();
</script>
我还能够使用文档中提到的 Polymers 轨迹手势。
Listening for certain gestures controls the scrolling direction for
touch input. For example, nodes with a listener for the track event
will prevent scrolling by default. Elements can be override scroll
direction with this.setScrollDirection(direction, node), where
direction is one of 'x', 'y', 'none', or 'all', and node defaults to
this.
state - a string indicating the tracking state:
start - fired when tracking is first detected (finger/button down and moved past a pre-set distance threshold)
track - fired while tracking
end - fired when tracking ends
x - clientX coordinate for event
y - clientY coordinate for event
dx - change in pixels horizontally since the first track event
dy - change in pixels vertically since the first track event
ddx - change in pixels horizontally since last track event
ddy - change in pixels vertically since last track event
hover() - a function that may be called to determine the element currently being hovered
我已经使用 (dx > dy) 了解它是水平滑动还是垂直滑动,然后根据情况具体启用水平和垂直滑动。这行得通,但我喜欢弹跳和 iScroll 提供的其他选项,除了它仅有的 4KB 压缩和 gzip 压缩。所以,我决定使用 iScroll。
[注意:jQuery不需要使用iScroll。是一个独立的脚本]
我目前正在处理一个页面。我使用了聚合物的纸抽屉面板和纸头面板组合。
基本上有两个容器,内层容器需要水平滚动,外层容器需要垂直滚动。当我没有使用 paper-header-panel 时,该行为是适当的。你可以看到演示here。如果您在移动浏览器(chrome 或 others/haven 未使用 Safari 进行检查)或在 chrome 中的移动模拟器上打开此站点,我可以水平和垂直滚动。这是我预期的行为。
但是,当我添加 paper-header-panel(自定义元素 <app-layout>
的一部分)时,我可以水平滚动(在移动浏览器中),但是当我触摸水平滚动 div 并尝试像以前的情况一样垂直滚动它,垂直滚动不再起作用。演示存在 here。
app-layout
元素的相关源代码如下。
html -
<dom-module id="app-layout">
<link rel="import" type="css" href="app-layout.css">
<template>
<paper-drawer-panel id="drawerPanel" responsive-width="1024px" drawer-width="280px">
<paper-header-panel class="list-panel" drawer>
<!-- List Toolbar -->
<div class="paper-header has-shadow layout horizontal center" id="navheader">
</div>
<!-- Menu -->
<div class="left-drawer">
<paper-menu class="list" selected="0" on-iron-activate="_listTap">
<template is="dom-repeat" items="{{menus}}">
<paper-item role="menu"><iron-icon class="menuitems" icon$={{item.icon}}></iron-icon><span>{{item.label}}</span></paper-item>
</template>
</paper-menu>
</div>
</paper-header-panel>
<paper-header-panel class$="{{positionClass}}" main mode="{{mainMode}}">
<!-- Main Toolbar -->
<paper-toolbar class$="{{toolbarClass}}">
<paper-icon-button icon="menu" paper-drawer-toggle></paper-icon-button>
<div style="width:60px" id="app-image"><iron-image style="width:40px; height:40px; background-color: lightgray;"
sizing="contain" preload fade src= "/images/app-icon-110.png"></iron-image></div>
<div hidden$="{{_isMobile}}" class="flex">{{label}}</div>
<div class="flex"></div>
<paper-icon-button icon="search" on-tap="toggleSearch"></paper-icon-button>
<paper-icon-button icon="more-vert"></paper-icon-button>
</paper-toolbar>
<div class="content">
<paper-material>
<content select=".main-content"></content>
</paper-material>
</div>
</paper-header-panel>
</paper-drawer-panel>
</template>
</dom-module>
CSS -
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
:host {
width: 100%;
height: 100%;
-moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
display: block;
}
#drawerPanel {
--paper-drawer-panel-left-drawer-container: {
background-color: #eee;
};
}
paper-header-panel {
background-color: #eee;
}
paper-toolbar {
background-color: #00bcd4;
}
.left-drawer {
background-color: #eee;
}
paper-header-panel .content {
height: 100%;
}
paper-header-panel[mode=cover] .content {
padding: 0 90px 0 0px;
height: 100%;
}
paper-header-panel {
--paper-header-panel-cover-container: {
height: 100%;
left: 90px;
};
}
paper-header-panel[mode=cover] paper-toolbar {
color: #fff;
font-size: 20px;
font-weight: 400;
padding-right: 16px;
}
.paper-header-panel paper-toolbar #app-image {
margin-left: -15px;
}
paper-material {
overflow-y: auto;
height: auto;
background-color: #fff;
z-index: 1;
}
paper-header-panel[mode=cover] paper-material {
max-width: 1024px;
margin: 64px auto;
}
根据我们的评论,
作为替代解决方案,在您找到问题之前,您可以使用 Iscroll 5 测试卡片的水平滚动,看看它在应用程序中是否正常工作。
我在我的应用程序中使用了 Iscroll 5,它使用水平和垂直滚动条以及 100 个项目并且在 Polymer 上速度很快。到目前为止,我还没有遇到任何性能问题,尽管我关闭了 iscroll 选项中的反弹,例如 ,bounce: false
以获得额外的性能提升
如果您有卡片的点击事件,请将 ,click:true
添加到 Iscroll 选项
在此处滚动 5 指南 http://iscrolljs.com/
当用户在那里水平滚动以节省资源时,该演示会为任何行创建 Iscroll,我评论中的原始演示是针对内置滑动检测的 JQM 框架。
在 Polymer 版本 0.5 中,它内置了 Touch 功能,尚不确定版本 1,但我从未使用过 https://www.polymer-project.org/0.5/docs/polymer/touch.html
对于 Polymer,我创建了另一个使用 Javascript 触摸事件来检测水平移动的演示,因此您不需要任何其他触摸手势插件来添加到应用程序中
Demo 我为代码初始化设置了 5 秒延迟。几乎所有代码都用于处理 Touch。 function slide(x) {
里面是Iscroll代码,大约10行
http://codepen.io/anon/pen/pJRmLo
代码
var slides = 17; //how many items in a row
var totalwidth = slides * 80; //times that by the width of each item in a row
$(".scroller").css("width", totalwidth+"px"); //set the total width of the horizontal wrapper
// touch function
var startPos;
var handlingTouch = false;
var itemis;
setTimeout(function() {
document.addEventListener('touchstart', function(e) {
// Is this the first finger going down?
if (e.touches.length == e.changedTouches.length) {
startPos = {
x: e.touches[0].clientX,
y: e.touches[0].clientY
};
}
});
document.addEventListener('touchmove', function(e) {
// If this is the first movement event in a sequence:
if (startPos) {
// Is the axis of movement horizontal?
if (Math.abs(e.changedTouches[0].clientX - startPos.x) > Math.abs(e.changedTouches[0].clientY - startPos.y)) {
handlingTouch = true;
e.preventDefault();
onSwipeStart(e);
}
startPos = undefined;
} else if (handlingTouch) {
e.preventDefault();
onSwipeMove(e);
}
});
document.addEventListener('touchend', function(e) {
if (handlingTouch && e.touches.length == 0) {
e.preventDefault();
onSwipeEnd(e);
handlingTouch = false;
}
});
function slide(x) {
var cclass = $(itemis).attr("class")
var ccclass = "."+cclass;
var newis = $(itemis).attr("data-id");
if (newis != "running") {
var cclass = new IScroll(ccclass, {
eventPassthrough: true,
scrollX: true,
scrollY: false,
preventDefault: false
});
cclass.scrollBy(-50, 0, 500);
//control here how many pixels to auto scroll uppon activating the scroll eg -50px
$(itemis).attr("data-id","running")
}
}
var swipeOrigin, x, itempos;
function onSwipeStart(e) {
// find what element is been touched. In your case it may be closest("swElement") but you need to test
itemis = $(e.target).closest("div");
// when touching over an element get its target, in this case the closest div of the row
swipeOrigin = e.touches[0].clientX;
}
function onSwipeMove(e) {
x = e.touches[0].clientX - swipeOrigin;
// slide(x);
}
function onSwipeEnd(e) {
//On Touch End if x (distance traveled to the right) is greater than +35 pixels then slide element +100 pixels.
if (x > 35) {
slide(0);
}
else {
slide(0);
}
}
}, 5000);
以上触摸功能我最初用于transforming/moving列表项,类似于Gmail App,用于JQM和Polymer列表项。在 Iscroll 并没有真正以这种方式使用的情况下,可以水平地用于任何东西,但它基本上说如果你触摸水平移动到一行上激活该行的 Iscroll
查看我在 Link 中的演示以了解该功能的替代用法。
出现此问题是因为在移动设备上,垂直滚动处于活动状态时水平滚动被禁用,反之亦然。我现在已经使用 Tasos 建议使用 iScroll 解决了这个问题。我使用聚合物的异步函数来延迟初始化滚动条。这是我用作聚合物就绪的一部分的代码。
<script>
Polymer ({
...
...
ready:function() {
this.async(function() {
this.setScroll();
}, null, 300);
},
setScroll: function() {
var nodeList = document.querySelectorAll('.wrapper');
if(nodeList.length == 0) {
this.async(function() { this.setScroll(); }, null, 300);
}
for (var i=0; i<nodeList.length; i++) {
// this.setScrollDirection ('y', nodeList[i]);
nodeList[i].id = 'wrapper'+i;
var myScroll = new IScroll('#'+nodeList[i].id, { eventPassthrough: true, scrollX: true, scrollY: false, preventDefault: false });
// myScroll.scrollBy(-50, 0, 500);
}
}
})();
</script>
我还能够使用文档中提到的 Polymers 轨迹手势。
Listening for certain gestures controls the scrolling direction for touch input. For example, nodes with a listener for the track event will prevent scrolling by default. Elements can be override scroll direction with this.setScrollDirection(direction, node), where direction is one of 'x', 'y', 'none', or 'all', and node defaults to this.
state - a string indicating the tracking state:
start - fired when tracking is first detected (finger/button down and moved past a pre-set distance threshold)
track - fired while tracking
end - fired when tracking ends
x - clientX coordinate for event
y - clientY coordinate for event
dx - change in pixels horizontally since the first track event
dy - change in pixels vertically since the first track event
ddx - change in pixels horizontally since last track event
ddy - change in pixels vertically since last track event
hover() - a function that may be called to determine the element currently being hovered
我已经使用 (dx > dy) 了解它是水平滑动还是垂直滑动,然后根据情况具体启用水平和垂直滑动。这行得通,但我喜欢弹跳和 iScroll 提供的其他选项,除了它仅有的 4KB 压缩和 gzip 压缩。所以,我决定使用 iScroll。
[注意:jQuery不需要使用iScroll。是一个独立的脚本]