├── images ├── loading.gif └── media_icon.png ├── upload ├── MPreview_DOC_1.jpg └── MPreview_PPT_1.jpg ├── data.json ├── PPT.html ├── index.html ├── css ├── base.css └── MPreview.css ├── api.php ├── README.md └── js ├── MPreviewPPT.js └── MPreview.js /images/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/MPreview/HEAD/images/loading.gif -------------------------------------------------------------------------------- /images/media_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/MPreview/HEAD/images/media_icon.png -------------------------------------------------------------------------------- /upload/MPreview_DOC_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/MPreview/HEAD/upload/MPreview_DOC_1.jpg -------------------------------------------------------------------------------- /upload/MPreview_PPT_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webjyh/MPreview/HEAD/upload/MPreview_PPT_1.jpg -------------------------------------------------------------------------------- /data.json: -------------------------------------------------------------------------------- 1 | { 2 | "code": 1, 3 | "imgs": [ 4 | "./upload/1.png", 5 | "./upload/2.png", 6 | "./upload/3.png", 7 | "./upload/4.png", 8 | "./upload/5.png", 9 | "./upload/1.png?ver=1.0.0", 10 | "./upload/2.png?ver=1.0.0", 11 | "./upload/3.png?ver=1.0.0", 12 | "./upload/4.png?ver=1.0.0", 13 | "./upload/5.png?ver=1.0.0", 14 | "./upload/1.png?ver=2.0.0", 15 | "./upload/2.png?ver=2.0.0", 16 | "./upload/3.png?ver=2.0.0", 17 | "./upload/4.png?ver=2.0.0", 18 | "./upload/5.png?ver=2.0.0", 19 | "./upload/1.png?ver=3.0.0", 20 | "./upload/2.png?ver=3.0.0", 21 | "./upload/3.png?ver=3.0.0", 22 | ] 23 | } -------------------------------------------------------------------------------- /PPT.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MPreview PPT格式预览 6 | 7 | 8 | 9 | 10 |

Word 版  PPT 版

11 |
12 |
13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | MPreview Word格式预览 6 | 7 | 8 | 9 | 10 |

Word 版  PPT 版

11 |
12 |
13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /css/base.css: -------------------------------------------------------------------------------- 1 | /* reset */ 2 | html, body, div, span, applet, object, iframe, 3 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 4 | a, abbr, acronym, address, big, cite, code, 5 | del, dfn, em, img, ins, kbd, q, s, samp, 6 | small, strike, strong, sub, sup, tt, var, 7 | b, u, i, center, 8 | dl, dt, dd, ol, ul, li, 9 | fieldset, form, label, legend, 10 | table, caption, tbody, tfoot, thead, tr, th, td, 11 | article, aside, canvas, details, embed, 12 | figure, figcaption, footer, header, hgroup, 13 | menu, nav, output, ruby, section, summary, 14 | time, mark, audio, video { 15 | margin: 0; 16 | padding: 0; 17 | border: 0; 18 | font-size: 100%; 19 | font: inherit; 20 | vertical-align: baseline; 21 | } 22 | /* HTML5 display-role reset for older browsers */ 23 | article, aside, details, figcaption, figure, 24 | footer, header, hgroup, menu, nav, section { 25 | display: block; 26 | } 27 | body { 28 | line-height: 1; 29 | } 30 | ol, ul { 31 | list-style: none; 32 | } 33 | blockquote, q { 34 | quotes: none; 35 | } 36 | blockquote:before, blockquote:after, 37 | q:before, q:after { 38 | content: ''; 39 | content: none; 40 | } 41 | table { 42 | border-collapse: collapse; 43 | border-spacing: 0; 44 | } 45 | 46 | /* common */ 47 | body { font-size: 12px; line-height: 1.6; color: #333; font-family:"Microsoft Yahei", Arial; background: #F2F2F2; } 48 | .wrapper { width: 1000px; margin: 50px auto; } 49 | .doc { width: 1000px; height: 800px; margin: 0px auto; } 50 | .ppt { width: 1000px; height: 800px; margin: 0px auto; } -------------------------------------------------------------------------------- /api.php: -------------------------------------------------------------------------------- 1 | 1, 8 | 'imgs' => array( 9 | './upload/MPreview_DOC_1.jpg?ver=1.0.0', 10 | './upload/MPreview_DOC_1.jpg?ver=2.0.0', 11 | './upload/MPreview_DOC_1.jpg?ver=3.0.0', 12 | './upload/MPreview_DOC_1.jpg?ver=4.0.0', 13 | './upload/MPreview_DOC_1.jpg?ver=5.0.0', 14 | './upload/MPreview_DOC_1.jpg?ver=6.0.0', 15 | './upload/MPreview_DOC_1.jpg?ver=7.0.0', 16 | './upload/MPreview_DOC_1.jpg?ver=8.0.0' 17 | ) 18 | ); 19 | } else { 20 | $JSON = array( 21 | 'code' => 1, 22 | 'imgs' => array( 23 | './upload/MPreview_PPT_1.jpg?ver=1.0.0', 24 | './upload/MPreview_PPT_1.jpg?ver=2.0.0', 25 | './upload/MPreview_PPT_1.jpg?ver=3.0.0', 26 | './upload/MPreview_PPT_1.jpg?ver=4.0.0', 27 | './upload/MPreview_PPT_1.jpg?ver=5.0.0', 28 | './upload/MPreview_PPT_1.jpg?ver=6.0.0', 29 | './upload/MPreview_PPT_1.jpg?ver=7.0.0', 30 | './upload/MPreview_PPT_1.jpg?ver=8.0.0', 31 | ) 32 | ); 33 | } 34 | 35 | header('Content-type: application/json'); 36 | if ( !empty( $_GET['callback'] ) ){ 37 | echo $callback.'('.json_encode($JSON).')'; 38 | } else { 39 | echo json_encode($JSON); 40 | } 41 | ?> -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MPreview.js 2 | 3 | Word,PPT 文档预览组件(图片预览组件) 4 | 5 | 移动端请移步 [MPreview.mobile](https://github.com/webjyh/MPreview.mobile) 6 | 7 | ## Demo参考 8 | 9 | 10 | 11 | ### 特此说明 12 | 此插件是我在项目开发中而制作,其只适用于其项目,如须使用须注意,提供的图片须有较大的宽高。 13 | 14 | ### 插件说明 15 | 1. 此插件需要由服务端提供转换好的Word图片或PPT图片来进行预览。 16 | 2. 插件需要 jQuery1.9+ 库。支持IE7+,FireFox,Chrome。 17 | 3. 初始化调用插件的外容器,只需设置宽高样式即可,无需其它设置。 18 | 4. 因插件是刚开始阶段,一些功能并未能完善全,如:放大,缩小功能。 19 | 5. 插件中一些滚动的计算是硬算出来的(勿喷)。 20 | 21 | ### 插件特性 22 | 1. 服务端将全数据返回(图像地址的数组集合),由插件进行分割加载。 23 | 2. 支持滚动条拖拽滚动及全屏预览。 24 | 3. 支持上一页,下一页功能。 25 | 26 | ### 目录结构说明 27 | ``` 28 | MPreview/ 29 | ├── css/ 30 | │ ├── base.css (重置样式) 31 | │ └── MPreview.css (插件所需样式) 32 | ├── images/ 33 | │ ├── loading.gif (加载图片等待动画) 34 | │ └── media_icon.png (插件所需的icon) 35 | ├── js/ 36 | │ ├── MPreview.js (Word版 js) 37 | │ └── MPreviewPPT.js (PPT版 js) 38 | ├── upload/ 39 | │ ├── MPreview_DOC_1.jpg (测试图片) 40 | │ └── MPreview_PPT_1.jpg 41 | ├── api.php (数据请求的演示地址) 42 | ├── data.json (请求所返回的数据格式) 43 | ├── index.html (Word版 Demo) 44 | └── PPT.html (PPT版 Demo) 45 | 46 | PS: 务必一次性返回所有图片地址,插件将自动分割加载 47 | ``` 48 | 49 | ### 如何使用 50 | ```html 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
60 | 63 | ``` 64 | 65 | ### MPreview.js (Word 版) 参数说明 66 | ```javascript 67 | $('#doc').MPreview({ 68 | url: 'api.php?action=doc&callback=?', //url中包含callback则表示跨越请求,具体可参考$.getJSON(); 69 | data: null, //包含所有图片地址的数组,如填写则不发送Ajax。用于直接传入数据,方便调用。 70 | offset: 100, //每次滚动偏移多少像素,默认 100px 71 | loadSize: 5, //每次加载几张图片 72 | pageFix: 50, //当前页数判定的衡量标准 73 | scrollFix: 5, //当前默认滚动条距离外容器的边距 74 | minScrollHeight: 20 //当前滚动条按钮最小高度 75 | }); 76 | 77 | //关于 data 参数的用法 78 | var data = ['upload/1.jpg','upload/2.jpg','upload/3.jpg']; 79 | $('#doc').MPreview({ data: data }); 80 | ``` 81 | 82 | ### MPreviewPPT.js (PPT 版) 参数说明 83 | ```javascript 84 | $('#ppt').MPreviewPPT({ 85 | url: 'api.php?action=doc&callback=?', //url中包含callback则表示跨越请求,具体可参考$.getJSON(); 86 | data: null, //包含所有图片地址的数组,如填写则不发送Ajax。用于直接传入数据,方便调用。 87 | loadSize: 5, //每次加载几张图片 88 | scrollFix: 5, //当前默认滚动条距离外容器的边距 89 | minScrollHeight: 20 //当前滚动条按钮最小高度 90 | }); 91 | 92 | //关于 data 参数的用法 93 | var data = ['upload/1.jpg','upload/2.jpg','upload/3.jpg']; 94 | $('#ppt').MPreviewPPT({ data: data }); 95 | ``` 96 | 97 | ### 联系作者 98 | Blog: 99 | Weibo: 100 | -------------------------------------------------------------------------------- /css/MPreview.css: -------------------------------------------------------------------------------- 1 | /* Media-box */ 2 | .MPreview-box { position: relative; border: 1px solid #DDD; background: #FFF; height: 100%; } 3 | .MPreview-mediaPlay { position: absolute; top: 0; left: 0; right: 0; bottom: 31px; overflow: hidden; } 4 | 5 | /* Media-box common */ 6 | .MPreview-box img { vertical-align: top; margin: 0; padding: 0; border: 0; } 7 | 8 | .MPreview-box .hidden { display:none; } 9 | .MPreview-box .invisible { visibility:hidden; } 10 | 11 | .MPreview-box .cle { display:block; height:0; overflow:hidden; clear:both; } 12 | .MPreview-box .clefix:after, 13 | .MPreview-ppt .MPreview-mediaView:after { content:'\20'; display:block; height:0; clear:both; } 14 | .MPreview-box .clefix, 15 | .MPreview-ppt .MPreview-mediaView { *zoom:1; } 16 | 17 | /* Media-box .tool-bar */ 18 | .MPreview-box .tool-bar { position: absolute; width: 70px; height: 28px; padding-top: 10px; top: 0px; right: 0px; z-index: 28; -webkit-user-select: none; -moz-user-select: none; } 19 | .MPreview-box .MPreview-mediaPlay { width: 100%; overflow: hidden; -webkit-user-select: none; -moz-user-select: none; background:url(../images/loading.gif) no-repeat center center; } 20 | .MPreview-box .MPreview-mediaView { width: 100%; text-align: center; } 21 | .MPreview-box .MPreview-mediaView img { max-width: 100%; } 22 | .MPreview-box .tool-bar ul { padding-right: 20px; } 23 | .MPreview-box .tool-bar ul li { float: left; display: inline; margin: 0px 10px; } 24 | .MPreview-box .tool-bar ul li a { display: block; width: 26px; height: 26px; border: 1px solid transparent; border-radius: 3px; } 25 | .MPreview-box .tool-bar ul li a:hover { border-color: #DDD; } 26 | .MPreview-box .tool-bar ul li a span { position: relative; top:3px; left: 3px; display: block; overflow: hidden; width: 20px; height: 20px; text-indent: -9999px; font: 0 a; } 27 | 28 | /* Media-box => icon */ 29 | .MPreview-box .MPreview-zoomBig span, 30 | .MPreview-box .MPreview-zoomSmall span, 31 | .MPreview-box .MPreview-viewOne span, 32 | .MPreview-box .MPreview-viewMulti span, 33 | .MPreview-box .MPreview-fullScreen span, 34 | .MPreview-box .MPreview-exit span, 35 | .MPreview-box .MPreview-pagePrev span, 36 | .MPreview-box .MPreview-pageNext span, 37 | .MPreview-box .MPreview-arrowTop span, 38 | .MPreview-box .MPreview-arrowBottom span { background: url(../images/media_icon.png) no-repeat -9999px -9999px; } 39 | 40 | .MPreview-box .MPreview-zoomBig span { background-position: 0px -78px; } 41 | .MPreview-box .MPreview-zoomSmall span { background-position: -23px -78px; } 42 | .MPreview-box .MPreview-viewOne span { background-position: 1px -23px; } 43 | .MPreview-box .MPreview-viewMulti span { background-position: -22px -23px; } 44 | .MPreview-box .MPreview-fullScreen span { background-position: -82px -27px; } 45 | .MPreview-box .MPreview-exit span { background-position: -55px -27px; } 46 | .MPreview-box .MPreview-pagePrev span { background-position: -82px -55px; } 47 | .MPreview-box .MPreview-pageNext span { background-position: -82px -80px; } 48 | .MPreview-box .MPreview-zoomBig.current span { background-position: 0px -50px; } 49 | .MPreview-box .MPreview-zoomSmall.current span { background-position: -23px -50px; } 50 | .MPreview-box .MPreview-viewOne.current span { background-position: 1px 2px; } 51 | .MPreview-box .MPreview-viewMulti.current span { background-position: -22px 3px; } 52 | .MPreview-box .MPreview-fullScreen:hover span, 53 | .MPreview-box .MPreview-fullScreen.current span { background-position: -82px 0px; } 54 | .MPreview-box .MPreview-exit:hover span, 55 | .MPreview-box .MPreview-exit.current span { background-position: -55px 0px; } 56 | .MPreview-box .MPreview-pagePrev.current span { background-position: -55px -55px; } 57 | .MPreview-box .MPreview-pageNext.current span { background-position: -55px -80px; } 58 | .MPreview-box .MPreview-arrowTop span { background-position: -122px -5px; } 59 | .MPreview-box .MPreview-arrowBottom span { background-position: -122px -48px; } 60 | 61 | /* Media-box => scroll-bar */ 62 | .MPreview-box .MPreview-scrollBar { display: block; position: absolute; top: 0px; right: 0px; bottom: 31px; width: 15px; border-left: 1px solid #DDD; z-index: 30; } 63 | .MPreview-box .MPreview-scrollBar .MPreview-scrollBtn { z-index: 40; cursor: default; border-radius: 5px; position: absolute; top: 5px; left: -6px; width:9px; min-height: 20px; background: #DDD; border: 1px solid #ccc; } 64 | .MPreview-box .MPreview-scrollBar .MPreview-scrollBtn:active, 65 | .MPreview-box .MPreview-scrollBar .MPreview-scrollBtn.current { box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2); } 66 | 67 | /* Media-box => page-bar */ 68 | .MPreview-box .page-bar { position: absolute; z-index: 25; left: 0px; bottom: 0px; width: 100%; height: 30px; border-top: 1px solid #DDD; z-index: 25; -webkit-user-select: none; -moz-user-select: none; } 69 | .MPreview-box .page-bar .page-bar-inner { padding-top: 2px; margin: 0px auto; width: 160px; } 70 | .MPreview-box .page-bar .page-bar-inner a { float: left; display: inline; margin: 0px 10px; overflow: hidden; border: 1px solid #FFF; width: 16px; height: 14px; padding: 5px; border-radius: 3px; } 71 | .MPreview-box .page-bar .page-bar-inner a:hover { border: 1px solid #DDD; } 72 | .MPreview-box .page-bar .page-bar-inner a span { display: block; overflow: hidden; width: 16px; height: 14px; text-indent: -9999px; font: 0 a; } 73 | .MPreview-box .page-bar .MPreview-pageInput { float: left; background:#FFF; border: 1px solid #DDD; color: #666; border: 0; text-align: center; margin: 0px; width: 30px; height: 16px; line-height:16px; padding: 0px; padding-top: 4px; outline: 0; -webkit-user-select: none; -moz-user-select: none; } 74 | .MPreview-box .page-bar .MPreview-pageCount { float: left; width: 30px; height: 16px; text-align:center; padding-top: 3px; color: #666; font-size: 12px; } 75 | .MPreview-box .page-bar .MPreview-pageCount em { font-style: normal; color: #666; } 76 | 77 | /* Media-box => arrow */ 78 | .MPreview-box .MPreview-arrowUp, 79 | .MPreview-box .MPreview-arrowDown { position: absolute; width: 100%; height: 30px; top: 10px; left: 0px; z-index: 25; *background:url(about:blank) no-repeat; } 80 | .MPreview-box .MPreview-arrowDown { top: auto; bottom: 40px; } 81 | .MPreview-box .MPreview-arrowUp div, 82 | .MPreview-box .MPreview-arrowDown div { display: none; margin: 0px auto; width: 61px; height: 30px; overflow: hidden; font: 0 a; text-indent: -9999px; width: 61px; height: 100%; margin: 0px auto; overflow: hidden; } 83 | .MPreview-box .MPreview-arrowUp span, 84 | .MPreview-box .MPreview-arrowDown span { cursor: pointer; display: block; width: 100%; height: 100%; } 85 | .MPreview-box .MPreview-arrowUp a:hover, 86 | .MPreview-box .MPreview-arrowDown a:hover, { opacity: 0.8; filter:alpha(opacity=80); } 87 | .MPreview-box .media-dual .view { float: left; width: 50%; } 88 | 89 | /* Media-PPT */ 90 | .MPreview-ppt .MPreview-mediaPlay { bottom: 51px; } 91 | .MPreview-ppt .MPreview-mediaView { width: auto; height: 100%; text-align: left; -webkit-transition: all .5s; transition: all .5s; } 92 | .MPreview-ppt .MPreview-mediaView div { float: left; text-align: center; width: 100%; height: 100%; background: #FFF url(../images/loading.gif) no-repeat center center; } 93 | .MPreview-ppt .MPreview-mediaView img { max-width: 100%; max-height: 100%; } 94 | .MPreview-ppt .tool-bar { width: 50px; } 95 | .MPreview-ppt .MPreview-scrollBar { top: auto; bottom: 25px; width: 100%; height: 15px; border-left: 0 none; border-top: 1px solid #DDD; } 96 | .MPreview-ppt .MPreview-scrollBar .MPreview-scrollBtn { top: -6px; left: 5px; height: 9px; width: auto; min-width: 20px; min-height: 9px; } 97 | .MPreview-ppt .MPreview-arrowUp, 98 | .MPreview-ppt .MPreview-arrowDown { width: 30px; height: 100%; top: 0px; left: 10px; } 99 | .MPreview-ppt .MPreview-arrowDown { top: 0px; bottom: auto; left: auto; right: 10px; } 100 | .MPreview-ppt .MPreview-arrowUp div, 101 | .MPreview-ppt .MPreview-arrowDown div { position: absolute; top: 50%; margin-top: -30px; width: 30px; height: 61px; } 102 | .MPreview-ppt .MPreview-arrowUp span, 103 | .MPreview-ppt .MPreview-arrowDown span { width: 30px; height: 61px; } 104 | .MPreview-ppt .MPreview-arrowUp span { background-position: -206px 0px; } 105 | .MPreview-ppt .MPreview-arrowDown span { background-position: -249px 0px; } -------------------------------------------------------------------------------- /js/MPreviewPPT.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name MPreviewPPT.js 3 | * @desc 幻灯片预览。 4 | * @depend jQuery 1.7+, jQuery.MouseWheel.js 5 | * @author M.J 6 | * @date 2014-12-31 7 | * @URL http://webjyh.com 8 | * @reutn {jQuery} 9 | * @version 1.0.0 10 | * 11 | * @PS If you have any questions, please don't look for me, I don't know anything. thank you. 12 | */ 13 | (function($) { 14 | var MPreviewPPT = function(elem, option) { 15 | 16 | this.config = $.extend({}, this.defaults, option); 17 | 18 | this.elem = $(elem); //绑定的元素 19 | this.page = 0; //当前页 20 | this.bout = 0; //当前滚动的总次数 21 | this.btnOffset = 0; //当前滚动按钮每次滚动的距离 22 | this.length = 0; //当前数据的总长度也是总页数 23 | this.data = []; //当前所有数据 24 | this.W = []; //存放所有图片容器距外容器左边的距离 25 | this.DOM = this.__createDOM(); //当前所有元素DOM 26 | this.S = { //存放当前容器的宽,高 27 | width: this.elem.width(), 28 | height: this.elem.height(), 29 | viewWidth: this.DOM.mediaPlay.width(), 30 | viewHeight: this.DOM.mediaPlay.height() 31 | }; 32 | 33 | this.__init(); 34 | 35 | }; 36 | 37 | 38 | MPreviewPPT.prototype = { 39 | /** 40 | * 默认配置 41 | * @type {Object} 42 | */ 43 | defaults: { 44 | url: null, //默认Ajax地址 45 | data: null, //默认JSON 格式的数据,如填写则不发送Ajax,默认为 {Array} 类型 46 | loadSize: 5, //默认先创建几页 47 | scrollFix: 5, //当前默认滚动条距离外容器的边距 48 | minScrollWidth: 20 //当前滚动条按钮最小高度 49 | }, 50 | 51 | /** 52 | * @access private 53 | * @name 执行请求 54 | * @return {this} 55 | */ 56 | __init: function() { 57 | var _this = this, DOM = this.DOM; 58 | 59 | if ( this.config.data && this.config.data.length ){ 60 | this.__set(this.config.data).__create().__addEvent(); 61 | } else { 62 | $.getJSON(this.config.url) 63 | .done(function(data) { 64 | if (data.code > 0 && data.imgs.length) { 65 | _this.__set(data.imgs).__create().__addEvent(); 66 | } 67 | }) 68 | .fail(function() { 69 | alert('\u83b7\u53d6\u6570\u636e\u5931\u8d25'); 70 | }); 71 | } 72 | 73 | return this; 74 | }, 75 | 76 | /** 77 | * @access private 78 | * @name 首次数据进行设置 79 | * @return {Object} 80 | */ 81 | __set: function(data) { 82 | var DOM = this.DOM; 83 | 84 | this.data = data; 85 | this.length = data.length; 86 | 87 | DOM.pageInput.val('01'); 88 | DOM.pageCount.children('em').text(this.__formatNumber(this.length)); 89 | if (this.length > 1) DOM.pageNext.addClass('current'); 90 | 91 | return this; 92 | }, 93 | 94 | /** 95 | * @access private 96 | * @name 创建list 97 | * @return {Object} 98 | */ 99 | __create: function() { 100 | if (!this.data.length) return false; 101 | $(document).off('mousemove'); 102 | 103 | var i = 0, 104 | tpl = '', 105 | len = this.data.length, 106 | count = len > this.config.loadSize ? this.config.loadSize : len, 107 | DOM = this.DOM, 108 | size = this.__getSize(); 109 | 110 | // create TPL && delete array 111 | for (; i _this.bout) _this.page = _this.bout; 155 | 156 | var m = (typeof _this.W[_this.page-1] === 'undefined' ? 0 : _this.W[_this.page-1]), 157 | t = _this.page * _this.btnOffset; 158 | 159 | //设置滚动条 160 | DOM.mediaView.css('margin-left', -m); 161 | DOM.scrollBtn.css('left', t + (val == 'up' ? 0 : _this.config.scrollFix)); 162 | 163 | //设置当前页 164 | DOM.pageInput.val(_this.__formatNumber(_this.page+1)); 165 | 166 | //创建剩余数据 167 | _this.__createLastData(); 168 | 169 | }; 170 | 171 | //滚动事件绑定 172 | DOM.mediaPlay.off('mousewheel').on('mousewheel', function(event) { 173 | event.preventDefault(); 174 | scroll(event.deltaY < 0 ? 'up' : 'down'); 175 | }); 176 | 177 | return this; 178 | }, 179 | 180 | /** 181 | * @access private 182 | * @name 给元素绑定相应的事件 183 | * @return {Object} 184 | */ 185 | __addEvent: function() { 186 | var DOM = this.DOM, 187 | _this = this; 188 | 189 | var arrowOver = function(){ 190 | if (_this.page > 0) DOM.arrowTop.stop(true,true).fadeIn(); 191 | if (_this.page < _this.length -1) DOM.arrowBottom.stop(true,true).fadeIn(); 192 | }; 193 | 194 | var arrowOut = function(){ 195 | DOM.arrowTop.stop(true,true).fadeOut(); 196 | DOM.arrowBottom.stop(true,true).fadeOut(); 197 | }; 198 | 199 | //拖拽事件 200 | DOM.scrollBtn.on('mousedown', function(event) { _this.__dragStart(event) }); 201 | 202 | //页码按钮显示 203 | DOM.arrowUp.on('mouseover', arrowOver); 204 | DOM.arrowDown.on('mouseover', arrowOver); 205 | DOM.arrowUp.on('mouseout', arrowOut); 206 | DOM.arrowDown.on('mouseout', arrowOut); 207 | 208 | //上一页,下一页事件 209 | DOM.arrowTop.on('click', function() { _this.__pageJump('up') }); 210 | DOM.pagePrev.on('click', function() { _this.__pageJump('up') }); 211 | DOM.arrowBottom.on('click', function() { _this.__pageJump('down') }); 212 | DOM.pageNext.on('click', function() { _this.__pageJump('down') }); 213 | 214 | //全屏操作 215 | DOM.fullScreen.on('click', function() { _this.__full(); }); 216 | DOM.mediaPlay.on('dblclick', function() { _this.__full(); }); 217 | 218 | return this; 219 | }, 220 | 221 | /** 222 | * @access private 223 | * @name 滚动条拖拽开始 224 | * @return {Object} 225 | */ 226 | __dragStart: function(event) { 227 | var _this = this, 228 | DOM = this.DOM, 229 | fix = Math.floor(event.clientX - DOM.scrollBtn.offset().left); 230 | 231 | $(document).on('mousemove', function(event) { _this.__dragDrop(event, fix) }); 232 | $(document).off('mouseup').on('mouseup', function() { $(this).off('mousemove') }); 233 | }, 234 | 235 | /** 236 | * @access private 237 | * @name 滚动条拖拽 238 | * @return {Object} 239 | */ 240 | __dragDrop: function(event, fix) { 241 | var DOM = this.DOM, 242 | size = this.__getSize(), 243 | defaultLeft = parseInt(DOM.scrollBtn.css('left'), 10), 244 | W = Math.floor(event.clientX - DOM.scrollBtn.offset().left - fix + defaultLeft), 245 | minW = this.config.scrollFix, 246 | maxW = size.width - DOM.scrollBtn.outerWidth() - minW; 247 | 248 | if ( W < minW ) W = minW; 249 | if ( W > maxW ) W = maxW; 250 | 251 | //设置当前页 252 | var page = Math.floor(W / this.btnOffset), M; 253 | this.page = page > this.bout ? this.bout : page; 254 | M = (typeof this.W[this.page-1] === 'undefined' ? 0 : this.W[this.page-1]); 255 | 256 | DOM.mediaView.css('margin-left', -M ); 257 | DOM.scrollBtn.css('left', W); 258 | 259 | //设置当前页 260 | DOM.pageInput.val(this.__formatNumber(this.page+1)); 261 | 262 | //创建剩余数据 263 | this.__createLastData(); 264 | }, 265 | 266 | /** 267 | * @private private 268 | * @param 页码跳转 269 | * @return {null} 270 | */ 271 | __pageJump: function(val) { 272 | 273 | //设置当前页码 274 | val == 'up' ? --this.page : ++this.page; 275 | if (this.page < 0) this.page = 0; 276 | if (this.page > this.length-1 ) this.page = this.length-1; 277 | 278 | //计算滚动值 279 | var DOM = this.DOM, 280 | size = this.__getSize(), 281 | M = typeof this.W[this.page-1] === 'undefined' ? 0 : this.W[this.page-1], 282 | btnL = this.page * this.btnOffset, 283 | minW = this.config.scrollFix, 284 | maxW = size.width - DOM.scrollBtn.outerWidth() - minW; 285 | 286 | if ( btnL < minW ) btnL = minW; 287 | if ( btnL > maxW ) btnL = maxW; 288 | 289 | //设置DOM 290 | DOM.pageInput.val(this.__formatNumber(this.page+1)); 291 | DOM.mediaView.css('margin-left', -M); 292 | DOM.scrollBtn.css('left', btnL); 293 | 294 | //创建剩余数据 295 | this.__createLastData(); 296 | }, 297 | 298 | __full: function(bool) { 299 | var $elem = this.elem, 300 | DOM = this.DOM, 301 | _this = this, 302 | has = DOM.fullScreen.hasClass('MPreview-exit'), 303 | winH = $(window).outerHeight(); 304 | 305 | //用于 resize 事件 306 | if ( bool ) has = false; 307 | 308 | // 全屏样式 309 | var css = { 310 | position: has ? 'static' : 'fixed', 311 | top: has ? 'auto' : 0, 312 | left: has ? 'auto' : 0, 313 | zIndex: has ? '0' : 9999, 314 | width: has ? this.S.width : '100%', 315 | height: has ? this.S.height : winH 316 | }, 317 | bodyCss = { 318 | overflow: has ? 'auto' : 'hidden', 319 | width: has ? 'auto' : '100%', 320 | height: has ? 'auto': winH 321 | }; 322 | 323 | //设置DOM样式 324 | DOM.fullScreen[has ? 'removeClass' : 'addClass']('MPreview-exit').attr('title', has ? '\u5168\u5c4f' : '\u53d6\u6d88\u5168\u5c4f'); 325 | $('html').css(bodyCss); 326 | $elem.css(css); 327 | 328 | var winW = DOM.mediaPlay.width(); 329 | 330 | //重新设置全局数据 331 | this.W = []; 332 | DOM.mediaView.children('div').each(function() { 333 | $(this).width(has ? _this.S.viewWidth : winW); 334 | $(this).children('img').height(has ? _this.S.viewHeight : winH); 335 | var W = (typeof _this.W[_this.W.length-1] === 'undefined' ? 0 : _this.W[_this.W.length-1]) + (has ? _this.S.viewWidth : winW); 336 | _this.W.push(W); 337 | }); 338 | 339 | DOM.mediaView.css('width', this.W[this.W.length-1]); 340 | DOM.mediaView.css('margin-left', -(typeof this.W[this.page-1] === 'undefined' ? 0 : this.W[this.page-1])); 341 | this.__scrollBar(); 342 | 343 | //绑定事件 344 | if ( has ){ 345 | $(document).off('keyup'); 346 | $(window).off('resize'); 347 | } else { 348 | $(document).on('keyup', function(event){ if (event.which == 27) _this.__full(); }); 349 | $(window).off('resize').on('resize', function(){ _this.__full(true); }) 350 | } 351 | 352 | }, 353 | 354 | /** 355 | * @private private 356 | * @param 给单数字自动补零 357 | * @return {String} 358 | */ 359 | __formatNumber: function(val) { 360 | return val.toString().length < 2 ? '0' + val : val; 361 | }, 362 | 363 | /** 364 | * @private private 365 | * @param 设置页码样式及判断是否创建剩余数据 366 | * @return {null} 367 | */ 368 | __createLastData: function() { 369 | var DOM = this.DOM; 370 | 371 | DOM.pagePrev[this.page > 0 ? 'addClass' : 'removeClass']('current'); 372 | DOM.pageNext[this.page < this.length - 1 ? 'addClass' : 'removeClass']('current'); 373 | 374 | if ( this.page >= Math.floor( this.bout ) - 1) this.__create(); 375 | }, 376 | 377 | /** 378 | * @access private 379 | * @name 创建DOM,存储DOM 380 | * @return {Object} 381 | */ 382 | __createDOM: function() { 383 | var $elem = this.elem, DOM = {}, elem; 384 | 385 | DOM['wrap'] = $(MPreviewPPT.template).appendTo($elem); 386 | DOM.wrap.find('*').each(function() { 387 | var className = $(this).attr('class'); 388 | if ( className !== undefined && className.toString().indexOf('MPreview') > -1 ) { 389 | var name = className.replace(/icon /g, '').replace('MPreview-', ''); 390 | DOM[name] = $(this); 391 | } 392 | }); 393 | 394 | return DOM; 395 | }, 396 | 397 | /** 398 | * @access private 399 | * @name 获取 DOM size 400 | * @return {Object} 401 | */ 402 | __getSize: function() { 403 | var DOM = this.DOM; 404 | return { 405 | width: DOM.mediaPlay.width(), 406 | height: DOM.mediaPlay.height() 407 | }; 408 | } 409 | }; 410 | 411 | MPreviewPPT.tpl = '
' 412 | 413 | MPreviewPPT.template = '
\u4e0a\u4e00\u9875
\u4e0b\u4e00\u9875
'; 414 | 415 | $.fn.MPreviewPPT = function(option) { 416 | return this.each(function() { 417 | new MPreviewPPT(this, option); 418 | }); 419 | }; 420 | 421 | })(jQuery); 422 | 423 | 424 | /*! 425 | * jQuery Mousewheel 3.1.12 426 | * 427 | * Copyright 2014 jQuery Foundation and other contributors 428 | * Released under the MIT license. 429 | * http://jquery.org/license 430 | */ 431 | (function (factory) { 432 | if ( typeof define === 'function' && define.amd ) { 433 | // AMD. Register as an anonymous module. 434 | define(['jquery'], factory); 435 | } else if (typeof exports === 'object') { 436 | // Node/CommonJS style for Browserify 437 | module.exports = factory; 438 | } else { 439 | // Browser globals 440 | factory(jQuery); 441 | } 442 | }(function ($) { 443 | 444 | var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], 445 | toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? 446 | ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], 447 | slice = Array.prototype.slice, 448 | nullLowestDeltaTimeout, lowestDelta; 449 | 450 | if ( $.event.fixHooks ) { 451 | for ( var i = toFix.length; i; ) { 452 | $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; 453 | } 454 | } 455 | 456 | var special = $.event.special.mousewheel = { 457 | version: '3.1.12', 458 | 459 | setup: function() { 460 | if ( this.addEventListener ) { 461 | for ( var i = toBind.length; i; ) { 462 | this.addEventListener( toBind[--i], handler, false ); 463 | } 464 | } else { 465 | this.onmousewheel = handler; 466 | } 467 | // Store the line height and page height for this particular element 468 | $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); 469 | $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); 470 | }, 471 | 472 | teardown: function() { 473 | if ( this.removeEventListener ) { 474 | for ( var i = toBind.length; i; ) { 475 | this.removeEventListener( toBind[--i], handler, false ); 476 | } 477 | } else { 478 | this.onmousewheel = null; 479 | } 480 | // Clean up the data we added to the element 481 | $.removeData(this, 'mousewheel-line-height'); 482 | $.removeData(this, 'mousewheel-page-height'); 483 | }, 484 | 485 | getLineHeight: function(elem) { 486 | var $elem = $(elem), 487 | $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); 488 | if (!$parent.length) { 489 | $parent = $('body'); 490 | } 491 | return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16; 492 | }, 493 | 494 | getPageHeight: function(elem) { 495 | return $(elem).height(); 496 | }, 497 | 498 | settings: { 499 | adjustOldDeltas: true, // see shouldAdjustOldDeltas() below 500 | normalizeOffset: true // calls getBoundingClientRect for each event 501 | } 502 | }; 503 | 504 | $.fn.extend({ 505 | mousewheel: function(fn) { 506 | return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); 507 | }, 508 | 509 | unmousewheel: function(fn) { 510 | return this.unbind('mousewheel', fn); 511 | } 512 | }); 513 | 514 | 515 | function handler(event) { 516 | var orgEvent = event || window.event, 517 | args = slice.call(arguments, 1), 518 | delta = 0, 519 | deltaX = 0, 520 | deltaY = 0, 521 | absDelta = 0, 522 | offsetX = 0, 523 | offsetY = 0; 524 | event = $.event.fix(orgEvent); 525 | event.type = 'mousewheel'; 526 | 527 | // Old school scrollwheel delta 528 | if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } 529 | if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } 530 | if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } 531 | if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } 532 | 533 | // Firefox < 17 horizontal scrolling related to DOMMouseScroll event 534 | if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { 535 | deltaX = deltaY * -1; 536 | deltaY = 0; 537 | } 538 | 539 | // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy 540 | delta = deltaY === 0 ? deltaX : deltaY; 541 | 542 | // New school wheel delta (wheel event) 543 | if ( 'deltaY' in orgEvent ) { 544 | deltaY = orgEvent.deltaY * -1; 545 | delta = deltaY; 546 | } 547 | if ( 'deltaX' in orgEvent ) { 548 | deltaX = orgEvent.deltaX; 549 | if ( deltaY === 0 ) { delta = deltaX * -1; } 550 | } 551 | 552 | // No change actually happened, no reason to go any further 553 | if ( deltaY === 0 && deltaX === 0 ) { return; } 554 | 555 | // Need to convert lines and pages to pixels if we aren't already in pixels 556 | // There are three delta modes: 557 | // * deltaMode 0 is by pixels, nothing to do 558 | // * deltaMode 1 is by lines 559 | // * deltaMode 2 is by pages 560 | if ( orgEvent.deltaMode === 1 ) { 561 | var lineHeight = $.data(this, 'mousewheel-line-height'); 562 | delta *= lineHeight; 563 | deltaY *= lineHeight; 564 | deltaX *= lineHeight; 565 | } else if ( orgEvent.deltaMode === 2 ) { 566 | var pageHeight = $.data(this, 'mousewheel-page-height'); 567 | delta *= pageHeight; 568 | deltaY *= pageHeight; 569 | deltaX *= pageHeight; 570 | } 571 | 572 | // Store lowest absolute delta to normalize the delta values 573 | absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); 574 | 575 | if ( !lowestDelta || absDelta < lowestDelta ) { 576 | lowestDelta = absDelta; 577 | 578 | // Adjust older deltas if necessary 579 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 580 | lowestDelta /= 40; 581 | } 582 | } 583 | 584 | // Adjust older deltas if necessary 585 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 586 | // Divide all the things by 40! 587 | delta /= 40; 588 | deltaX /= 40; 589 | deltaY /= 40; 590 | } 591 | 592 | // Get a whole, normalized value for the deltas 593 | delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); 594 | deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); 595 | deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); 596 | 597 | // Normalise offsetX and offsetY properties 598 | if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { 599 | var boundingRect = this.getBoundingClientRect(); 600 | offsetX = event.clientX - boundingRect.left; 601 | offsetY = event.clientY - boundingRect.top; 602 | } 603 | 604 | // Add information to the event object 605 | event.deltaX = deltaX; 606 | event.deltaY = deltaY; 607 | event.deltaFactor = lowestDelta; 608 | event.offsetX = offsetX; 609 | event.offsetY = offsetY; 610 | // Go ahead and set deltaMode to 0 since we converted to pixels 611 | // Although this is a little odd since we overwrite the deltaX/Y 612 | // properties with normalized deltas. 613 | event.deltaMode = 0; 614 | 615 | // Add event and delta to the front of the arguments 616 | args.unshift(event, delta, deltaX, deltaY); 617 | 618 | // Clearout lowestDelta after sometime to better 619 | // handle multiple device types that give different 620 | // a different lowestDelta 621 | // Ex: trackpad = 3 and mouse wheel = 120 622 | if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } 623 | nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); 624 | 625 | return ($.event.dispatch || $.event.handle).apply(this, args); 626 | } 627 | 628 | function nullLowestDelta() { 629 | lowestDelta = null; 630 | } 631 | 632 | function shouldAdjustOldDeltas(orgEvent, absDelta) { 633 | // If this is an older event and the delta is divisable by 120, 634 | // then we are assuming that the browser is treating this as an 635 | // older mouse wheel event and that we should divide the deltas 636 | // by 40 to try and get a more usable deltaFactor. 637 | // Side note, this actually impacts the reported scroll distance 638 | // in older browsers and can cause scrolling to be slower than native. 639 | // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. 640 | return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; 641 | } 642 | 643 | })); -------------------------------------------------------------------------------- /js/MPreview.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @name MPreview.js 3 | * @desc 文档预览。 4 | * @depend jQuery 1.7+, jQuery.MouseWheel.js 5 | * @author M.J 6 | * @date 2014-12-25 7 | * @URL http://webjyh.com 8 | * @reutn {jQuery} 9 | * @version 1.0.1 10 | * 11 | * @PS If you have any questions, please don't look for me, I don't know anything. thank you. 12 | */ 13 | (function($) { 14 | var MPreview = function(elem, option) { 15 | 16 | this.config = $.extend({}, this.defaults, option); 17 | 18 | this.elem = $(elem); //绑定的元素 19 | this.page = 0; //当前页 20 | this.bout = 0; //当前要滚动总次数 21 | this.offset = 0; //当前已滚动次数 22 | this.btnOffset = 0; //当前滚动按钮每次滚动的距离 23 | this.length = 0; //当前数据的总长度也是总页数 24 | this.data = []; //当前所有数据 25 | this.H = []; //存放所有图片容器距外容器顶部的距离 26 | this.DOM = this.__createDOM(); //当前所有元素DOM 27 | this.S = { //存放当前容器的宽,高 28 | width: this.elem.width(), 29 | height: this.elem.height() 30 | }; 31 | 32 | this.__init(); 33 | 34 | }; 35 | 36 | 37 | MPreview.prototype = { 38 | /** 39 | * 默认配置 40 | * @type {Object} 41 | */ 42 | defaults: { 43 | url: null, //默认Ajax地址 44 | data: null, //默认JSON 格式的数据,如填写则不发送Ajax,默认为 {Array} 类型 45 | offset: 100, //每次滚动偏移多少像素 46 | loadSize: 5, //默认先创建几页 47 | pageFix: 50, //当前页码判定的衡量标准 48 | scrollFix: 5, //当前默认滚动条距离外容器的边距 49 | minScrollHeight: 20 //当前滚动条按钮最小高度 50 | }, 51 | 52 | /** 53 | * @access private 54 | * @name 执行请求 55 | * @return {this} 56 | */ 57 | __init: function() { 58 | var _this = this, DOM = this.DOM; 59 | 60 | if ( this.config.data && this.config.data.length ){ 61 | this.__set(this.config.data).__create().__addEvent(); 62 | } else { 63 | $.getJSON(this.config.url) 64 | .done(function(data) { 65 | if (data.code > 0 && data.imgs.length) { 66 | _this.__set(data.imgs).__create().__addEvent(); 67 | } 68 | }) 69 | .fail(function() { 70 | alert('\u83b7\u53d6\u6570\u636e\u5931\u8d25'); 71 | }); 72 | } 73 | 74 | return this; 75 | }, 76 | 77 | /** 78 | * @access private 79 | * @name 首次数据进行设置 80 | * @return {Object} 81 | */ 82 | __set: function(data) { 83 | var DOM = this.DOM; 84 | 85 | this.data = data; 86 | this.length = data.length; 87 | 88 | DOM.pageInput.val('01'); 89 | DOM.pageCount.children('em').text(this.__formatNumber(this.length)); 90 | if (this.length > 1) DOM.pageNext.addClass('current'); 91 | 92 | return this; 93 | }, 94 | 95 | /** 96 | * @access private 97 | * @name 创建list 98 | * @return {Object} 99 | */ 100 | __create: function() { 101 | if (!this.data.length) return false; 102 | $(document).off('mousemove'); 103 | 104 | var i = 0, 105 | tpl = '', 106 | len = this.data.length, 107 | count = len > this.config.loadSize ? this.config.loadSize : len, 108 | DOM = this.DOM, 109 | _this = this; 110 | 111 | // create TPL && delete array 112 | for (; i _this.bout) _this.offset = _this.bout; 167 | if (val == 'down' && _this.offset < 0) _this.offset = 0; 168 | setDOMStyle(val); 169 | 170 | //设置当前页 171 | if (val == 'up' && H + _this.config.pageFix > _this.H[_this.page]) DOM.pageInput.val(_this.__formatNumber(++_this.page+1)); 172 | if (val == 'down' && H + _this.config.pageFix < _this.H[_this.page-1]) DOM.pageInput.val(_this.__formatNumber(--_this.page+1)); 173 | 174 | //创建剩余数据 175 | _this.__createLastData(); 176 | 177 | }; 178 | 179 | //默认设置DOM 180 | DOM.scrollBtn.height(btnHeight <= this.config.minScrollHeight ? this.config.minScrollHeight : btnHeight); 181 | DOM.scrollBtn.css('top', _this.btnOffset * _this.offset + _this.config.scrollFix); 182 | 183 | //滚动事件绑定 184 | DOM.mediaPlay.off('mousewheel').on('mousewheel', function(event) { 185 | event.preventDefault(); 186 | scroll(event.deltaY < 0 ? 'up' : 'down'); 187 | }); 188 | 189 | return this; 190 | }, 191 | 192 | /** 193 | * @access private 194 | * @name 滚动按钮拖拽事件 195 | * @return {null} 196 | */ 197 | __scrollDrag: { 198 | dragStart: function(event, _this){ 199 | //滚动条偏差 200 | var DOM = _this.DOM, 201 | fix = (event.clientY - DOM.scrollBtn.offset().top).toFixed(0); 202 | 203 | //拖拽事件绑定 204 | $(document).on('mousemove', function(event) { _this.__scrollDrag.dragDrop(event, fix, _this) }); 205 | $(document).off('mouseup').on('mouseup', function() { $(this).off('mousemove') }); 206 | }, 207 | dragDrop: function(event, fix, _this){ 208 | 209 | //计算一些必要的值 210 | var DOM = _this.DOM, 211 | size = _this.__getSize(), 212 | defaultTop = parseInt(DOM.scrollBtn.css('top'), 10), 213 | offsetY = (event.clientY - DOM.scrollBtn.offset().top).toFixed(0) - fix, 214 | top = defaultTop + offsetY, 215 | minTop = _this.config.scrollFix, 216 | maxTop = size.height - _this.config.scrollFix - DOM.scrollBtn.outerHeight(); 217 | 218 | //拖拽最小最大高度设置 219 | if ( top < minTop ) top = minTop; 220 | if ( top > maxTop ) top = maxTop; 221 | 222 | //设置当前分页,及滚动次数 223 | var offset = Math.floor(top / _this.btnOffset), 224 | marginTop = Math.floor( (size.viewHeight - _this.config.scrollFix * 2) / size.height) * (top == minTop ? 0 : top); 225 | 226 | //是否拖放到底部 227 | if ( top == maxTop ) marginTop = size.viewHeight - size.height; 228 | 229 | _this.offset = offset > _this.bout ? _this.bout: offset; 230 | if ( marginTop + _this.config.pageFix > _this.H[_this.page] ) DOM.pageInput.val(_this.__formatNumber(++_this.page+1)); 231 | if ( marginTop + _this.config.pageFix < _this.H[_this.page-1] ) DOM.pageInput.val(_this.__formatNumber(--_this.page+1)); 232 | 233 | //设置对应的DOM样式 234 | DOM.mediaView.css('margin-top', -marginTop); 235 | DOM.scrollBtn.css('top', top); 236 | 237 | //创建剩余数据 并卸载当前拖拽事件 238 | _this.__createLastData(); 239 | } 240 | }, 241 | 242 | /** 243 | * @access private 244 | * @name 给元素绑定相应的事件 245 | * @return {Object} 246 | */ 247 | __addEvent: function() { 248 | var _this = this, 249 | DOM = this.DOM; 250 | 251 | var arrowOver = function(){ 252 | if (_this.page > 0) DOM.arrowTop.stop(true,true).fadeIn(); 253 | if (_this.page < _this.length -1) DOM.arrowBottom.stop(true,true).fadeIn(); 254 | }; 255 | 256 | var arrowOut = function(){ 257 | DOM.arrowTop.stop(true,true).fadeOut(); 258 | DOM.arrowBottom.stop(true,true).fadeOut(); 259 | }; 260 | 261 | //滚动条按钮拖拽事件 262 | DOM.scrollBtn.on('mousedown', function(event) { _this.__scrollDrag.dragStart(event, _this) }); 263 | 264 | //页码按钮显示 265 | DOM.arrowUp.on('mouseover', arrowOver); 266 | DOM.arrowDown.on('mouseover', arrowOver); 267 | DOM.arrowUp.on('mouseout', arrowOut); 268 | DOM.arrowDown.on('mouseout', arrowOut); 269 | 270 | //上一页,下一页事件 271 | DOM.arrowTop.on('click', function() { _this.__pageJump('up') }); 272 | DOM.pagePrev.on('click', function() { _this.__pageJump('up') }); 273 | DOM.arrowBottom.on('click', function() { _this.__pageJump('down') }); 274 | DOM.pageNext.on('click', function() { _this.__pageJump('down') }); 275 | 276 | //全屏操作 277 | DOM.fullScreen.on('click', function() { _this.__full(); }); 278 | DOM.mediaPlay.on('dblclick', function() { _this.__full(); }); 279 | 280 | return this; 281 | }, 282 | 283 | /** 284 | * @private private 285 | * @param 页码跳转 286 | * @return {null} 287 | */ 288 | __pageJump: function(val) { 289 | 290 | //设置当前页码 291 | val == 'up' ? --this.page : ++this.page; 292 | if (this.page < 0) this.page = 0; 293 | if (this.page > this.length-1 ) this.page = this.length-1; 294 | 295 | //计算滚动值 296 | var DOM = this.DOM, 297 | size = this.__getSize(), 298 | H = typeof this.H[this.page-1] === 'undefined' ? 0 : this.H[this.page-1], 299 | minH = this.config.scrollFix, 300 | maxH = size.height - DOM.scrollBtn.outerHeight() - minH; 301 | 302 | //计算当前已滚动次数 303 | var btnT, offset = (H / this.config.offset == 0) ? 0 : Math.floor(H / this.config.offset); 304 | this.offset = offset > this.bout ? this.bout: offset; 305 | btnT = this.offset * this.btnOffset; 306 | 307 | //滚动条容错处理 308 | if (btnT < minH) btnT = minH; 309 | if (btnT > maxH) btnT = maxH; 310 | 311 | //设置DOM 312 | DOM.pageInput.val(this.__formatNumber(this.page+1)); 313 | DOM.mediaView.css('margin-top', -H); 314 | DOM.scrollBtn.css('top', btnT); 315 | 316 | //创建剩余数据 317 | this.__createLastData(); 318 | }, 319 | 320 | /** 321 | * @private private 322 | * @param 全屏操作 323 | * @return {this} 324 | */ 325 | __full: function(bool){ 326 | var $elem = this.elem, 327 | DOM = this.DOM, 328 | _this = this, 329 | has = DOM.fullScreen.hasClass('MPreview-exit'), 330 | winHeight = $(window).outerHeight(); 331 | 332 | //用于 resize 事件 333 | if ( bool ) has = false; 334 | 335 | // 全屏样式 336 | var css = { 337 | position: has ? 'static' : 'fixed', 338 | top: has ? 'auto' : 0, 339 | left: has ? 'auto' : 0, 340 | zIndex: has ? '0' : 9999, 341 | width: has ? this.S.width : '100%', 342 | height: has ? this.S.height : winHeight 343 | }, 344 | bodyCss = { 345 | overflow: has ? 'auto' : 'hidden', 346 | width: has ? 'auto' : '100%', 347 | height: has ? 'auto': winHeight 348 | }; 349 | 350 | //设置DOM样式 351 | DOM.fullScreen[has ? 'removeClass' : 'addClass']('MPreview-exit').attr('title', has ? '\u5168\u5c4f' : '\u53d6\u6d88\u5168\u5c4f'); 352 | $('html').css(bodyCss); 353 | $elem.css(css); 354 | 355 | //保存原滚动次数 356 | var bout = function(){return _this.bout;}(); 357 | 358 | //清空数组,重新计算 359 | this.H = []; 360 | DOM.mediaView.find('img').each(function(i) { 361 | var H = (typeof _this.H[_this.H.length-1] === 'undefined' ? 0 : _this.H[_this.H.length-1]) + $(this).parent().outerHeight(); 362 | _this.H.push(H); 363 | }); 364 | this.__scrollBar(); 365 | 366 | //差值计算:新总滚动次数 - 原总滚动次数 * 每次滚动偏移量 367 | //得出与原滚动次数相差了多少差值 368 | //在 除此 原滚动的次数,得出每次滚动相差多少差值 369 | //在 乘以 当前已滚动的次数,得出总差值。在原基础上增加到预览页上。 370 | //由得出来的差值 得出偏移量的差值 371 | var fix = ((this.bout - bout) * this.config.offset / bout) * this.offset, 372 | offsetFix = fix / this.config.offset, 373 | top = parseInt(DOM.mediaView.css('margin-top'), 10); 374 | 375 | //重新计算浏览次数 376 | this.offset = this.offset+offsetFix; 377 | DOM.mediaView.css('margin-top', top+(-fix)); 378 | DOM.scrollBtn.css('top', _this.btnOffset * _this.offset + _this.config.scrollFix); 379 | 380 | //绑定事件 381 | if ( has ){ 382 | $(document).off('keyup'); 383 | $(window).off('resize'); 384 | } else { 385 | $(document).on('keyup', function(event){ if (event.which == 27) _this.__full(); }); 386 | $(window).off('resize').on('resize', function(){ _this.__full(true); }) 387 | } 388 | }, 389 | 390 | /** 391 | * @private private 392 | * @param 给单数字自动补零 393 | * @return {String} 394 | */ 395 | __formatNumber: function(val) { 396 | return val.toString().length < 2 ? '0' + val : val; 397 | }, 398 | 399 | /** 400 | * @private private 401 | * @param 设置页码样式及判断是否创建剩余数据 402 | * @return {null} 403 | */ 404 | __createLastData: function() { 405 | var DOM = this.DOM; 406 | 407 | DOM.pagePrev[this.page > 0 ? 'addClass' : 'removeClass']('current'); 408 | DOM.pageNext[this.page < this.length - 1 ? 'addClass' : 'removeClass']('current'); 409 | 410 | if ( this.offset >= Math.floor( this.bout ) - 1) this.__create(); 411 | }, 412 | 413 | /** 414 | * @access private 415 | * @name 创建DOM,存储DOM 416 | * @return {Object} 417 | */ 418 | __createDOM: function() { 419 | var $elem = this.elem, DOM = {}, elem; 420 | 421 | DOM['wrap'] = $(MPreview.template).appendTo($elem); 422 | DOM.wrap.find('*').each(function() { 423 | var className = $(this).attr('class'); 424 | if ( className !== undefined && className.toString().indexOf('MPreview') > -1 ) { 425 | var name = className.replace(/icon /g, '').replace('MPreview-', ''); 426 | DOM[name] = $(this); 427 | } 428 | }); 429 | 430 | return DOM; 431 | }, 432 | 433 | /** 434 | * @access private 435 | * @name 获取 DOM size 436 | * @return {Object} 437 | */ 438 | __getSize: function() { 439 | var DOM = this.DOM; 440 | return { 441 | width: DOM.mediaPlay.width(), 442 | height: DOM.mediaPlay.height(), 443 | viewWidth: DOM.mediaView.width(), 444 | viewHeight: DOM.mediaView.height() 445 | }; 446 | } 447 | }; 448 | 449 | MPreview.tpl = '
' 450 | 451 | MPreview.template = '
\u4e0a\u4e00\u9875
\u4e0b\u4e00\u9875
'; 452 | 453 | $.fn.MPreview = function(option) { 454 | return this.each(function() { 455 | new MPreview(this, option); 456 | }); 457 | }; 458 | 459 | })(jQuery); 460 | 461 | 462 | /*! 463 | * jQuery Mousewheel 3.1.12 464 | * 465 | * Copyright 2014 jQuery Foundation and other contributors 466 | * Released under the MIT license. 467 | * http://jquery.org/license 468 | */ 469 | (function (factory) { 470 | if ( typeof define === 'function' && define.amd ) { 471 | // AMD. Register as an anonymous module. 472 | define(['jquery'], factory); 473 | } else if (typeof exports === 'object') { 474 | // Node/CommonJS style for Browserify 475 | module.exports = factory; 476 | } else { 477 | // Browser globals 478 | factory(jQuery); 479 | } 480 | }(function ($) { 481 | 482 | var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'], 483 | toBind = ( 'onwheel' in document || document.documentMode >= 9 ) ? 484 | ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'], 485 | slice = Array.prototype.slice, 486 | nullLowestDeltaTimeout, lowestDelta; 487 | 488 | if ( $.event.fixHooks ) { 489 | for ( var i = toFix.length; i; ) { 490 | $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks; 491 | } 492 | } 493 | 494 | var special = $.event.special.mousewheel = { 495 | version: '3.1.12', 496 | 497 | setup: function() { 498 | if ( this.addEventListener ) { 499 | for ( var i = toBind.length; i; ) { 500 | this.addEventListener( toBind[--i], handler, false ); 501 | } 502 | } else { 503 | this.onmousewheel = handler; 504 | } 505 | // Store the line height and page height for this particular element 506 | $.data(this, 'mousewheel-line-height', special.getLineHeight(this)); 507 | $.data(this, 'mousewheel-page-height', special.getPageHeight(this)); 508 | }, 509 | 510 | teardown: function() { 511 | if ( this.removeEventListener ) { 512 | for ( var i = toBind.length; i; ) { 513 | this.removeEventListener( toBind[--i], handler, false ); 514 | } 515 | } else { 516 | this.onmousewheel = null; 517 | } 518 | // Clean up the data we added to the element 519 | $.removeData(this, 'mousewheel-line-height'); 520 | $.removeData(this, 'mousewheel-page-height'); 521 | }, 522 | 523 | getLineHeight: function(elem) { 524 | var $elem = $(elem), 525 | $parent = $elem['offsetParent' in $.fn ? 'offsetParent' : 'parent'](); 526 | if (!$parent.length) { 527 | $parent = $('body'); 528 | } 529 | return parseInt($parent.css('fontSize'), 10) || parseInt($elem.css('fontSize'), 10) || 16; 530 | }, 531 | 532 | getPageHeight: function(elem) { 533 | return $(elem).height(); 534 | }, 535 | 536 | settings: { 537 | adjustOldDeltas: true, // see shouldAdjustOldDeltas() below 538 | normalizeOffset: true // calls getBoundingClientRect for each event 539 | } 540 | }; 541 | 542 | $.fn.extend({ 543 | mousewheel: function(fn) { 544 | return fn ? this.bind('mousewheel', fn) : this.trigger('mousewheel'); 545 | }, 546 | 547 | unmousewheel: function(fn) { 548 | return this.unbind('mousewheel', fn); 549 | } 550 | }); 551 | 552 | 553 | function handler(event) { 554 | var orgEvent = event || window.event, 555 | args = slice.call(arguments, 1), 556 | delta = 0, 557 | deltaX = 0, 558 | deltaY = 0, 559 | absDelta = 0, 560 | offsetX = 0, 561 | offsetY = 0; 562 | event = $.event.fix(orgEvent); 563 | event.type = 'mousewheel'; 564 | 565 | // Old school scrollwheel delta 566 | if ( 'detail' in orgEvent ) { deltaY = orgEvent.detail * -1; } 567 | if ( 'wheelDelta' in orgEvent ) { deltaY = orgEvent.wheelDelta; } 568 | if ( 'wheelDeltaY' in orgEvent ) { deltaY = orgEvent.wheelDeltaY; } 569 | if ( 'wheelDeltaX' in orgEvent ) { deltaX = orgEvent.wheelDeltaX * -1; } 570 | 571 | // Firefox < 17 horizontal scrolling related to DOMMouseScroll event 572 | if ( 'axis' in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { 573 | deltaX = deltaY * -1; 574 | deltaY = 0; 575 | } 576 | 577 | // Set delta to be deltaY or deltaX if deltaY is 0 for backwards compatabilitiy 578 | delta = deltaY === 0 ? deltaX : deltaY; 579 | 580 | // New school wheel delta (wheel event) 581 | if ( 'deltaY' in orgEvent ) { 582 | deltaY = orgEvent.deltaY * -1; 583 | delta = deltaY; 584 | } 585 | if ( 'deltaX' in orgEvent ) { 586 | deltaX = orgEvent.deltaX; 587 | if ( deltaY === 0 ) { delta = deltaX * -1; } 588 | } 589 | 590 | // No change actually happened, no reason to go any further 591 | if ( deltaY === 0 && deltaX === 0 ) { return; } 592 | 593 | // Need to convert lines and pages to pixels if we aren't already in pixels 594 | // There are three delta modes: 595 | // * deltaMode 0 is by pixels, nothing to do 596 | // * deltaMode 1 is by lines 597 | // * deltaMode 2 is by pages 598 | if ( orgEvent.deltaMode === 1 ) { 599 | var lineHeight = $.data(this, 'mousewheel-line-height'); 600 | delta *= lineHeight; 601 | deltaY *= lineHeight; 602 | deltaX *= lineHeight; 603 | } else if ( orgEvent.deltaMode === 2 ) { 604 | var pageHeight = $.data(this, 'mousewheel-page-height'); 605 | delta *= pageHeight; 606 | deltaY *= pageHeight; 607 | deltaX *= pageHeight; 608 | } 609 | 610 | // Store lowest absolute delta to normalize the delta values 611 | absDelta = Math.max( Math.abs(deltaY), Math.abs(deltaX) ); 612 | 613 | if ( !lowestDelta || absDelta < lowestDelta ) { 614 | lowestDelta = absDelta; 615 | 616 | // Adjust older deltas if necessary 617 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 618 | lowestDelta /= 40; 619 | } 620 | } 621 | 622 | // Adjust older deltas if necessary 623 | if ( shouldAdjustOldDeltas(orgEvent, absDelta) ) { 624 | // Divide all the things by 40! 625 | delta /= 40; 626 | deltaX /= 40; 627 | deltaY /= 40; 628 | } 629 | 630 | // Get a whole, normalized value for the deltas 631 | delta = Math[ delta >= 1 ? 'floor' : 'ceil' ](delta / lowestDelta); 632 | deltaX = Math[ deltaX >= 1 ? 'floor' : 'ceil' ](deltaX / lowestDelta); 633 | deltaY = Math[ deltaY >= 1 ? 'floor' : 'ceil' ](deltaY / lowestDelta); 634 | 635 | // Normalise offsetX and offsetY properties 636 | if ( special.settings.normalizeOffset && this.getBoundingClientRect ) { 637 | var boundingRect = this.getBoundingClientRect(); 638 | offsetX = event.clientX - boundingRect.left; 639 | offsetY = event.clientY - boundingRect.top; 640 | } 641 | 642 | // Add information to the event object 643 | event.deltaX = deltaX; 644 | event.deltaY = deltaY; 645 | event.deltaFactor = lowestDelta; 646 | event.offsetX = offsetX; 647 | event.offsetY = offsetY; 648 | // Go ahead and set deltaMode to 0 since we converted to pixels 649 | // Although this is a little odd since we overwrite the deltaX/Y 650 | // properties with normalized deltas. 651 | event.deltaMode = 0; 652 | 653 | // Add event and delta to the front of the arguments 654 | args.unshift(event, delta, deltaX, deltaY); 655 | 656 | // Clearout lowestDelta after sometime to better 657 | // handle multiple device types that give different 658 | // a different lowestDelta 659 | // Ex: trackpad = 3 and mouse wheel = 120 660 | if (nullLowestDeltaTimeout) { clearTimeout(nullLowestDeltaTimeout); } 661 | nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200); 662 | 663 | return ($.event.dispatch || $.event.handle).apply(this, args); 664 | } 665 | 666 | function nullLowestDelta() { 667 | lowestDelta = null; 668 | } 669 | 670 | function shouldAdjustOldDeltas(orgEvent, absDelta) { 671 | // If this is an older event and the delta is divisable by 120, 672 | // then we are assuming that the browser is treating this as an 673 | // older mouse wheel event and that we should divide the deltas 674 | // by 40 to try and get a more usable deltaFactor. 675 | // Side note, this actually impacts the reported scroll distance 676 | // in older browsers and can cause scrolling to be slower than native. 677 | // Turn this off by setting $.event.special.mousewheel.settings.adjustOldDeltas to false. 678 | return special.settings.adjustOldDeltas && orgEvent.type === 'mousewheel' && absDelta % 120 === 0; 679 | } 680 | 681 | })); --------------------------------------------------------------------------------