1. jquery.roundabout.js文件
    /**
  2. * jQuery Roundabout - v2.4.2
  3. * http://fredhq.com/projects/roundabout
  4. *
  5. * Moves list-items of enabled ordered and unordered lists long
  6. * a chosen path. Includes the default "lazySusan" path, that
  7. * moves items long a spinning turntable.
  8. *
  9. * Terms of Use // jQuery Roundabout
  10. *
  11. * Open source under the BSD license
  12. *
  13. * Copyright (c) 2011-2012, Fred LeBlanc
  14. * All rights reserved.
  15. *
  16. * Redistribution and use in source and binary forms, with or without
  17. * modification, are permitted provided that the following conditions are met:
  18. *
  19. * - Redistributions of source code must retain the above copyright
  20. * notice, this list of conditions and the following disclaimer.
  21. * - Redistributions in binary form must reproduce the above
  22. * copyright notice, this list of conditions and the following
  23. * disclaimer in the documentation and/or other materials provided
  24. * with the distribution.
  25. * - Neither the name of the author nor the names of its contributors
  26. * may be used to endorse or promote products derived from this
  27. * software without specific prior written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  30. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
  33. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  34. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  35. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  36. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  37. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  38. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  39. * POSSIBILITY OF SUCH DAMAGE.
  40. */
  41. (function($) {
  42. "use strict";
  43.  
  44. var defaults, internalData, methods;
  45.  
  46. // add default shape
  47. $.extend({
  48. roundaboutShapes: {
  49. def: "lazySusan",
  50. lazySusan: function (r, a, t) {
  51. return {
  52. x: Math.sin(r + a),
  53. y: (Math.sin(r + 3 * Math.PI / 2 + a) / 8) * t,
  54. z: (Math.cos(r + a) + 1) / 2,
  55. scale: (Math.sin(r + Math.PI / 2 + a) / 2) + 0.5
  56. };
  57. }
  58. }
  59. });
  60.  
  61. defaults = {
  62. bearing: 0.0,
  63. tilt: 0.0,
  64. minZ: 100,
  65. maxZ: 280,
  66. minOpacity: 0.4,
  67. maxOpacity: 1.0,
  68. minScale: 0.4,
  69. maxScale: 1.0,
  70. duration: 600,
  71. btnNext: null,
  72. btnNextCallback: function() {},
  73. btnPrev: null,
  74. btnPrevCallback: function() {},
  75. btnToggleAutoplay: null,
  76. btnStartAutoplay: null,
  77. btnStopAutoplay: null,
  78. easing: "swing",
  79. clickToFocus: true,
  80. clickToFocusCallback: function() {},
  81. focusBearing: 0.0,
  82. shape: "lazySusan",
  83. debug: false,
  84. childSelector: "li",
  85. startingChild: null,
  86. reflect: false,
  87. floatComparisonThreshold: 0.001,
  88. autoplay: false,
  89. autoplayDuration: 1000,
  90. autoplayPauseOnHover: false,
  91. autoplayCallback: function() {},
  92. autoplayInitialDelay: 0,
  93. enableDrag: false,
  94. dropDuration: 600,
  95. dropEasing: "swing",
  96. dropAnimateTo: "nearest",
  97. dropCallback: function() {},
  98. dragAxis: "x",
  99. dragFactor: 4,
  100. triggerFocusEvents: true,
  101. triggerBlurEvents: true,
  102. responsive: false
  103. };
  104.  
  105. internalData = {
  106. autoplayInterval: null,
  107. autoplayIsRunning: false,
  108. autoplayStartTimeout: null,
  109. animating: false,
  110. childInFocus: -1,
  111. touchMoveStartPosition: null,
  112. stopAnimation: false,
  113. lastAnimationStep: false
  114. };
  115.  
  116. methods = {
  117.  
  118. // starters
  119. // -----------------------------------------------------------------------
  120.  
  121. // init
  122. // starts up roundabout
  123. init: function(options, callback, relayout) {
  124. var settings,
  125. now = (new Date()).getTime();
  126.  
  127. options = (typeof options === "object") ? options : {};
  128. callback = ($.isFunction(callback)) ? callback : function() {};
  129. callback = ($.isFunction(options)) ? options : callback;
  130. settings = $.extend({}, defaults, options, internalData);
  131.  
  132. return this
  133. .each(function() {
  134. // make options
  135. var self = $(this),
  136. childCount = self.children(settings.childSelector).length,
  137. period = 360.0 / childCount,
  138. startingChild = (settings.startingChild && settings.startingChild > (childCount - 1)) ? (childCount - 1) : settings.startingChild,
  139. startBearing = (settings.startingChild === null) ? settings.bearing : 360 - (startingChild * period),
  140. holderCSSPosition = (self.css("position") !== "static") ? self.css("position") : "relative";
  141.  
  142. self
  143. .css({ // starting styles
  144. padding: 0,
  145. position: holderCSSPosition
  146. })
  147. .addClass("roundabout-holder")
  148. .data( // starting options
  149. "roundabout",
  150. $.extend(
  151. {},
  152. settings,
  153. {
  154. startingChild: startingChild,
  155. bearing: startBearing,
  156. oppositeOfFocusBearing: methods.normalize.apply(null, [settings.focusBearing - 180]),
  157. dragBearing: startBearing,
  158. period: period
  159. }
  160. )
  161. );
  162.  
  163. // unbind any events that we set if we're relaying out
  164. if (relayout) {
  165. self
  166. .unbind(".roundabout")
  167. .children(settings.childSelector)
  168. .unbind(".roundabout");
  169. } else {
  170. // bind responsive action
  171. if (settings.responsive) {
  172. $(window).bind("resize", function() {
  173. methods.stopAutoplay.apply(self);
  174. methods.relayoutChildren.apply(self);
  175. });
  176. }
  177. }
  178.  
  179. // bind click-to-focus
  180. if (settings.clickToFocus) {
  181. self
  182. .children(settings.childSelector)
  183. .each(function(i) {
  184. $(this)
  185. .bind("click.roundabout", function() {
  186. var degrees = methods.getPlacement.apply(self, [i]);
  187.  
  188. if (!methods.isInFocus.apply(self, [degrees])) {
  189. methods.stopAnimation.apply($(this));
  190. if (!self.data("roundabout").animating) {
  191. methods.animateBearingToFocus.apply(self, [degrees, self.data("roundabout").clickToFocusCallback]);
  192. }
  193. return false;
  194. }
  195. });
  196. });
  197. }
  198.  
  199. // bind next buttons
  200. if (settings.btnNext) {
  201. $(settings.btnNext)
  202. .bind("click.roundabout", function() {
  203. if (!self.data("roundabout").animating) {
  204. methods.animateToNextChild.apply(self, [self.data("roundabout").btnNextCallback]);
  205. }
  206. return false;
  207. });
  208. }
  209.  
  210. // bind previous buttons
  211. if (settings.btnPrev) {
  212. $(settings.btnPrev)
  213. .bind("click.roundabout", function() {
  214. methods.animateToPreviousChild.apply(self, [self.data("roundabout").btnPrevCallback]);
  215. return false;
  216. });
  217. }
  218.  
  219. // bind toggle autoplay buttons
  220. if (settings.btnToggleAutoplay) {
  221. $(settings.btnToggleAutoplay)
  222. .bind("click.roundabout", function() {
  223. methods.toggleAutoplay.apply(self);
  224. return false;
  225. });
  226. }
  227.  
  228. // bind start autoplay buttons
  229. if (settings.btnStartAutoplay) {
  230. $(settings.btnStartAutoplay)
  231. .bind("click.roundabout", function() {
  232. methods.startAutoplay.apply(self);
  233. return false;
  234. });
  235. }
  236.  
  237. // bind stop autoplay buttons
  238. if (settings.btnStopAutoplay) {
  239. $(settings.btnStopAutoplay)
  240. .bind("click.roundabout", function() {
  241. methods.stopAutoplay.apply(self);
  242. return false;
  243. });
  244. }
  245.  
  246. // autoplay pause on hover
  247. if (settings.autoplayPauseOnHover) {
  248. self
  249. .bind("mouseenter.roundabout.autoplay", function() {
  250. methods.stopAutoplay.apply(self, [true]);
  251. })
  252. .bind("mouseleave.roundabout.autoplay", function() {
  253. methods.startAutoplay.apply(self);
  254. });
  255. }
  256.  
  257. // drag and drop
  258. if (settings.enableDrag) {
  259. // on screen
  260. if (!$.isFunction(self.drag)) {
  261. if (settings.debug) {
  262. alert("You do not have the drag plugin loaded.");
  263. }
  264. } else if (!$.isFunction(self.drop)) {
  265. if (settings.debug) {
  266. alert("You do not have the drop plugin loaded.");
  267. }
  268. } else {
  269. self
  270. .drag(function(e, properties) {
  271. var data = self.data("roundabout"),
  272. delta = (data.dragAxis.toLowerCase() === "x") ? "deltaX" : "deltaY";
  273. methods.stopAnimation.apply(self);
  274. methods.setBearing.apply(self, [data.dragBearing + properties[delta] / data.dragFactor]);
  275. })
  276. .drop(function(e) {
  277. var data = self.data("roundabout"),
  278. method = methods.getAnimateToMethod(data.dropAnimateTo);
  279. methods.allowAnimation.apply(self);
  280. methods[method].apply(self, [data.dropDuration, data.dropEasing, data.dropCallback]);
  281. data.dragBearing = data.period * methods.getNearestChild.apply(self);
  282. });
  283. }
  284.  
  285. // on mobile
  286. self
  287. .each(function() {
  288. var element = $(this).get(0),
  289. data = $(this).data("roundabout"),
  290. page = (data.dragAxis.toLowerCase() === "x") ? "pageX" : "pageY",
  291. method = methods.getAnimateToMethod(data.dropAnimateTo);
  292.  
  293. // some versions of IE don't like this
  294. if (element.addEventListener) {
  295. element.addEventListener("touchstart", function(e) {
  296. data.touchMoveStartPosition = e.touches[0][page];
  297. }, false);
  298.  
  299. element.addEventListener("touchmove", function(e) {
  300. var delta = (e.touches[0][page] - data.touchMoveStartPosition) / data.dragFactor;
  301. e.preventDefault();
  302. methods.stopAnimation.apply($(this));
  303. methods.setBearing.apply($(this), [data.dragBearing + delta]);
  304. }, false);
  305.  
  306. element.addEventListener("touchend", function(e) {
  307. e.preventDefault();
  308. methods.allowAnimation.apply($(this));
  309. method = methods.getAnimateToMethod(data.dropAnimateTo);
  310. methods[method].apply($(this), [data.dropDuration, data.dropEasing, data.dropCallback]);
  311. data.dragBearing = data.period * methods.getNearestChild.apply($(this));
  312. }, false);
  313. }
  314. });
  315. }
  316.  
  317. // start children
  318. methods.initChildren.apply(self, [callback, relayout]);
  319. });
  320. },
  321.  
  322. // initChildren
  323. // applys settings to child elements, starts roundabout
  324. initChildren: function(callback, relayout) {
  325. var self = $(this),
  326. data = self.data("roundabout");
  327.  
  328. callback = callback || function() {};
  329.  
  330. self.children(data.childSelector).each(function(i) {
  331. var startWidth, startHeight, startFontSize,
  332. degrees = methods.getPlacement.apply(self, [i]);
  333.  
  334. // on relayout, grab these values from current data
  335. if (relayout && $(this).data("roundabout")) {
  336. startWidth = $(this).data("roundabout").startWidth;
  337. startHeight = $(this).data("roundabout").startHeight;
  338. startFontSize = $(this).data("roundabout").startFontSize;
  339. }
  340.  
  341. // apply classes and css first
  342. $(this)
  343. .addClass("roundabout-moveable-item")
  344. .css("position", "absolute");
  345.  
  346. // now measure
  347. $(this)
  348. .data(
  349. "roundabout",
  350. {
  351. startWidth: startWidth || $(this).width(),
  352. startHeight: startHeight || $(this).height(),
  353. startFontSize: startFontSize || parseInt($(this).css("font-size"), 10),
  354. degrees: degrees,
  355. backDegrees: methods.normalize.apply(null, [degrees - 180]),
  356. childNumber: i,
  357. currentScale: 1,
  358. parent: self
  359. }
  360. );
  361. });
  362.  
  363. methods.updateChildren.apply(self);
  364.  
  365. // start autoplay if necessary
  366. if (data.autoplay) {
  367. data.autoplayStartTimeout = setTimeout(function() {
  368. methods.startAutoplay.apply(self);
  369. }, data.autoplayInitialDelay);
  370. }
  371.  
  372. self.trigger('ready');
  373. callback.apply(self);
  374. return self;
  375. },
  376.  
  377. // positioning
  378. // -----------------------------------------------------------------------
  379.  
  380. // updateChildren
  381. // move children elements into their proper locations
  382. updateChildren: function() {
  383. return this
  384. .each(function() {
  385. var self = $(this),
  386. data = self.data("roundabout"),
  387. inFocus = -1,
  388. info = {
  389. bearing: data.bearing,
  390. tilt: data.tilt,
  391. stage: {
  392. width: Math.floor($(this).width() * 0.9),
  393. height: Math.floor($(this).height() * 0.9)
  394. },
  395. animating: data.animating,
  396. inFocus: data.childInFocus,
  397. focusBearingRadian: methods.degToRad.apply(null, [data.focusBearing]),
  398. shape: $.roundaboutShapes[data.shape] || $.roundaboutShapes[$.roundaboutShapes.def]
  399. };
  400.  
  401. // calculations
  402. info.midStage = {
  403. width: info.stage.width / 2,
  404. height: info.stage.height / 2
  405. };
  406.  
  407. info.nudge = {
  408. width: info.midStage.width + (info.stage.width * 0.05),
  409. height: info.midStage.height + (info.stage.height * 0.05)
  410. };
  411.  
  412. info.zValues = {
  413. min: data.minZ,
  414. max: data.maxZ,
  415. diff: data.maxZ - data.minZ
  416. };
  417.  
  418. info.opacity = {
  419. min: data.minOpacity,
  420. max: data.maxOpacity,
  421. diff: data.maxOpacity - data.minOpacity
  422. };
  423.  
  424. info.scale = {
  425. min: data.minScale,
  426. max: data.maxScale,
  427. diff: data.maxScale - data.minScale
  428. };
  429.  
  430. // update child positions
  431. self.children(data.childSelector)
  432. .each(function(i) {
  433. if (methods.updateChild.apply(self, [$(this), info, i, function() { $(this).trigger('ready'); }]) && (!info.animating || data.lastAnimationStep)) {
  434. inFocus = i;
  435. $(this).addClass("roundabout-in-focus");
  436. } else {
  437. $(this).removeClass("roundabout-in-focus");
  438. }
  439. });
  440.  
  441. if (inFocus !== info.inFocus) {
  442. // blur old child
  443. if (data.triggerBlurEvents) {
  444. self.children(data.childSelector)
  445. .eq(info.inFocus)
  446. .trigger("blur");
  447. }
  448.  
  449. data.childInFocus = inFocus;
  450.  
  451. if (data.triggerFocusEvents && inFocus !== -1) {
  452. // focus new child
  453. self.children(data.childSelector)
  454. .eq(inFocus)
  455. .trigger("focus");
  456. }
  457. }
  458.  
  459. self.trigger("childrenUpdated");
  460. });
  461. },
  462.  
  463. // updateChild
  464. // repositions a child element into its new position
  465. updateChild: function(childElement, info, childPos, callback) {
  466. var factors,
  467. self = this,
  468. child = $(childElement),
  469. data = child.data("roundabout"),
  470. out = [],
  471. rad = methods.degToRad.apply(null, [(360.0 - data.degrees) + info.bearing]);
  472.  
  473. callback = callback || function() {};
  474.  
  475. // adjust radians to be between 0 and Math.PI * 2
  476. rad = methods.normalizeRad.apply(null, [rad]);
  477.  
  478. // get factors from shape
  479. factors = info.shape(rad, info.focusBearingRadian, info.tilt);
  480.  
  481. // correct
  482. factors.scale = (factors.scale > 1) ? 1 : factors.scale;
  483. factors.adjustedScale = (info.scale.min + (info.scale.diff * factors.scale)).toFixed(4);
  484. factors.width = (factors.adjustedScale * data.startWidth).toFixed(4);
  485. factors.height = (factors.adjustedScale * data.startHeight).toFixed(4);
  486.  
  487. // update item
  488. child
  489. .css({
  490. left: ((factors.x * info.midStage.width + info.nudge.width) - factors.width / 2.0).toFixed(0) + "px",
  491. top: ((factors.y * info.midStage.height + info.nudge.height) - factors.height / 2.0).toFixed(0) + "px",
  492. width: factors.width + "px",
  493. height: factors.height + "px",
  494. opacity: (info.opacity.min + (info.opacity.diff * factors.scale)).toFixed(2),
  495. zIndex: Math.round(info.zValues.min + (info.zValues.diff * factors.z)),
  496. fontSize: (factors.adjustedScale * data.startFontSize).toFixed(1) + "px"
  497. });
  498. data.currentScale = factors.adjustedScale;
  499.  
  500. // for debugging purposes
  501. if (self.data("roundabout").debug) {
  502. out.push("<div style=\"font-weight: normal; font-size: 10px; padding: 2px; width: " + child.css("width") + "; background-color: #ffc;\">");
  503. out.push("<strong style=\"font-size: 12px; white-space: nowrap;\">Child " + childPos + "</strong><br />");
  504. out.push("<strong>left:</strong> " + child.css("left") + "<br />");
  505. out.push("<strong>top:</strong> " + child.css("top") + "<br />");
  506. out.push("<strong>width:</strong> " + child.css("width") + "<br />");
  507. out.push("<strong>opacity:</strong> " + child.css("opacity") + "<br />");
  508. out.push("<strong>height:</strong> " + child.css("height") + "<br />");
  509. out.push("<strong>z-index:</strong> " + child.css("z-index") + "<br />");
  510. out.push("<strong>font-size:</strong> " + child.css("font-size") + "<br />");
  511. out.push("<strong>scale:</strong> " + child.data("roundabout").currentScale);
  512. out.push("</div>");
  513.  
  514. child.html(out.join(""));
  515. }
  516.  
  517. // trigger event
  518. child.trigger("reposition");
  519.  
  520. // callback
  521. callback.apply(self);
  522.  
  523. return methods.isInFocus.apply(self, [data.degrees]);
  524. },
  525.  
  526. // manipulation
  527. // -----------------------------------------------------------------------
  528.  
  529. // setBearing
  530. // changes the bearing of the roundabout
  531. setBearing: function(bearing, callback) {
  532. callback = callback || function() {};
  533. bearing = methods.normalize.apply(null, [bearing]);
  534.  
  535. this
  536. .each(function() {
  537. var diff, lowerValue, higherValue,
  538. self = $(this),
  539. data = self.data("roundabout"),
  540. oldBearing = data.bearing;
  541.  
  542. // set bearing
  543. data.bearing = bearing;
  544. self.trigger("bearingSet");
  545. methods.updateChildren.apply(self);
  546.  
  547. // not animating? we're done here
  548. diff = Math.abs(oldBearing - bearing);
  549. if (!data.animating || diff > 180) {
  550. return;
  551. }
  552.  
  553. // check to see if any of the children went through the back
  554. diff = Math.abs(oldBearing - bearing);
  555. self.children(data.childSelector).each(function(i) {
  556. var eventType;
  557.  
  558. if (methods.isChildBackDegreesBetween.apply($(this), [bearing, oldBearing])) {
  559. eventType = (oldBearing > bearing) ? "Clockwise" : "Counterclockwise";
  560. $(this).trigger("move" + eventType + "ThroughBack");
  561. }
  562. });
  563. });
  564.  
  565. // call callback if one was given
  566. callback.apply(this);
  567. return this;
  568. },
  569.  
  570. // adjustBearing
  571. // change the bearing of the roundabout by a given degree
  572. adjustBearing: function(delta, callback) {
  573. callback = callback || function() {};
  574. if (delta === 0) {
  575. return this;
  576. }
  577.  
  578. this
  579. .each(function() {
  580. methods.setBearing.apply($(this), [$(this).data("roundabout").bearing + delta]);
  581. });
  582.  
  583. callback.apply(this);
  584. return this;
  585. },
  586.  
  587. // setTilt
  588. // changes the tilt of the roundabout
  589. setTilt: function(tilt, callback) {
  590. callback = callback || function() {};
  591.  
  592. this
  593. .each(function() {
  594. $(this).data("roundabout").tilt = tilt;
  595. methods.updateChildren.apply($(this));
  596. });
  597.  
  598. // call callback if one was given
  599. callback.apply(this);
  600. return this;
  601. },
  602.  
  603. // adjustTilt
  604. // changes the tilt of the roundabout
  605. adjustTilt: function(delta, callback) {
  606. callback = callback || function() {};
  607.  
  608. this
  609. .each(function() {
  610. methods.setTilt.apply($(this), [$(this).data("roundabout").tilt + delta]);
  611. });
  612.  
  613. callback.apply(this);
  614. return this;
  615. },
  616.  
  617. // animation
  618. // -----------------------------------------------------------------------
  619.  
  620. // animateToBearing
  621. // animates the roundabout to a given bearing, all animations come through here
  622. animateToBearing: function(bearing, duration, easing, passedData, callback) {
  623. var now = (new Date()).getTime();
  624.  
  625. callback = callback || function() {};
  626.  
  627. // find callback function in arguments
  628. if ($.isFunction(passedData)) {
  629. callback = passedData;
  630. passedData = null;
  631. } else if ($.isFunction(easing)) {
  632. callback = easing;
  633. easing = null;
  634. } else if ($.isFunction(duration)) {
  635. callback = duration;
  636. duration = null;
  637. }
  638.  
  639. this
  640. .each(function() {
  641. var timer, easingFn, newBearing,
  642. self = $(this),
  643. data = self.data("roundabout"),
  644. thisDuration = (!duration) ? data.duration : duration,
  645. thisEasingType = (easing) ? easing : data.easing || "swing";
  646.  
  647. // is this your first time?
  648. if (!passedData) {
  649. passedData = {
  650. timerStart: now,
  651. start: data.bearing,
  652. totalTime: thisDuration
  653. };
  654. }
  655.  
  656. // update the timer
  657. timer = now - passedData.timerStart;
  658.  
  659. if (data.stopAnimation) {
  660. methods.allowAnimation.apply(self);
  661. data.animating = false;
  662. return;
  663. }
  664.  
  665. // we need to animate more
  666. if (timer < thisDuration) {
  667. if (!data.animating) {
  668. self.trigger("animationStart");
  669. }
  670.  
  671. data.animating = true;
  672.  
  673. if (typeof $.easing.def === "string") {
  674. easingFn = $.easing[thisEasingType] || $.easing[$.easing.def];
  675. newBearing = easingFn(null, timer, passedData.start, bearing - passedData.start, passedData.totalTime);
  676. } else {
  677. newBearing = $.easing[thisEasingType]((timer / passedData.totalTime), timer, passedData.start, bearing - passedData.start, passedData.totalTime);
  678. }
  679.  
  680. // fixes issue #24, animation changed as of jQuery 1.7.2
  681. // also addresses issue #29, using easing breaks "linear"
  682. if (methods.compareVersions.apply(null, [$().jquery, "1.7.2"]) >= 0 && !($.easing["easeOutBack"])) {
  683. newBearing = passedData.start + ((bearing - passedData.start) * newBearing);
  684. }
  685.  
  686. newBearing = methods.normalize.apply(null, [newBearing]);
  687. data.dragBearing = newBearing;
  688.  
  689. methods.setBearing.apply(self, [newBearing, function() {
  690. setTimeout(function() { // done with a timeout so that each step is displayed
  691. methods.animateToBearing.apply(self, [bearing, thisDuration, thisEasingType, passedData, callback]);
  692. }, 0);
  693. }]);
  694.  
  695. // we're done animating
  696. } else {
  697. data.lastAnimationStep = true;
  698.  
  699. bearing = methods.normalize.apply(null, [bearing]);
  700. methods.setBearing.apply(self, [bearing, function() {
  701. self.trigger("animationEnd");
  702. }]);
  703. data.animating = false;
  704. data.lastAnimationStep = false;
  705. data.dragBearing = bearing;
  706.  
  707. callback.apply(self);
  708. }
  709. });
  710.  
  711. return this;
  712. },
  713.  
  714. // animateToNearbyChild
  715. // animates roundabout to a nearby child
  716. animateToNearbyChild: function(passedArgs, which) {
  717. var duration = passedArgs[0],
  718. easing = passedArgs[1],
  719. callback = passedArgs[2] || function() {};
  720.  
  721. // find callback
  722. if ($.isFunction(easing)) {
  723. callback = easing;
  724. easing = null;
  725. } else if ($.isFunction(duration)) {
  726. callback = duration;
  727. duration = null;
  728. }
  729.  
  730. return this
  731. .each(function() {
  732. var j, range,
  733. self = $(this),
  734. data = self.data("roundabout"),
  735. bearing = (!data.reflect) ? data.bearing % 360 : data.bearing,
  736. length = self.children(data.childSelector).length;
  737.  
  738. if (!data.animating) {
  739. // reflecting, not moving to previous || not reflecting, moving to next
  740. if ((data.reflect && which === "previous") || (!data.reflect && which === "next")) {
  741. // slightly adjust for rounding issues
  742. bearing = (Math.abs(bearing) < data.floatComparisonThreshold) ? 360 : bearing;
  743.  
  744. // clockwise
  745. for (j = 0; j < length; j += 1) {
  746. range = {
  747. lower: (data.period * j),
  748. upper: (data.period * (j + 1))
  749. };
  750. range.upper = (j === length - 1) ? 360 : range.upper;
  751.  
  752. if (bearing <= Math.ceil(range.upper) && bearing >= Math.floor(range.lower)) {
  753. if (length === 2 && bearing === 360) {
  754. methods.animateToDelta.apply(self, [-180, duration, easing, callback]);
  755. } else {
  756. methods.animateBearingToFocus.apply(self, [range.lower, duration, easing, callback]);
  757. }
  758. break;
  759. }
  760. }
  761. } else {
  762. // slightly adjust for rounding issues
  763. bearing = (Math.abs(bearing) < data.floatComparisonThreshold || 360 - Math.abs(bearing) < data.floatComparisonThreshold) ? 0 : bearing;
  764.  
  765. // counterclockwise
  766. for (j = length - 1; j >= 0; j -= 1) {
  767. range = {
  768. lower: data.period * j,
  769. upper: data.period * (j + 1)
  770. };
  771. range.upper = (j === length - 1) ? 360 : range.upper;
  772.  
  773. if (bearing >= Math.floor(range.lower) && bearing < Math.ceil(range.upper)) {
  774. if (length === 2 && bearing === 360) {
  775. methods.animateToDelta.apply(self, [180, duration, easing, callback]);
  776. } else {
  777. methods.animateBearingToFocus.apply(self, [range.upper, duration, easing, callback]);
  778. }
  779. break;
  780. }
  781. }
  782. }
  783. }
  784. });
  785. },
  786.  
  787. // animateToNearestChild
  788. // animates roundabout to the nearest child
  789. animateToNearestChild: function(duration, easing, callback) {
  790. callback = callback || function() {};
  791.  
  792. // find callback
  793. if ($.isFunction(easing)) {
  794. callback = easing;
  795. easing = null;
  796. } else if ($.isFunction(duration)) {
  797. callback = duration;
  798. duration = null;
  799. }
  800.  
  801. return this
  802. .each(function() {
  803. var nearest = methods.getNearestChild.apply($(this));
  804. methods.animateToChild.apply($(this), [nearest, duration, easing, callback]);
  805. });
  806. },
  807.  
  808. // animateToChild
  809. // animates roundabout to a given child position
  810. animateToChild: function(childPosition, duration, easing, callback) {
  811. callback = callback || function() {};
  812.  
  813. // find callback
  814. if ($.isFunction(easing)) {
  815. callback = easing;
  816. easing = null;
  817. } else if ($.isFunction(duration)) {
  818. callback = duration;
  819. duration = null;
  820. }
  821.  
  822. return this
  823. .each(function() {
  824. var child,
  825. self = $(this),
  826. data = self.data("roundabout");
  827.  
  828. if (data.childInFocus !== childPosition && !data.animating) {
  829. child = self.children(data.childSelector).eq(childPosition);
  830. methods.animateBearingToFocus.apply(self, [child.data("roundabout").degrees, duration, easing, callback]);
  831. }
  832. });
  833. },
  834.  
  835. // animateToNextChild
  836. // animates roundabout to the next child
  837. animateToNextChild: function(duration, easing, callback) {
  838. return methods.animateToNearbyChild.apply(this, [arguments, "next"]);
  839. },
  840.  
  841. // animateToPreviousChild
  842. // animates roundabout to the preious child
  843. animateToPreviousChild: function(duration, easing, callback) {
  844. return methods.animateToNearbyChild.apply(this, [arguments, "previous"]);
  845. },
  846.  
  847. // animateToDelta
  848. // animates roundabout to a given delta (in degrees)
  849. animateToDelta: function(degrees, duration, easing, callback) {
  850. callback = callback || function() {};
  851.  
  852. // find callback
  853. if ($.isFunction(easing)) {
  854. callback = easing;
  855. easing = null;
  856. } else if ($.isFunction(duration)) {
  857. callback = duration;
  858. duration = null;
  859. }
  860.  
  861. return this
  862. .each(function() {
  863. var delta = $(this).data("roundabout").bearing + degrees;
  864. methods.animateToBearing.apply($(this), [delta, duration, easing, callback]);
  865. });
  866. },
  867.  
  868. // animateBearingToFocus
  869. // animates roundabout to bring a given angle into focus
  870. animateBearingToFocus: function(degrees, duration, easing, callback) {
  871. callback = callback || function() {};
  872.  
  873. // find callback
  874. if ($.isFunction(easing)) {
  875. callback = easing;
  876. easing = null;
  877. } else if ($.isFunction(duration)) {
  878. callback = duration;
  879. duration = null;
  880. }
  881.  
  882. return this
  883. .each(function() {
  884. var delta = $(this).data("roundabout").bearing - degrees;
  885. delta = (Math.abs(360 - delta) < Math.abs(delta)) ? 360 - delta : -delta;
  886. delta = (delta > 180) ? -(360 - delta) : delta;
  887.  
  888. if (delta !== 0) {
  889. methods.animateToDelta.apply($(this), [delta, duration, easing, callback]);
  890. }
  891. });
  892. },
  893.  
  894. // stopAnimation
  895. // if an animation is currently in progress, stop it
  896. stopAnimation: function() {
  897. return this
  898. .each(function() {
  899. $(this).data("roundabout").stopAnimation = true;
  900. });
  901. },
  902.  
  903. // allowAnimation
  904. // clears the stop-animation hold placed by stopAnimation
  905. allowAnimation: function() {
  906. return this
  907. .each(function() {
  908. $(this).data("roundabout").stopAnimation = false;
  909. });
  910. },
  911.  
  912. // autoplay
  913. // -----------------------------------------------------------------------
  914.  
  915. // startAutoplay
  916. // starts autoplaying this roundabout
  917. startAutoplay: function(callback) {
  918. return this
  919. .each(function() {
  920. var self = $(this),
  921. data = self.data("roundabout");
  922.  
  923. callback = callback || data.autoplayCallback || function() {};
  924.  
  925. clearInterval(data.autoplayInterval);
  926. data.autoplayInterval = setInterval(function() {
  927. methods.animateToNextChild.apply(self, [callback]);
  928. }, data.autoplayDuration);
  929. data.autoplayIsRunning = true;
  930.  
  931. self.trigger("autoplayStart");
  932. });
  933. },
  934.  
  935. // stopAutoplay
  936. // stops autoplaying this roundabout
  937. stopAutoplay: function(keepAutoplayBindings) {
  938. return this
  939. .each(function() {
  940. clearInterval($(this).data("roundabout").autoplayInterval);
  941. $(this).data("roundabout").autoplayInterval = null;
  942. $(this).data("roundabout").autoplayIsRunning = false;
  943.  
  944. // this will prevent autoplayPauseOnHover from restarting autoplay
  945. if (!keepAutoplayBindings) {
  946. $(this).unbind(".autoplay");
  947. }
  948.  
  949. $(this).trigger("autoplayStop");
  950. });
  951. },
  952.  
  953. // toggleAutoplay
  954. // toggles autoplay pause/resume
  955. toggleAutoplay: function(callback) {
  956. return this
  957. .each(function() {
  958. var self = $(this),
  959. data = self.data("roundabout");
  960.  
  961. callback = callback || data.autoplayCallback || function() {};
  962.  
  963. if (!methods.isAutoplaying.apply($(this))) {
  964. methods.startAutoplay.apply($(this), [callback]);
  965. } else {
  966. methods.stopAutoplay.apply($(this), [callback]);
  967. }
  968. });
  969. },
  970.  
  971. // isAutoplaying
  972. // is this roundabout currently autoplaying?
  973. isAutoplaying: function() {
  974. return (this.data("roundabout").autoplayIsRunning);
  975. },
  976.  
  977. // changeAutoplayDuration
  978. // stops the autoplay, changes the duration, restarts autoplay
  979. changeAutoplayDuration: function(duration) {
  980. return this
  981. .each(function() {
  982. var self = $(this),
  983. data = self.data("roundabout");
  984.  
  985. data.autoplayDuration = duration;
  986.  
  987. if (methods.isAutoplaying.apply(self)) {
  988. methods.stopAutoplay.apply(self);
  989. setTimeout(function() {
  990. methods.startAutoplay.apply(self);
  991. }, 10);
  992. }
  993. });
  994. },
  995.  
  996. // helpers
  997. // -----------------------------------------------------------------------
  998.  
  999. // normalize
  1000. // regulates degrees to be >= 0.0 and < 360
  1001. normalize: function(degrees) {
  1002. var inRange = degrees % 360.0;
  1003. return (inRange < 0) ? 360 + inRange : inRange;
  1004. },
  1005.  
  1006. // normalizeRad
  1007. // regulates radians to be >= 0 and < Math.PI * 2
  1008. normalizeRad: function(radians) {
  1009. while (radians < 0) {
  1010. radians += (Math.PI * 2);
  1011. }
  1012.  
  1013. while (radians > (Math.PI * 2)) {
  1014. radians -= (Math.PI * 2);
  1015. }
  1016.  
  1017. return radians;
  1018. },
  1019.  
  1020. // isChildBackDegreesBetween
  1021. // checks that a given child's backDegrees is between two values
  1022. isChildBackDegreesBetween: function(value1, value2) {
  1023. var backDegrees = $(this).data("roundabout").backDegrees;
  1024.  
  1025. if (value1 > value2) {
  1026. return (backDegrees >= value2 && backDegrees < value1);
  1027. } else {
  1028. return (backDegrees < value2 && backDegrees >= value1);
  1029. }
  1030. },
  1031.  
  1032. // getAnimateToMethod
  1033. // takes a user-entered option and maps it to an animation method
  1034. getAnimateToMethod: function(effect) {
  1035. effect = effect.toLowerCase();
  1036.  
  1037. if (effect === "next") {
  1038. return "animateToNextChild";
  1039. } else if (effect === "previous") {
  1040. return "animateToPreviousChild";
  1041. }
  1042.  
  1043. // default selection
  1044. return "animateToNearestChild";
  1045. },
  1046.  
  1047. // relayoutChildren
  1048. // lays out children again with new contextual information
  1049. relayoutChildren: function() {
  1050. return this
  1051. .each(function() {
  1052. var self = $(this),
  1053. settings = $.extend({}, self.data("roundabout"));
  1054.  
  1055. settings.startingChild = self.data("roundabout").childInFocus;
  1056. methods.init.apply(self, [settings, null, true]);
  1057. });
  1058. },
  1059.  
  1060. // getNearestChild
  1061. // gets the nearest child from the current bearing
  1062. getNearestChild: function() {
  1063. var self = $(this),
  1064. data = self.data("roundabout"),
  1065. length = self.children(data.childSelector).length;
  1066.  
  1067. if (!data.reflect) {
  1068. return ((length) - (Math.round(data.bearing / data.period) % length)) % length;
  1069. } else {
  1070. return (Math.round(data.bearing / data.period) % length);
  1071. }
  1072. },
  1073.  
  1074. // degToRad
  1075. // converts degrees to radians
  1076. degToRad: function(degrees) {
  1077. return methods.normalize.apply(null, [degrees]) * Math.PI / 180.0;
  1078. },
  1079.  
  1080. // getPlacement
  1081. // returns the starting degree for a given child
  1082. getPlacement: function(child) {
  1083. var data = this.data("roundabout");
  1084. return (!data.reflect) ? 360.0 - (data.period * child) : data.period * child;
  1085. },
  1086.  
  1087. // isInFocus
  1088. // is this roundabout currently in focus?
  1089. isInFocus: function(degrees) {
  1090. var diff,
  1091. self = this,
  1092. data = self.data("roundabout"),
  1093. bearing = methods.normalize.apply(null, [data.bearing]);
  1094.  
  1095. degrees = methods.normalize.apply(null, [degrees]);
  1096. diff = Math.abs(bearing - degrees);
  1097.  
  1098. // this calculation gives a bit of room for javascript float rounding
  1099. // errors, it looks on both 0deg and 360deg ends of the spectrum
  1100. return (diff <= data.floatComparisonThreshold || diff >= 360 - data.floatComparisonThreshold);
  1101. },
  1102.  
  1103. // getChildInFocus
  1104. // returns the current child in focus, or false if none are in focus
  1105. getChildInFocus: function() {
  1106. var data = $(this).data("roundabout");
  1107.  
  1108. return (data.childInFocus > -1) ? data.childInFocus : false;
  1109. },
  1110.  
  1111. // compareVersions
  1112. // compares a given version string with another
  1113. compareVersions: function(baseVersion, compareVersion) {
  1114. var i,
  1115. base = baseVersion.split(/\./i),
  1116. compare = compareVersion.split(/\./i),
  1117. maxVersionSegmentLength = (base.length > compare.length) ? base.length : compare.length;
  1118.  
  1119. for (i = 0; i <= maxVersionSegmentLength; i++) {
  1120. if (base[i] && !compare[i] && parseInt(base[i], 10) !== 0) {
  1121. // base is higher
  1122. return 1;
  1123. } else if (compare[i] && !base[i] && parseInt(compare[i], 10) !== 0) {
  1124. // compare is higher
  1125. return -1;
  1126. } else if (base[i] === compare[i]) {
  1127. // these are the same, next
  1128. continue;
  1129. }
  1130.  
  1131. if (base[i] && compare[i]) {
  1132. if (parseInt(base[i], 10) > parseInt(compare[i], 10)) {
  1133. // base is higher
  1134. return 1;
  1135. } else {
  1136. // compare is higher
  1137. return -1;
  1138. }
  1139. }
  1140. }
  1141.  
  1142. // nothing was triggered, versions are the same
  1143. return 0;
  1144. }
  1145. };
  1146.  
  1147. // start the plugin
  1148. $.fn.roundabout = function(method) {
  1149. if (methods[method]) {
  1150. return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
  1151. } else if (typeof method === "object" || $.isFunction(method) || !method) {
  1152. return methods.init.apply(this, arguments);
  1153. } else {
  1154. $.error("Method " + method + " does not exist for jQuery.roundabout.");
  1155. }
  1156. };
  1157. })(jQuery);
<!DOCTYPE html>
  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <title>jQuery左右旋转幻灯片特效 - 【科e互联】</title>
  <meta name="keywords" content="jQuery插件,幻灯片特效,左右旋转,3D旋转,旋转插件" />
  <meta name="description" content="一款jQuery左右旋转幻灯片网页特效,jquery.roundabout.js是一款超棒的左右3D旋转式幻灯片jQuery插件。">
  <link href="css/demos.css" rel="stylesheet" />
  </head>
  <body class="keBody">
  <h1 class="keTitle">jQuery左右旋转幻灯片特效</h1>
  <div class="kePublic">
  <!--效果html开始-->
  <ul class="mmul">
  <li><img src="images/firefox.png" alt="firefox" /></li>
  <li><img src="images/ps.png" alt="ps" /></li>
  <li><img src="images/word.png" alt="word" /></li>
  <li><img src="images/youtube.png" alt="youtube" /></li>
  <li><img src="images/skype.png" alt="skype" /></li>
  </ul>
  <script src="js/jquery.min.js"></script>
  <script src="js/jquery.roundabout.js"></script>
  <script>
  $(document).ready(function() {
  $('.mmul').roundabout();
  });
  </script>
  <!--效果html结束-->
  <div class="clear"></div>
  </div>
  <div class="keBottom">
  <p class="keTxtP">科e互联网页特效集锦---更多特效请访问 <a class="keUrl" href="http://www.internetke.com" target="_blank">www.internetke.com</a></p>
  <p class="keTxtP">本站导航:
  <a href="http://www.internetke.com/" target="_blank" class="cor_bs">网站建设</a> |
  <a href="http://www.internetke.com/material/" target="_blank" class="cor_bs">网页素材</a> |
  <a href="http://www.internetke.com/effects/" target="_blank" class="cor_bs">网页特效</a> |
  <a href="http://www.internetke.com/share/" target="_blank" class="cor_bs">设计分享</a> |
  <a href="http://www.internetke.com/tutorial/" target="_blank" class="cor_bs">建站教程</a> |
  <a href="http://www.internetke.com/model/" target="_blank" class="cor_bs">网站模版</a> |
  <a href="http://www.internetke.com/appreciate/" target="_blank" class="cor_bs">酷站赏析</a>
  </p>
   
  </body>
  </html>

roundabout旋转幻灯的更多相关文章

  1. jquery.roundabout.js图片叠加3D旋转

    Roundabout是一个jQuery插件能够将一组静态HTML元素转换成可以灵活定制具有类似于转盘旋转效果的交互区域.有多种旋转形状可供选择.官方说明:roundabout.js是一个jQuery插 ...

  2. jquery roundabout幻灯片插件3d图片切换支持图片旋转切换滚动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. jquery.roundabout.js图片叠加3D旋转插件多功能图片翻转切换效果

    http://www.17sucai.com/pins/4880.html DEMO演示地址:http://www.17sucai.com/pins/demoshow/4880

  4. Carousel 旋转画廊特效的疑难杂症

    疑难杂症 该画廊特效的特点就是前后元素有层级关系. 我想很多人应该看过或者用过这个插件carousel.js,网上也有相关的教程.不知道这个插件的原型是哪个,有知道的朋友可以告诉我. 该插件相对完美, ...

  5. impress.js 一个创建在线幻灯的js库

    真的好奇怪,我居然会写前端技术的博客.没有办法的,最近实习,看的大多是前端.所以今天就用这个来练练手了. Impress.js 是一个非常棒的用来创建在线演示的Javascript库.它基于CSS3转 ...

  6. Canvas绘图之平移translate、旋转rotate、缩放scale

    画布操作介绍 画布绘图的环境通过translate(),scale(),rotate(), setTransform()和transform()来改变,它们会对画布的变换矩阵产生影响. 函数 方法 描 ...

  7. jQuery可拖拽3D万花筒旋转特效

    这是一个使用了CSS3立体效果的强大特效,本特效使用jQuery跟CSS3 transform来实现在用户鼠标按下拖动时,环形图片墙可以跟随鼠标进行3D旋转动画. 效果体验:http://hovert ...

  8. css3制作旋转动画

    现在的css3真是强大,之前很多动画都是用jq来实现,但是css3制作的动画要比jq实现起来简单很多,今天呢,我自己也写了一个css旋转动画和大家分享.效果如下面的图片 思路:1.制作之前呢,我们先来 ...

  9. Android 旋转屏幕--处理Activity与AsyncTask的最佳解决方案

    一.概述 运行时变更就是设备在运行时发生变化(例如屏幕旋转.键盘可用性及语言).发生这些变化,Android会重启Activity,这时就需要保存activity的状态及与activity相关的任务, ...

随机推荐

  1. CSDN怎么转载别人的博客

    在参考"如何快速转载CSDN中的博客"后,由于自己不懂html以及markdown相关知识,所以花了一些时间来弄明白怎么转载博客,以下为转载CSDN博客步骤和一些知识小笔记. 参考 ...

  2. 洛谷 P1280 尼克的任务 (线性DP)

    题意概括 线性资源分配的问题,因为空闲的时间大小看后面的时间(反正感觉这个就是个套路)所以从后往前DP. 转移方程 如果当前时刻没有工作 f[i]=f[i+1]+1 如果当前时刻有工作 f[i]=ma ...

  3. 第一个Maven工程的目录结构和文件内容及联网问题

    [第一个Maven工程] ①目录结构 Hello |---src |---|---main |---|---|---java |---|---|---resources |---|---test |- ...

  4. Jboss 服务器SSL证书安装指南

    1.获取服务器证书 将证书签发邮件中的从BEGIN到 END结束的服务器证书内容(包括“-----BEGIN CERTIFICATE-----”和“-----END CERTIFICATE-----” ...

  5. noip模拟赛 蒜头君打地鼠

    分析:直接一个一个地去暴力枚举分数比较少,我们需要一种比较快的统计一定空间内1的数量,标准做法是前缀和,但是二维前缀和维护的是一个矩形内的值,这个是旋转过的该怎么办?可以把图旋转45°,不过这样比较考 ...

  6. 使用C#执行PowerShell命令

    按照网上的教程配置会发生SSL链接错误 该文章的最后使用了SSL来保证账户在连接服务器的时候不发生账户认证错误,但是我经过测试发现这个是不可行的,有一种更为简单的方法 首先要对服务器进行winrm设置 ...

  7. Junit4使用总结

    常用注解 @Before:初始化方法,在任何一个测试方法执行之前,必须执行的代码. @After:释放资源,在任何一个测试方法执行之后,需要进行的收尾工作.   @Test:测试方法,表明这是一个测试 ...

  8. Ubuntu 16.04安装NASM汇编IDE-SASM

    在Linux下,尤其是Ubuntu,SASM工具应该是用来开发汇编最好用的IDE,小巧且支持调试.支持的编译器有:NASM, MASM, GAS, FASM. 安装步骤: 下载: http://dow ...

  9. C++中const引用的是对象的时候只能调用该对象的f()const方法

    const引用的作用: 1. 避免不必要的复制.  2. 限制不能修改对象. const 引用的是对象时只能访问该对象的const 函数  例: class A { public: void cons ...

  10. jeewx 微信管家 - 举办商业版本号免费试用活动

    jeewx 微信管家 举办商业版本号免费试用活动 1,关注微信账号:jeecg_scott 2.输入:"jeewx商业版本号试用活动: 你的邮箱(比如:zhangsan@11.com)&qu ...