Fixed resistance for scrollView

This commit is contained in:
Max Lynch
2013-10-24 16:43:19 -05:00
parent 8508560455
commit 0536c03271
7 changed files with 67 additions and 57 deletions

42
dist/js/ionic.js vendored
View File

@ -2484,30 +2484,22 @@ window.ionic = {
(function(ionic) { (function(ionic) {
'use strict'; 'use strict';
/**
* The Scroll view is a container that suppoerts complex
* and customizable scroll behavior.
*
* This is a replacement for the buggy and shallow -webkit-overflow-scroll: touch.
* which is fine for web apps that want to have overflow scrolling containers,
* but HTML5 hybrid apps benefit from the same kind of scroll abstractions
* seen on iOS or Android.
*/
ionic.views.ScrollView = function(opts) { ionic.views.ScrollView = function(opts) {
var _this = this; var _this = this;
// Extend the options with our defaults // Extend the options with our defaults
ionic.Utils.extend(opts, { ionic.Utils.extend(opts, {
decelerationRate: ionic.views.Scroll.prototype.DECEL_RATE_NORMAL, decelerationRate: ionic.views.ScrollView.prototype.DECEL_RATE_NORMAL,
dragThresholdY: 10, dragThresholdY: 10,
resistance: 2, resistance: 2,
scrollEventName: 'momentumScrolled', scrollEventName: 'momentumScrolled',
intertialEventInterval: 50, intertialEventInterval: 50
showScrollBar: true
}); });
ionic.Utils.extend(this, opts); ionic.Utils.extend(this, opts);
this.el = opts.el;
// Listen for drag and release events // Listen for drag and release events
ionic.onGesture('drag', function(e) { ionic.onGesture('drag', function(e) {
_this._handleDrag(e); _this._handleDrag(e);
@ -2593,6 +2585,8 @@ window.ionic = {
var scrollTop = parseFloat(this.el.style.webkitTransform.replace('translate3d(', '').split(',')[1]) || 0; var scrollTop = parseFloat(this.el.style.webkitTransform.replace('translate3d(', '').split(',')[1]) || 0;
this._drag = { this._drag = {
y: scrollTop,
pointY: e.gesture.touches[0].pageY,
startY: scrollTop, startY: scrollTop,
resist: 1, resist: 1,
startTime: +(new Date) startTime: +(new Date)
@ -2622,25 +2616,37 @@ window.ionic = {
// Stop any default events during the drag // Stop any default events during the drag
e.preventDefault(); e.preventDefault();
var py = e.gesture.touches[0].pageY;
var deltaY = py - _this._drag.pointY;
console.log("Delta y", deltaY);
_this._drag.pointY = py;
// Check if we should start dragging. Check if we've dragged past the threshold. // Check if we should start dragging. Check if we've dragged past the threshold.
if(!_this._isDragging && (Math.abs(e.gesture.deltaY) > _this.dragThresholdY)) { if(!_this._isDragging && (Math.abs(e.gesture.deltaY) > _this.dragThresholdY)) {
_this._isDragging = true; _this._isDragging = true;
} }
if(_this._isDragging) { if(_this._isDragging) {
// We are dragging, grab the current content height
// and the height of the parent container
var totalHeight = _this.el.offsetHeight; var totalHeight = _this.el.offsetHeight;
var parentHeight = _this.el.parentNode.offsetHeight; var parentHeight = _this.el.parentNode.offsetHeight;
var newY = _this._drag.startY + e.gesture.deltaY; // Calculate the new Y point for the container
var newY = _this._drag.y + deltaY;
// Check if the dragging is beyond the bottom or top // Check if the dragging is beyond the bottom or top
if(newY > 0 || (-newY + parentHeight) > totalHeight) { if(newY > 0 || (-newY + parentHeight) > totalHeight) {
// Rubber band // Rubber band
newY = newY + e.gesture.deltaY / (-_this.resistance); newY = _this._drag.y + deltaY / 3;//(-_this.resistance);
} }
// Update the new translated Y point of the container // Update the new translated Y point of the container
_this.el.style.webkitTransform = 'translate3d(0,' + newY + 'px, 0)'; _this.el.style.webkitTransform = 'translate3d(0,' + newY + 'px, 0)';
_this._drag.y = newY;
ionic.trigger(_this.scrollEventName, { ionic.trigger(_this.scrollEventName, {
target: _this.el, target: _this.el,
scrollTop: -newY scrollTop: -newY
@ -2725,7 +2731,10 @@ window.ionic = {
* Adapted from the great iScroll for Ionic. iScroll is licensed under MIT just like Ionic. * Adapted from the great iScroll for Ionic. iScroll is licensed under MIT just like Ionic.
* *
* Think of ionic.views.Scroll like a Javascript version of UIScrollView or any * Think of ionic.views.Scroll like a Javascript version of UIScrollView or any
* scroll container in any UI library. * scroll container in any UI library. You could just use -webkit-overflow-scrolling: touch,
* but you lose control over scroll behavior that native developers have with things
* like UIScrollView, and you don't get events after the finger stops touching the
* device (after a flick, for example)
* *
* iScroll v5.0.5 ~ (c) 2008-2013 Matteo Spinelli ~ http://cubiq.org/license * iScroll v5.0.5 ~ (c) 2008-2013 Matteo Spinelli ~ http://cubiq.org/license
*/ */
@ -2739,6 +2748,9 @@ var rAF = window.requestAnimationFrame ||
window.msRequestAnimationFrame || window.msRequestAnimationFrame ||
function (callback) { window.setTimeout(callback, 1000 / 60); }; function (callback) { window.setTimeout(callback, 1000 / 60); };
/**
* Utilities for calculating momentum, etc.
*/
var utils = (function () { var utils = (function () {
var me = {}; var me = {};

View File

@ -1,30 +1,22 @@
(function(ionic) { (function(ionic) {
'use strict'; 'use strict';
/**
* The Scroll view is a container that suppoerts complex
* and customizable scroll behavior.
*
* This is a replacement for the buggy and shallow -webkit-overflow-scroll: touch.
* which is fine for web apps that want to have overflow scrolling containers,
* but HTML5 hybrid apps benefit from the same kind of scroll abstractions
* seen on iOS or Android.
*/
ionic.views.ScrollView = function(opts) { ionic.views.ScrollView = function(opts) {
var _this = this; var _this = this;
// Extend the options with our defaults // Extend the options with our defaults
ionic.Utils.extend(opts, { ionic.Utils.extend(opts, {
decelerationRate: ionic.views.Scroll.prototype.DECEL_RATE_NORMAL, decelerationRate: ionic.views.ScrollView.prototype.DECEL_RATE_NORMAL,
dragThresholdY: 10, dragThresholdY: 10,
resistance: 2, resistance: 2,
scrollEventName: 'momentumScrolled', scrollEventName: 'momentumScrolled',
intertialEventInterval: 50, intertialEventInterval: 50
showScrollBar: true
}); });
ionic.Utils.extend(this, opts); ionic.Utils.extend(this, opts);
this.el = opts.el;
// Listen for drag and release events // Listen for drag and release events
ionic.onGesture('drag', function(e) { ionic.onGesture('drag', function(e) {
_this._handleDrag(e); _this._handleDrag(e);
@ -110,6 +102,8 @@
var scrollTop = parseFloat(this.el.style.webkitTransform.replace('translate3d(', '').split(',')[1]) || 0; var scrollTop = parseFloat(this.el.style.webkitTransform.replace('translate3d(', '').split(',')[1]) || 0;
this._drag = { this._drag = {
y: scrollTop,
pointY: e.gesture.touches[0].pageY,
startY: scrollTop, startY: scrollTop,
resist: 1, resist: 1,
startTime: +(new Date) startTime: +(new Date)
@ -139,25 +133,37 @@
// Stop any default events during the drag // Stop any default events during the drag
e.preventDefault(); e.preventDefault();
var py = e.gesture.touches[0].pageY;
var deltaY = py - _this._drag.pointY;
console.log("Delta y", deltaY);
_this._drag.pointY = py;
// Check if we should start dragging. Check if we've dragged past the threshold. // Check if we should start dragging. Check if we've dragged past the threshold.
if(!_this._isDragging && (Math.abs(e.gesture.deltaY) > _this.dragThresholdY)) { if(!_this._isDragging && (Math.abs(e.gesture.deltaY) > _this.dragThresholdY)) {
_this._isDragging = true; _this._isDragging = true;
} }
if(_this._isDragging) { if(_this._isDragging) {
// We are dragging, grab the current content height
// and the height of the parent container
var totalHeight = _this.el.offsetHeight; var totalHeight = _this.el.offsetHeight;
var parentHeight = _this.el.parentNode.offsetHeight; var parentHeight = _this.el.parentNode.offsetHeight;
var newY = _this._drag.startY + e.gesture.deltaY; // Calculate the new Y point for the container
var newY = _this._drag.y + deltaY;
// Check if the dragging is beyond the bottom or top // Check if the dragging is beyond the bottom or top
if(newY > 0 || (-newY + parentHeight) > totalHeight) { if(newY > 0 || (-newY + parentHeight) > totalHeight) {
// Rubber band // Rubber band
newY = newY + e.gesture.deltaY / (-_this.resistance); newY = _this._drag.y + deltaY / 3;//(-_this.resistance);
} }
// Update the new translated Y point of the container // Update the new translated Y point of the container
_this.el.style.webkitTransform = 'translate3d(0,' + newY + 'px, 0)'; _this.el.style.webkitTransform = 'translate3d(0,' + newY + 'px, 0)';
_this._drag.y = newY;
ionic.trigger(_this.scrollEventName, { ionic.trigger(_this.scrollEventName, {
target: _this.el, target: _this.el,
scrollTop: -newY scrollTop: -newY

View File

@ -2,7 +2,10 @@
* Adapted from the great iScroll for Ionic. iScroll is licensed under MIT just like Ionic. * Adapted from the great iScroll for Ionic. iScroll is licensed under MIT just like Ionic.
* *
* Think of ionic.views.Scroll like a Javascript version of UIScrollView or any * Think of ionic.views.Scroll like a Javascript version of UIScrollView or any
* scroll container in any UI library. * scroll container in any UI library. You could just use -webkit-overflow-scrolling: touch,
* but you lose control over scroll behavior that native developers have with things
* like UIScrollView, and you don't get events after the finger stops touching the
* device (after a flick, for example)
* *
* iScroll v5.0.5 ~ (c) 2008-2013 Matteo Spinelli ~ http://cubiq.org/license * iScroll v5.0.5 ~ (c) 2008-2013 Matteo Spinelli ~ http://cubiq.org/license
*/ */
@ -16,6 +19,9 @@ var rAF = window.requestAnimationFrame ||
window.msRequestAnimationFrame || window.msRequestAnimationFrame ||
function (callback) { window.setTimeout(callback, 1000 / 60); }; function (callback) { window.setTimeout(callback, 1000 / 60); };
/**
* Utilities for calculating momentum, etc.
*/
var utils = (function () { var utils = (function () {
var me = {}; var me = {};

View File

@ -18,7 +18,7 @@ angular.module('ionic.weather', ['ionic.weather.services', 'ionic.weather.direct
$scope.getActiveBackgroundImage = function() { $scope.getActiveBackgroundImage = function() {
if($scope.activeBgImage) { if($scope.activeBgImage) {
var item = $scope.activeBgImage; var item = $scope.activeBgImage;
var url = "http://farm"+ item.farm +".static.flickr.com/"+ item.server +"/"+ item.id +"_"+ item.secret +"_m.jpg"; var url = "http://farm"+ item.farm +".static.flickr.com/"+ item.server +"/"+ item.id +"_"+ item.secret +"_z.jpg";
return { return {
'background-image': 'url(' + url + ')' 'background-image': 'url(' + url + ')'
}; };
@ -62,7 +62,7 @@ angular.module('ionic.weather', ['ionic.weather.services', 'ionic.weather.direct
if($scope.bgImages) { if($scope.bgImages) {
$scope.activeBgImage = $scope.bgImages[$scope.activeBgImageIndex++ % $scope.bgImages.length]; $scope.activeBgImage = $scope.bgImages[$scope.activeBgImageIndex++ % $scope.bgImages.length];
} }
$timeout(cycle, 10000); //$timeout(cycle, 10000);
}); });
}; };

View File

@ -47,7 +47,7 @@
var bgImage = document.getElementById('bg-image'); var bgImage = document.getElementById('bg-image');
var header = document.getElementById('header'); var header = document.getElementById('header');
var scroll = new ionic.views.Scroll({ var scroll = new ionic.views.ScrollView({
el: s, el: s,
decelerationRate: 0.87, decelerationRate: 0.87,
inertialEventInterval: 100 inertialEventInterval: 100
@ -67,7 +67,7 @@
var per = 1 - (diff / 600); var per = 1 - (diff / 600);
brightness = Math.max(0.7, per); brightness = Math.max(0.7, per);
} }
bgImage.style.webkitFilter = 'brightness(' + brightness + ')'; //bgImage.style.webkitFilter = 'brightness(' + brightness + ')';
}); });
}); });
</script> </script>

View File

@ -1,5 +1,7 @@
body { body {
} }
#scroller {
}
#bg-image { #bg-image {
position: fixed; position: fixed;
width: 120%; width: 120%;

View File

@ -14,20 +14,6 @@
.list-item { .list-item {
padding: 10px; padding: 10px;
} }
#wrapper {
position:absolute; z-index:1;
top:0px; bottom:0px; left:0;
width:100%;
background:#aaa;
overflow:hidden;
}
#scroller {
position:absolute; z-index:1;
/* -webkit-touch-callout:none;*/
-webkit-tap-highlight-color:rgba(0,0,0,0);
width:100%;
padding:0;
}
</style> </style>
</head> </head>
<body> <body>
@ -37,28 +23,26 @@
<h1 class="title">Scroll Me</h1> <h1 class="title">Scroll Me</h1>
<a href="#" class="button button-danger button-clear">Delete</a> <a href="#" class="button button-danger button-clear">Delete</a>
</div> </div>
<div id="wrapper">
<div id="scroller" class="scroll" style="margin-top:44px"> <div id="scroller" class="scroll" style="margin-top:44px">
<!--<div id="filler" style="height: 1400px; background: url('tree_bark.png') repeat;"></div>-->
<ul class="list"> <ul class="list">
</ul> </ul>
</div> </div>
</div>
</section> </section>
<script src="../dist/js/ionic.js"></script> <script src="../dist/js/ionic.js"></script>
<script> <script>
var s = document.getElementById('wrapper'); var s = document.getElementById('scroller');
for(var i = 0; i < 100; i++) { for(var i = 0; i < 100; i++) {
var li = document.createElement('li'); var li = document.createElement('li');
li.className = 'list-item'; li.className = 'list-item';
li.innerHTML = 'Item ' + i; li.innerHTML = 'Item ' + i;
s.firstElementChild.children[0].appendChild(li); s.firstElementChild.appendChild(li);
} }
var scroll = new ionic.views.Scroll({ var scroll = new ionic.views.ScrollView({
el: s el: s
}); });
</script> </script>
</body> </body>
</html> </html>