Brak opisu

mui.pullToRefresh.material.js 12KB

    (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);