You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
352 lines
12 KiB
352 lines
12 KiB
(function($) { |
|
var CLASS_PULL_TOP_TIPS = $.className('pull-top-tips'); |
|
|
|
$.PullToRefresh = $.PullToRefresh.extend({ |
|
init: function(element, options) { |
|
this._super(element, options); |
|
this.options = $.extend(true, { |
|
down: { |
|
tips: { |
|
colors: ['008000', 'd8ad44', 'd00324', 'dc00b8', '017efc'], |
|
size: 200, //width=height=size;x=y=size/2;radius=size/4 |
|
lineWidth: 15, |
|
duration: 1000, |
|
tail_duration: 1000 * 2.5 |
|
} |
|
} |
|
}, this.options); |
|
this.options.down.tips.color = this.options.down.tips.colors[0]; |
|
this.options.down.tips.colors = this.options.down.tips.colors.map(function(color) { |
|
return { |
|
r: parseInt(color.substring(0, 2), 16), |
|
g: parseInt(color.substring(2, 4), 16), |
|
b: parseInt(color.substring(4, 6), 16) |
|
}; |
|
}); |
|
}, |
|
initPullDownTips: function() { |
|
var self = this; |
|
if ($.isFunction(self.options.down.callback)) { |
|
self.pullDownTips = (function() { |
|
var element = document.querySelector('.' + CLASS_PULL_TOP_TIPS); |
|
if (element) { |
|
element.parentNode.removeChild(element); |
|
} |
|
if (!element) { |
|
element = document.createElement('div'); |
|
element.classList.add(CLASS_PULL_TOP_TIPS); |
|
element.innerHTML = '<div class="mui-pull-top-wrapper"><div class="mui-pull-top-canvas"><canvas id="pullDownTips" width="' + self.options.down.tips.size + '" height="' + self.options.down.tips.size + '"></canvas></div></div>'; |
|
element.addEventListener('webkitTransitionEnd', self); |
|
document.body.appendChild(element); |
|
} |
|
self.pullDownCanvas = document.getElementById("pullDownTips"); |
|
self.pullDownCanvasCtx = self.pullDownCanvas.getContext('2d'); |
|
self.canvasUtils.init(self.pullDownCanvas, self.options.down.tips); |
|
return element; |
|
}()); |
|
} |
|
}, |
|
removePullDownTips: function() { |
|
this._super(); |
|
this.canvasUtils.stopSpin(); |
|
}, |
|
pulling: function(deltaY) { |
|
var ratio = Math.min(deltaY / (this.options.down.height * 1.5), 1); |
|
var ratioPI = Math.min(1, ratio * 2); |
|
this.pullDownTips.style.webkitTransform = 'translate3d(0,' + (deltaY < 0 ? 0 : deltaY) + 'px,0)'; |
|
this.pullDownCanvas.style.opacity = ratioPI; |
|
this.pullDownCanvas.style.webkitTransform = 'rotate(' + 300 * ratio + 'deg)'; |
|
var canvas = this.pullDownCanvas; |
|
var ctx = this.pullDownCanvasCtx; |
|
var size = this.options.down.tips.size; |
|
ctx.lineWidth = this.options.down.tips.lineWidth; |
|
ctx.fillStyle = '#' + this.options.down.tips.color; |
|
ctx.strokeStyle = '#' + this.options.down.tips.color; |
|
ctx.stroke(); |
|
ctx.clearRect(0, 0, size, size); |
|
//fixed android 4.1.x |
|
canvas.style.display = 'none'; // Detach from DOM |
|
canvas.offsetHeight; // Force the detach |
|
canvas.style.display = 'inherit'; // Reattach to DOM |
|
this.canvasUtils.drawArcedArrow(ctx, size / 2 + 0.5, size / 2, size / 4, 0 * Math.PI, 5 / 3 * Math.PI * ratioPI, false, 1, 2, 0.7853981633974483, 25, this.options.down.tips.lineWidth, this.options.down.tips.lineWidth); |
|
}, |
|
|
|
beforeChangeOffset: function(deltaY) {}, |
|
afterChangeOffset: function(deltaY) {}, |
|
dragEndAfterChangeOffset: function(isNeedRefresh) { |
|
if (isNeedRefresh) { |
|
this.canvasUtils.startSpin(); |
|
this.pullDownLoading(); |
|
} else { |
|
this.canvasUtils.stopSpin(); |
|
this.endPullDownToRefresh(); |
|
} |
|
}, |
|
canvasUtils: (function() { |
|
var canvasObj = null, |
|
ctx = null, |
|
size = 200, |
|
lineWidth = 15, |
|
tick = 0, |
|
startTime = 0, |
|
frameTime = 0, |
|
timeLast = 0, |
|
oldStep = 0, |
|
acc = 0, |
|
head = 0, |
|
tail = 180, |
|
rad = Math.PI / 180, |
|
duration = 1000, |
|
tail_duration = 1000 * 2.5, |
|
colors = ['35ad0e', 'd8ad44', 'd00324', 'dc00b8', '017efc'], |
|
rAF = null; |
|
|
|
function easeLinear(currentIteration, startValue, changeInValue, totalIterations) { |
|
return changeInValue * currentIteration / totalIterations + startValue; |
|
} |
|
|
|
function easeInOutQuad(currentIteration, startValue, changeInValue, totalIterations) { |
|
if ((currentIteration /= totalIterations / 2) < 1) { |
|
return changeInValue / 2 * currentIteration * currentIteration + startValue; |
|
} |
|
return -changeInValue / 2 * ((--currentIteration) * (currentIteration - 2) - 1) + startValue; |
|
} |
|
|
|
function minmax(value, v0, v1) { |
|
var min = Math.min(v0, v1); |
|
var max = Math.max(v0, v1); |
|
if (value < min) |
|
return min; |
|
if (value > max) |
|
return min; |
|
return value; |
|
} |
|
var drawHead = function(ctx, x0, y0, x1, y1, x2, y2, style) { |
|
'use strict'; |
|
if (typeof(x0) == 'string') x0 = parseInt(x0); |
|
if (typeof(y0) == 'string') y0 = parseInt(y0); |
|
if (typeof(x1) == 'string') x1 = parseInt(x1); |
|
if (typeof(y1) == 'string') y1 = parseInt(y1); |
|
if (typeof(x2) == 'string') x2 = parseInt(x2); |
|
if (typeof(y2) == 'string') y2 = parseInt(y2); |
|
var radius = 3; |
|
var twoPI = 2 * Math.PI; |
|
ctx.save(); |
|
ctx.beginPath(); |
|
ctx.moveTo(x0, y0); |
|
ctx.lineTo(x1, y1); |
|
ctx.lineTo(x2, y2); |
|
switch (style) { |
|
case 0: |
|
var backdist = Math.sqrt(((x2 - x0) * (x2 - x0)) + ((y2 - y0) * (y2 - y0))); |
|
ctx.arcTo(x1, y1, x0, y0, .55 * backdist); |
|
ctx.fill(); |
|
break; |
|
case 1: |
|
ctx.beginPath(); |
|
ctx.moveTo(x0, y0); |
|
ctx.lineTo(x1, y1); |
|
ctx.lineTo(x2, y2); |
|
ctx.lineTo(x0, y0); |
|
ctx.fill(); |
|
break; |
|
case 2: |
|
ctx.stroke(); |
|
break; |
|
case 3: |
|
var cpx = (x0 + x1 + x2) / 3; |
|
var cpy = (y0 + y1 + y2) / 3; |
|
ctx.quadraticCurveTo(cpx, cpy, x0, y0); |
|
ctx.fill(); |
|
break; |
|
case 4: |
|
var cp1x, cp1y, cp2x, cp2y, backdist; |
|
var shiftamt = 5; |
|
if (x2 == x0) { |
|
backdist = y2 - y0; |
|
cp1x = (x1 + x0) / 2; |
|
cp2x = (x1 + x0) / 2; |
|
cp1y = y1 + backdist / shiftamt; |
|
cp2y = y1 - backdist / shiftamt; |
|
} else { |
|
backdist = Math.sqrt(((x2 - x0) * (x2 - x0)) + ((y2 - y0) * (y2 - y0))); |
|
var xback = (x0 + x2) / 2; |
|
var yback = (y0 + y2) / 2; |
|
var xmid = (xback + x1) / 2; |
|
var ymid = (yback + y1) / 2; |
|
var m = (y2 - y0) / (x2 - x0); |
|
var dx = (backdist / (2 * Math.sqrt(m * m + 1))) / shiftamt; |
|
var dy = m * dx; |
|
cp1x = xmid - dx; |
|
cp1y = ymid - dy; |
|
cp2x = xmid + dx; |
|
cp2y = ymid + dy; |
|
} |
|
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x0, y0); |
|
ctx.fill(); |
|
break; |
|
} |
|
ctx.restore(); |
|
}; |
|
var drawArcedArrow = function(ctx, x, y, r, startangle, endangle, anticlockwise, style, which, angle, d, lineWidth, lineRatio) { |
|
'use strict'; |
|
style = typeof(style) != 'undefined' ? style : 3; |
|
which = typeof(which) != 'undefined' ? which : 1; |
|
angle = typeof(angle) != 'undefined' ? angle : Math.PI / 8; |
|
lineWidth = lineWidth || 1; |
|
lineRatio = lineRatio || 10; |
|
d = typeof(d) != 'undefined' ? d : 10; |
|
ctx.save(); |
|
ctx.lineWidth = lineWidth; |
|
ctx.beginPath(); |
|
ctx.arc(x, y, r, startangle, endangle, anticlockwise); |
|
ctx.stroke(); |
|
var sx, sy, lineangle, destx, desty; |
|
if (which & 1) { |
|
sx = Math.cos(startangle) * r + x; |
|
sy = Math.sin(startangle) * r + y; |
|
lineangle = Math.atan2(x - sx, sy - y); |
|
if (anticlockwise) { |
|
destx = sx + 10 * Math.cos(lineangle); |
|
desty = sy + 10 * Math.sin(lineangle); |
|
} else { |
|
destx = sx - 10 * Math.cos(lineangle); |
|
desty = sy - 10 * Math.sin(lineangle); |
|
} |
|
drawArrow(ctx, sx, sy, destx, desty, style, 2, angle, d); |
|
} |
|
if (which & 2) { |
|
sx = Math.cos(endangle) * r + x; |
|
sy = Math.sin(endangle) * r + y; |
|
lineangle = Math.atan2(x - sx, sy - y); |
|
if (anticlockwise) { |
|
destx = sx - 10 * Math.cos(lineangle); |
|
desty = sy - 10 * Math.sin(lineangle); |
|
} else { |
|
destx = sx + 10 * Math.cos(lineangle); |
|
desty = sy + 10 * Math.sin(lineangle); |
|
} |
|
drawArrow(ctx, sx - lineRatio * Math.sin(endangle), sy + lineRatio * Math.cos(endangle), destx - lineRatio * Math.sin(endangle), desty + lineRatio * Math.cos(endangle), style, 2, angle, d) |
|
} |
|
ctx.restore(); |
|
} |
|
var drawArrow = function(ctx, x1, y1, x2, y2, style, which, angle, d) { |
|
'use strict'; |
|
if (typeof(x1) == 'string') x1 = parseInt(x1); |
|
if (typeof(y1) == 'string') y1 = parseInt(y1); |
|
if (typeof(x2) == 'string') x2 = parseInt(x2); |
|
if (typeof(y2) == 'string') y2 = parseInt(y2); |
|
style = typeof(style) != 'undefined' ? style : 3; |
|
which = typeof(which) != 'undefined' ? which : 1; |
|
angle = typeof(angle) != 'undefined' ? angle : Math.PI / 8; |
|
d = typeof(d) != 'undefined' ? d : 10; |
|
var toDrawHead = typeof(style) != 'function' ? drawHead : style; |
|
var dist = Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); |
|
var ratio = (dist - d / 3) / dist; |
|
var tox, toy, fromx, fromy; |
|
if (which & 1) { |
|
tox = Math.round(x1 + (x2 - x1) * ratio); |
|
toy = Math.round(y1 + (y2 - y1) * ratio); |
|
} else { |
|
tox = x2; |
|
toy = y2; |
|
} |
|
if (which & 2) { |
|
fromx = x1 + (x2 - x1) * (1 - ratio); |
|
fromy = y1 + (y2 - y1) * (1 - ratio); |
|
} else { |
|
fromx = x1; |
|
fromy = y1; |
|
} |
|
ctx.beginPath(); |
|
ctx.moveTo(fromx, fromy); |
|
ctx.lineTo(tox, toy); |
|
ctx.stroke(); |
|
var lineangle = Math.atan2(y2 - y1, x2 - x1); |
|
var h = Math.abs(d / Math.cos(angle)); |
|
if (which & 1) { |
|
var angle1 = lineangle + Math.PI + angle; |
|
var topx = x2 + Math.cos(angle1) * h; |
|
var topy = y2 + Math.sin(angle1) * h; |
|
var angle2 = lineangle + Math.PI - angle; |
|
var botx = x2 + Math.cos(angle2) * h; |
|
var boty = y2 + Math.sin(angle2) * h; |
|
toDrawHead(ctx, topx, topy, x2, y2, botx, boty, style); |
|
} |
|
if (which & 2) { |
|
var angle1 = lineangle + angle; |
|
var topx = x1 + Math.cos(angle1) * h; |
|
var topy = y1 + Math.sin(angle1) * h; |
|
var angle2 = lineangle - angle; |
|
var botx = x1 + Math.cos(angle2) * h; |
|
var boty = y1 + Math.sin(angle2) * h; |
|
toDrawHead(ctx, topx, topy, x1, y1, botx, boty, style); |
|
} |
|
}; |
|
|
|
var spinColors = function(currentIteration, totalIterations) { |
|
var step = currentIteration % totalIterations; |
|
if (step < oldStep) |
|
colors.push(colors.shift()); |
|
var c0 = colors[0], |
|
c1 = colors[1], |
|
r = minmax(easeLinear(step, c0.r, c1.r - c0.r, totalIterations), c0.r, c1.r), |
|
g = minmax(easeLinear(step, c0.g, c1.g - c0.g, totalIterations), c0.g, c1.g), |
|
b = minmax(easeLinear(step, c0.b, c1.b - c0.b, totalIterations), c0.b, c1.b); |
|
|
|
oldStep = step; |
|
return "rgb(" + parseInt(r) + "," + parseInt(g) + "," + parseInt(b) + ")"; |
|
} |
|
|
|
var spin = function(t) { |
|
var timeCurrent = t || (new Date).getTime(); |
|
if (!startTime) { |
|
startTime = timeCurrent; |
|
} |
|
tick = timeCurrent - startTime; |
|
acc = easeInOutQuad((tick + tail_duration / 2) % tail_duration, 0, duration, tail_duration); |
|
head = easeLinear((tick + acc) % duration, 0, 360, duration); |
|
tail = 20 + Math.abs(easeLinear((tick + tail_duration / 2) % tail_duration, -300, 600, tail_duration)); |
|
|
|
ctx.lineWidth = lineWidth; |
|
ctx.lineCap = "round"; |
|
|
|
ctx.strokeStyle = spinColors(tick, duration); |
|
ctx.clearRect(0, 0, size, size); |
|
//fixed android 4.1.x |
|
canvasObj.style.display = 'none'; // Detach from DOM |
|
canvasObj.offsetHeight; // Force the detach |
|
canvasObj.style.display = 'inherit'; // Reattach to DOM |
|
ctx.beginPath(); |
|
ctx.arc(size / 2, size / 2, size / 4, parseInt(head - tail) % 360 * rad, parseInt(head) % 360 * rad, false); |
|
ctx.stroke(); |
|
|
|
rAF = requestAnimationFrame(spin); |
|
}; |
|
var startSpin = function() { |
|
startTime = 0; |
|
oldStep = 0; |
|
rAF = requestAnimationFrame(spin); |
|
}; |
|
var stopSpin = function() { |
|
rAF && cancelAnimationFrame(rAF); |
|
} |
|
var init = function(canvas, options) { |
|
canvasObj = canvas; |
|
ctx = canvasObj.getContext('2d'); |
|
var options = $.extend(true, {}, options); |
|
colors = options.colors; |
|
duration = options.duration; |
|
tail_duration = options.tail_duration; |
|
size = options.size; |
|
lineWidth = options.lineWidth; |
|
}; |
|
return { |
|
init: init, |
|
drawArcedArrow: drawArcedArrow, |
|
startSpin: startSpin, |
|
stopSpin: stopSpin |
|
}; |
|
})() |
|
}); |
|
})(mui); |