zview-mobile
Version:
Mobile UI Components, based on Vue.js and ionic CSS.
290 lines (229 loc) • 7.26 kB
JavaScript
// default options
const DEFAULT_OPTIONS = {
itemClass: '.gallery-item',
spacewidth: 5,
direction: 'vertical', //垂直
threshold: 30,
duration: 250,
transitionEnd: noop
};
// utilities
const extend = (target, source) => {
for (var key in source) {
target[key] = source[key]
}
return target
};
function noop() {}
function execFn(fn) { setTimeout(fn || noop, 0)}
function Swiper(container, swiperOptions) {
let options = extend(DEFAULT_OPTIONS, swiperOptions)
let spacewidth = options.spacewidth;
let itemClass = options.itemClass;
console.log('option space', spacewidth, 'class', itemClass);
let offset = 0;
let maxoffset = 0;
let width = container.getBoundingClientRect().width || container.offsetWidth;
let height = container.getBoundingClientRect().height || container.offsetHeight;
console.log('container width', width, 'height', height);
// Init
function init() {
offset = 0;
maxoffset = 0;
width = container.getBoundingClientRect().width || container.offsetWidth;
height = container.getBoundingClientRect().height || container.offsetHeight;
console.log('container width', width, 'height', height);
let style = container.style;
style.webkitTransition =
style.transition = '2ms';
style.webkitTransform =
style.transform = 'translate3d(0, 0, 0)';
}
// Setup
function setup() {
let items = container.querySelectorAll(itemClass);
let count = items.length;
let item = items[0];
let item_width = item.offsetWidth;
let item_height = item.offsetHeight;
console.log('item width', item_width, 'height', item_height);
// reset container's width and height
var w = width;
var h = (item_height + Number(spacewidth)) * count;
maxoffset = h - height;
if (options.direction === 'horizontal') { //水平
w = (item_width + Number(spacewidth)) * count;
h = height;
maxoffset = w - width;
}
// console.log('setup', count, w, h, maxoffset);
container.style.width = w + 'px';
container.style.height = h + 'px';
// set width and height for every single swipe item
let pos = count
while (pos--) {
let itemx = items[pos];
if (options.direction === 'horizontal') { //水平
itemx.style.marginRight = spacewidth + 'px';
}
else {
itemx.style.marginBottom = spacewidth + 'px';
}
}
}
// Events
// init varialbles
let start = {}
let move = {}
let end = {}
const events = {
start: function (e) {
let touch = e.changedTouches[0];
start.x = touch.pageX;
start.y = touch.pageY;
start.time = +new Date();
// console.log('start', start.x, start.y);
let style = container.style;
style.webkitTransition =
style.transition = 'none';
},
move: function (e) {
// ensure swiping with one touch and not pinching
// if ( event.touches.length > 1 || event.scale && event.scale !== 1) return
let touch = e.changedTouches[0];
move.x = touch.pageX;
move.y = touch.pageY;
let dist = move.y - start.y;
let transform = 'translate3d(0, ' + (dist - offset) + 'px, 0)';
if (options.direction == 'horizontal') { //水平
dist = move.x - start.x;
transform = 'translate3d(' + (dist - offset) + 'px, 0, 0)';
}
// console.log('move', dist, offset, maxoffset);
if(maxoffset>0) {
let style = container.style;
style.webkitTransform =
style.transfrom = transform;
}
//门限
if (dist > options.threshold) {
e.preventDefault()
}
else if (dist < -options.threshold) {
e.preventDefault()
}
// e.preventDefault();
},
end: function (e) {
let touch = e.changedTouches[0];
end.x = touch.pageX;
end.y = touch.pageY;
let dist = end.y - start.y;
if (options.direction == 'horizontal') { //水平
dist = end.x - start.x;
}
let transform = 'translate3d(0, -' + (dist - offset) + 'px, 0)';
if (options.direction == 'horizontal') {//水平
transform = 'translate3d(-' + (dist - offset) + 'px, 0, 0)';
}
let duration = options.duration + 'ms';
// console.log('end', dist, offset, maxoffset, transform);
//门限
/*if (dist > options.threshold) {
e.preventDefault()
}
else if (dist < -options.threshold) {
e.preventDefault()
}
else if(maxoffset<=0) {
e.preventDefault()
}*/
let overright = false;
let overleft = false;
if (options.direction == 'horizontal') {//水平
overright = (offset - dist) >= maxoffset;
console.log('overright', overright);
if(overright) {
transform = 'translate3d(-' + (maxoffset) + 'px, 0, 0)';
}
overleft = (dist>0 && offset==0);
console.log('overleft', overleft);
if(overleft) {
transform = 'translate3d(-' + (0) + 'px, 0, 0)';
}
}
let overbottom = false;
let overtop = false;
if (options.direction == 'vertical') {//垂直 TODO
overbottom = (offset - dist) >= maxoffset;
console.log('overbottom', overbottom);
if(overbottom) {
transform = 'translate3d(0, -' + maxoffset + 'px, 0)';
}
overtop = (dist>0 && offset==0);
console.log('overtop', overtop);
if(overtop) {
transform = 'translate3d(0, -' + 0 + 'px, 0)';
}
}
let style = container.style;
style.webkitTransition =
style.transition = duration;
style.webkitTransform =
style.transform = transform;
if(overright) {
offset = maxoffset;
}
if(overleft) {
offset = 0;
}
else {
offset = offset - dist;
}
},
transitionEnd: function (e) {
e.preventDefault();
}
};
function resize() {
execFn(setup)
}
// bind events
function bind() {
container.addEventListener('touchstart', events.start);
container.addEventListener('touchmove', events.move);
container.addEventListener('touchend', events.end);
container.addEventListener('transitionEnd', noop);
container.addEventListener('webkitTransitionEnd', noop); //events.transitionEnd
container.addEventListener('resize', resize);
}
function unbind() {
container.removeEventListener('touchstart', events.start);
container.removeEventListener('touchmove', events.move);
container.removeEventListener('touchend', events.end);
container.removeEventListener('transitionEnd', noop);
container.removeEventListener('webkitTransitionEnd', noop); //events.transitionEnd
container.removeEventListener('resize', resize);
}
window.addEventListener('resize', resize);
init();
setup();
bind();
// Publish APIs
function noTransition() {
let style = container.style
style.webkitTransition =
style.transition = 'none'
}
return {
resize: function () {
init();
setup();
},
destroy: function () {
unbind()
window.removeEventListener('resize', resize)
},
}
}
export default Swiper