触摸带有快照和奇数项的幻灯片



所以我必须实现这个相当简单的触摸滑块,它的主要功能必须是从一个滑块捕捉到另一个滑块,我不知道如何做的一件事是捕捉情侣,但当我有奇数个项目时会发生什么?发生这种情况:http://prntscr.com/2j86ck我只剩下一个空位。

我想实现的是:在最后一个项目上,滑动应该理解前面只有一个项目,并在一半的距离上滑动/捕捉,这样网页视图上就不会留下空白。

我使用了flipsnap.js,但在这一点上我陷入了困境,因为我不是真正的javascript专家,插件也不打算以这种方式工作。

这是一把小提琴:http://jsfiddle.net/omegaiori/mPCm8/1/

我试着想出一种css方法来解决这个问题,但一无所获,所以它主要是javascript的东西。这是一些代码:

/**
* flipsnap.js
*
* @version  0.6.1
* @url http://pxgrid.github.com/js-flipsnap/
*
* Copyright 2011 PixelGrid, Inc.
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*/
(function (window, document, undefined) {
var div = document.createElement('div');
var prefix = ['webkit', 'moz', 'o', 'ms'];
var saveProp = {};
var support = Flipsnap.support = {};
var gestureStart = false;
support.transform3d = hasProp([
'perspectiveProperty',
'WebkitPerspective',
'MozPerspective',
'OPerspective',
'msPerspective']);
support.transform = hasProp([
'transformProperty',
'WebkitTransform',
'MozTransform',
'OTransform',
'msTransform']);
support.transition = hasProp([
'transitionProperty',
'WebkitTransitionProperty',
'MozTransitionProperty',
'OTransitionProperty',
'msTransitionProperty']);
support.addEventListener = 'addEventListener' in window;
support.mspointer = window.navigator.msPointerEnabled;
support.cssAnimation = (support.transform3d || support.transform) && support.transition;
var eventTypes = ['touch', 'mouse'];
var events = {
start: {
touch: 'touchstart',
mouse: 'mousedown'
},
move: {
touch: 'touchmove',
mouse: 'mousemove'
},
end: {
touch: 'touchend',
mouse: 'mouseup'
}
};
if (support.addEventListener) {
document.addEventListener('gesturestart', function () {
gestureStart = true;
});
document.addEventListener('gestureend', function () {
gestureStart = false;
});
}
function Flipsnap(element, opts) {
return (this instanceof Flipsnap) ? this.init(element, opts) : new Flipsnap(element, opts);
}
Flipsnap.prototype.init = function (element, opts) {
var self = this;
// set element
self.element = element;
if (typeof element === 'string') {
self.element = document.querySelector(element);
}
if (!self.element) {
throw new Error('element not found');
}
if (support.mspointer) {
self.element.style.msTouchAction = 'pan-y';
}
// set opts
opts = opts || {};
self.distance = opts.distance;
self.maxPoint = opts.maxPoint;
self.disableTouch = (opts.disableTouch === undefined) ? false : opts.disableTouch;
self.disable3d = (opts.disable3d === undefined) ? false : opts.disable3d;
self.transitionDuration = (opts.transitionDuration === undefined) ? '350ms' : opts.transitionDuration + 'ms';
// set property
self.currentPoint = 0;
self.currentX = 0;
self.animation = false;
self.use3d = support.transform3d;
if (self.disable3d === true) {
self.use3d = false;
}
// set default style
if (support.cssAnimation) {
self._setStyle({
transitionProperty: getCSSVal('transform'),
transitionTimingFunction: 'cubic-bezier(0,0,0.25,1)',
transitionDuration: '0ms',
transform: self._getTranslate(0)
});
} else {
self._setStyle({
position: 'relative',
left: '0px'
});
}
// initilize
self.refresh();
eventTypes.forEach(function (type) {
self.element.addEventListener(events.start[type], self, false);
});
return self;
};
Flipsnap.prototype.handleEvent = function (event) {
var self = this;
switch (event.type) {
case events.start.touch:
case events.start.mouse:
self._touchStart(event);
break;
case events.move.touch:
case events.move.mouse:
self._touchMove(event);
break;
case events.end.touch:
case events.end.mouse:
self._touchEnd(event);
break;
case 'click':
self._click(event);
break;
}
};
Flipsnap.prototype.refresh = function () {
var self = this;
// setting max point
self._maxPoint = (self.maxPoint === undefined) ? (function () {
var childNodes = self.element.childNodes,
itemLength = -1,
i = 0,
len = childNodes.length,
node;
for (; i < len; i++) {
node = childNodes[i];
if (node.nodeType === 1) {
itemLength++;
}
}
return itemLength;
})() : self.maxPoint;
// setting distance
if (self.distance === undefined) {
if (self._maxPoint < 0) {
self._distance = 0;
} else {
self._distance = self.element.scrollWidth / (self._maxPoint + 1);
}
} else {
self._distance = self.distance;
}
// setting maxX
self._maxX = -self._distance * self._maxPoint;
self.moveToPoint();
};
Flipsnap.prototype.hasNext = function () {
var self = this;
return self.currentPoint < self._maxPoint;
};
Flipsnap.prototype.hasPrev = function () {
var self = this;
return self.currentPoint > 0;
};
Flipsnap.prototype.toNext = function (transitionDuration) {
var self = this;
if (!self.hasNext()) {
return;
}
self.moveToPoint(self.currentPoint + 1, transitionDuration);
};
Flipsnap.prototype.toPrev = function (transitionDuration) {
var self = this;
if (!self.hasPrev()) {
return;
}
self.moveToPoint(self.currentPoint - 1, transitionDuration);
};
Flipsnap.prototype.moveToPoint = function (point, transitionDuration) {
var self = this;
transitionDuration = transitionDuration === undefined ? self.transitionDuration : transitionDuration + 'ms';
var beforePoint = self.currentPoint;
// not called from `refresh()`
if (point === undefined) {
point = self.currentPoint;
}
if (point < 0) {
self.currentPoint = 0;
} else if (point > self._maxPoint) {
self.currentPoint = self._maxPoint;
} else {
self.currentPoint = parseInt(point, 10);
}
if (support.cssAnimation) {
self._setStyle({
transitionDuration: transitionDuration
});
} else {
self.animation = true;
}
self._setX(-self.currentPoint * self._distance, transitionDuration);
if (beforePoint !== self.currentPoint) { // is move?
// `fsmoveend` is deprecated
// `fspointmove` is recommend.
self._triggerEvent('fsmoveend', true, false);
self._triggerEvent('fspointmove', true, false);
}
};
Flipsnap.prototype._setX = function (x, transitionDuration) {
var self = this;
self.currentX = x;
if (support.cssAnimation) {
self.element.style[saveProp.transform] = self._getTranslate(x);
} else {
if (self.animation) {
self._animate(x, transitionDuration || self.transitionDuration);
} else {
self.element.style.left = x + 'px';
}
}
};
Flipsnap.prototype._touchStart = function (event) {
var self = this;
if (self.disableTouch || self._eventType || gestureStart) {
return;
}
some(eventTypes, function (type) {
if (event.type === events.start[type]) {
self._eventType = type;
return true;
}
});
self.element.addEventListener(events.move[self._eventType], self, false);
document.addEventListener(events.end[self._eventType], self, false);
var tagName = event.target.tagName;
if (self._eventType === 'mouse' && tagName !== 'SELECT' && tagName !== 'INPUT' && tagName !== 'TEXTAREA' && tagName !== 'BUTTON') {
event.preventDefault();
}
if (support.cssAnimation) {
self._setStyle({
transitionDuration: '0ms'
});
} else {
self.animation = false;
}
self.scrolling = true;
self.moveReady = false;
self.startPageX = getPage(event, 'pageX');
self.startPageY = getPage(event, 'pageY');
self.basePageX = self.startPageX;
self.directionX = 0;
self.startTime = event.timeStamp;
self._triggerEvent('fstouchstart', true, false);
};
Flipsnap.prototype._touchMove = function (event) {
var self = this;
if (!self.scrolling || gestureStart) {
return;
}
var pageX = getPage(event, 'pageX'),
pageY = getPage(event, 'pageY'),
distX,
newX,
deltaX,
deltaY;
if (self.moveReady) {
event.preventDefault();
distX = pageX - self.basePageX;
newX = self.currentX + distX;
if (newX >= 0 || newX < self._maxX) {
newX = Math.round(self.currentX + distX / 3);
}
// When distX is 0, use one previous value.
// For android firefox. When touchend fired, touchmove also
// fired and distX is certainly set to 0. 
self.directionX = distX === 0 ? self.directionX : distX > 0 ? -1 : 1;
// if they prevent us then stop it
var isPrevent = !self._triggerEvent('fstouchmove', true, true, {
delta: distX,
direction: self.directionX
});
if (isPrevent) {
self._touchAfter({
moved: false,
originalPoint: self.currentPoint,
newPoint: self.currentPoint,
cancelled: true
});
} else {
self._setX(newX);
}
} else {
deltaX = Math.abs(pageX - self.startPageX);
deltaY = Math.abs(pageY - self.startPageY);
if (deltaX > 5) {
event.preventDefault();
self.moveReady = true;
self.element.addEventListener('click', self, true);
} else if (deltaY > 5) {
self.scrolling = false;
self._touchEnd();
}
}
self.basePageX = pageX;
};
Flipsnap.prototype._touchEnd = function (event) {
var self = this;
self.element.removeEventListener(events.move[self._eventType], self, false);
document.removeEventListener(events.end[self._eventType], self, false);
self._eventType = null;
if (!self.scrolling) {
return;
}
var newPoint = -self.currentX / self._distance;
newPoint = (self.directionX > 0) ? Math.ceil(newPoint) : (self.directionX < 0) ? Math.floor(newPoint) : Math.round(newPoint);
if (newPoint < 0) {
newPoint = 0;
} else if (newPoint > self._maxPoint) {
newPoint = self._maxPoint;
}
self._touchAfter({
moved: newPoint !== self.currentPoint,
originalPoint: self.currentPoint,
newPoint: newPoint,
cancelled: false
});
self.moveToPoint(newPoint);
};
Flipsnap.prototype._click = function (event) {
var self = this;
event.stopPropagation();
event.preventDefault();
};
Flipsnap.prototype._touchAfter = function (params) {
var self = this;
self.scrolling = false;
self.moveReady = false;
setTimeout(function () {
self.element.removeEventListener('click', self, true);
}, 200);
self._triggerEvent('fstouchend', true, false, params);
};
Flipsnap.prototype._setStyle = function (styles) {
var self = this;
var style = self.element.style;
for (var prop in styles) {
setStyle(style, prop, styles[prop]);
}
};
Flipsnap.prototype._animate = function (x, transitionDuration) {
var self = this;
var elem = self.element;
var begin = +new Date();
var from = parseInt(elem.style.left, 10);
var to = x;
var duration = parseInt(transitionDuration, 10);
var easing = function (time, duration) {
return -(time /= duration) * (time - 2);
};
var timer = setInterval(function () {
var time = new Date() - begin;
var pos, now;
if (time > duration) {
clearInterval(timer);
now = to;
} else {
pos = easing(time, duration);
now = pos * (to - from) + from;
}
elem.style.left = now + "px";
}, 10);
};
Flipsnap.prototype.destroy = function () {
var self = this;
eventTypes.forEach(function (type) {
self.element.removeEventListener(events.start[type], self, false);
});
};
Flipsnap.prototype._getTranslate = function (x) {
var self = this;
return self.use3d ? 'translate3d(' + x + 'px, 0, 0)' : 'translate(' + x + 'px, 0)';
};
Flipsnap.prototype._triggerEvent = function (type, bubbles, cancelable, data) {
var self = this;
var ev = document.createEvent('Event');
ev.initEvent(type, bubbles, cancelable);
if (data) {
for (var d in data) {
if (data.hasOwnProperty(d)) {
ev[d] = data[d];
}
}
}
return self.element.dispatchEvent(ev);
};
function getPage(event, page) {
return event.changedTouches ? event.changedTouches[0][page] : event[page];
}
function hasProp(props) {
return some(props, function (prop) {
return div.style[prop] !== undefined;
});
}
function setStyle(style, prop, val) {
var _saveProp = saveProp[prop];
if (_saveProp) {
style[_saveProp] = val;
} else if (style[prop] !== undefined) {
saveProp[prop] = prop;
style[prop] = val;
} else {
some(prefix, function (_prefix) {
var _prop = ucFirst(_prefix) + ucFirst(prop);
if (style[_prop] !== undefined) {
saveProp[prop] = _prop;
style[_prop] = val;
return true;
}
});
}
}
function getCSSVal(prop) {
if (div.style[prop] !== undefined) {
return prop;
} else {
var ret;
some(prefix, function (_prefix) {
var _prop = ucFirst(_prefix) + ucFirst(prop);
if (div.style[_prop] !== undefined) {
ret = '-' + _prefix + '-' + prop;
return true;
}
});
return ret;
}
}
function ucFirst(str) {
return str.charAt(0).toUpperCase() + str.substr(1);
}
function some(ary, callback) {
for (var i = 0, len = ary.length; i < len; i++) {
if (callback(ary[i], i)) {
return true;
}
}
return false;
}
if (typeof exports == 'object') {
module.exports = Flipsnap;
} else if (typeof define == 'function' && define.amd) {
define(function () {
return Flipsnap;
});
} else {
window.Flipsnap = Flipsnap;
}
})(window, window.document);
var $pointer = $('.pointer span');
var flipsnap = Flipsnap('.flipsnap', {
//distance: 230
});
flipsnap.element.addEventListener('fspointmove', function () {
$pointer.filter('.current').removeClass('current');
$pointer.eq(flipsnap.currentPoint).addClass('current');
}, false);
function resize() {
var heights = window.innerHeight;
jQuery('.item').css('height', (heights) + "px");
}
resize();

一个主要的问题是,插件的宽度是固定的,而我使用的是响应方法。

有人能帮我吗?那就太好了:)

这并不完美,但我使用jquery来检测flipsnap使用的元素的大小,并在调用flipsnap之前设置宽度。

var vpwidth = $(".viewport").width();
var itemwidth = $(".item").width();     
var flipsnapwidth = itemwidth * 4; //4 is the number of elements        
$(".viewport").css("width",vpwidth);
$(".item").css("width",itemwidth);
$(".flipsnap").css("width",flipsnapwidth);

最新更新