├── README.md ├── images ├── banner.png ├── banner1.jpg ├── banner2.jpg ├── banner3.jpg ├── lazyload.png └── icons │ ├── left.png │ ├── pullUp.png │ ├── refresh.gif │ ├── checkImg.png │ ├── pullDown.png │ ├── returnTop.png │ └── toast-icon.png ├── demo ├── css │ ├── iscroll.css │ ├── preview.css │ ├── lazyload.css │ ├── bmap.css │ ├── date.css │ ├── zsmap.css │ ├── selector.css │ ├── waterfall.css │ ├── citypicker.css │ ├── dialog.css │ ├── index.css │ ├── drag.css │ ├── clip_image.css │ └── pull.css ├── bmap.html ├── drag.html ├── selector.html ├── iscroll.html ├── waterfall.html ├── js │ ├── preview.js │ ├── drag.js │ ├── iscroll.js │ ├── selector.js │ ├── date.js │ ├── bmap.js │ ├── citypicker.js │ ├── lazyload.js │ ├── clip_image.js │ ├── index.js │ ├── dialog.js │ ├── zsmap.js │ ├── waterfall.js │ └── pull.js ├── zsmap.html ├── citypicker.html ├── date.html ├── dialog.html ├── clip_image.html ├── index.html ├── pull.html ├── preview.html └── lazyload.html ├── error.html ├── js ├── error.js ├── app.js ├── waterfall_module.js ├── mobile_module.js ├── map_module.js ├── iscroll_module.js ├── sea.js ├── util_module.js ├── datepicker_module.js ├── jweixin-1.0.0.js ├── dialog_module.js ├── citypicker_module.js ├── iscroll.min.js ├── clip │ ├── hammer.js │ └── iscroll-zoom.js └── clip_module.js ├── index.html ├── resource └── wine_province.json └── css ├── datepicker.css ├── app.css ├── citypicker.css ├── dialog.css └── loading.css /README.md: -------------------------------------------------------------------------------- 1 | Hello mobileapp -------------------------------------------------------------------------------- /images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/banner.png -------------------------------------------------------------------------------- /images/banner1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/banner1.jpg -------------------------------------------------------------------------------- /images/banner2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/banner2.jpg -------------------------------------------------------------------------------- /images/banner3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/banner3.jpg -------------------------------------------------------------------------------- /images/lazyload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/lazyload.png -------------------------------------------------------------------------------- /images/icons/left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/left.png -------------------------------------------------------------------------------- /images/icons/pullUp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/pullUp.png -------------------------------------------------------------------------------- /images/icons/refresh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/refresh.gif -------------------------------------------------------------------------------- /images/icons/checkImg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/checkImg.png -------------------------------------------------------------------------------- /images/icons/pullDown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/pullDown.png -------------------------------------------------------------------------------- /images/icons/returnTop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/returnTop.png -------------------------------------------------------------------------------- /images/icons/toast-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/77424797/mobileapp/HEAD/images/icons/toast-icon.png -------------------------------------------------------------------------------- /demo/css/iscroll.css: -------------------------------------------------------------------------------- 1 | #iscroll_wrapper{ 2 | width: 100%; 3 | height: 100%; 4 | font-size: 14px; 5 | max-width: 640px; 6 | margin-top: 45px; 7 | } 8 | -------------------------------------------------------------------------------- /demo/bmap.html: -------------------------------------------------------------------------------- 1 |
404
6 |您访问的页面找不到!
7 |
7 |
8 |
9 |
10 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 6.O){o++}}}6.2a(6.W.R||0,6.W.P||0,0);A(6.B.2t%1===0){6.3H=6.B.2t;6.3G=6.B.2t}D{6.3H=e.N(6.L[6.W.R][6.W.P].1b*6.B.2t);6.3G=e.N(6.L[6.W.R][6.W.P].1c*6.B.2t)}});6.1s("3V",C(){F i=6.B.3E||e.X(e.X(e.1x(e.M(6.x-6.1I),1G),e.1x(e.M(6.y-6.1K),1G)),1C);6.2a(6.W.R+6.1X,6.W.P+6.1P,i)})},4c:C(k,p){A(!6.L.U){E{x:0,y:0,R:0,P:0}}F o=0,n=6.L.U,j=0;A(e.M(k-6.5j)<6.3H&&e.M(p-6.5d)<6.3G){E 6.W}A(k>0){k=0}D{A(k<6.O){k=6.O}}A(p>0){p=0}D{A(p<6.S){p=6.S}}1f(;o=6.L[o][0].3K){k=6.L[o][0].x;Y}}n=6.L[o].U;1f(;j =6.L[0][j].3I){p=6.L[0][j].y;Y}}A(o==6.W.R){o+=6.1X;A(o<0){o=0}D{A(o>=6.L.U){o=6.L.U-1}}k=6.L[o][0].x}A(j==6.W.P){j+=6.1P;A(j<0){j=0}D{A(j>=6.L[0].U){j=6.L[0].U-1}}p=6.L[0][j].y}E{x:k,y:p,R:o,P:j}},2a:C(i,n,j,m){m=m||6.B.1M;A(i>=6.L.U){i=6.L.U-1}D{A(i<0){i=0}}A(n>=6.L[i].U){n=6.L[i].U-1}D{A(n<0){n=0}}F l=6.L[i][n].x,k=6.L[i][n].y;j=j===1A?6.B.3E||e.X(e.X(e.1x(e.M(l-6.x),1G),e.1x(e.M(k-6.y),1G)),1C):j;6.W={x:l,y:k,R:i,P:n};6.1i(l,k,j,m)},7T:C(j,l){F i=6.W.R,k=6.W.P;i++;A(i>=6.L.U&&6.1k){i=0;k++}6.2a(i,k,j,l)},7V:C(j,l){F i=6.W.R,k=6.W.P;i--;A(i<0&&6.1k){i=0;k--}6.2a(i,k,j,l)},4R:C(l){F k={64:33,63:34,62:35,5X:36,14:37,5T:38,2v:39,5S:40};F j;A(1T 6.B.1a=="7f"){1f(j 16 6.B.1a){A(1T 6.B.1a[j]=="2y"){6.B.1a[j]=6.B.1a[j].3F().7g(0)}}}D{6.B.1a={}}1f(j 16 k){6.B.1a[j]=6.B.1a[j]||k[j]}c.1g(f,"3U",6);6.1s("26",C(){c.15(f,"3U",6)})},5n:C(n){A(!6.1E){E}F i=6.B.1t,o=i?6.W.R:6.x,m=i?6.W.P:6.y,k=c.1r(),j=6.5W||0,l=0.25,p;A(6.B.1F&&6.1w){p=6.3L();6.2b(e.N(p.x),e.N(p.y));6.1w=Q}6.1z=k-j<5Y?e.1x(6.1z+l,50):0;4B(n.7d){G 6.B.1a.64:A(6.1o&&!6.1k){o+=i?1:6.1h}D{m+=i?1:6.1e}Y;G 6.B.1a.63:A(6.1o&&!6.1k){o-=i?1:6.1h}D{m-=i?1:6.1e}Y;G 6.B.1a.62:o=i?6.L.U-1:6.O;m=i?6.L[0].U-1:6.S;Y;G 6.B.1a.5X:o=0;m=0;Y;G 6.B.1a.14:o+=i?-1:5+6.1z>>0;Y;G 6.B.1a.5T:m+=i?1:5+6.1z>>0;Y;G 6.B.1a.2v:o-=i?-1:5+6.1z>>0;Y;G 6.B.1a.5S:m-=i?1:5+6.1z>>0;Y;7e:E}A(i){6.2a(o,m);E}A(o>0){o=0;6.1z=0}D{A(o<6.O){o=6.O;6.1z=0}}A(m>0){m=0;6.1z=0}D{A(m<6.S){m=6.S;6.1z=0}}6.1i(o,m,0);6.5W=k},5V:C(r,q,l,i){F o=6,n=6.x,m=6.y,j=c.1r(),p=j+l;C k(){F s=c.1r(),u,t,v;A(s>=p){o.3b=Q;o.2b(r,q);A(!o.3a(o.B.2l)){o.Z("1V")}E}s=(s-j)/l;v=i(s);u=(r-n)*v+n;t=(q-m)*v+m;o.2b(u,t);A(o.3b){h(k)}}6.3b=K;k()},5B:C(i){4B(i.1H){G"2f":G"2g":G"4O":G"2o":6.3A(i);A(6.B.2C&&i.T&&i.T.U>1){6.67(i)}Y;G"28":G"21":G"4M":G"23":A(6.B.2C&&i.T&&i.T[1]){6.65(i);E}6.3z(i);Y;G"2p":G"2k":G"4N":G"2m":G"4P":G"4I":G"5C":G"4H":A(6.3T){6.66(i);E}6.3w(i);Y;G"69":G"2e":6.6a();Y;G"5v":G"5w":G"5t":G"61":6.5z(i);Y;G"3R":G"43":G"3S":A(6.B.7k=="2C"){6.5x(i);E}6.5y(i);Y;G"3U":6.5n(i);Y}}};C d(l,j,k){F m=a.41("3Z"),i=a.41("3Z");A(k===K){m.I.2N="5l:5m;z-7h:7i";i.I.2N="-77-2D-3X:2S-2D;-78-2D-3X:2S-2D;2D-3X:2S-2D;5l:5m;74:5q(0,0,0,0.5);2S:5J 76 5q(3J,3J,3J,0.9);2S-7b:7c"}i.1U="79";A(l=="h"){A(k===K){m.I.2N+=";1c:5M;14:2s;2v:2s;3t:0";i.I.1c="3g%"}m.1U="7a"}D{A(k===K){m.I.2N+=";1b:5M;3t:2s;18:2s;2v:5J";i.I.1b="3g%"}m.1U="7v"}m.I.2N+=";7w:7t";A(!j){m.I.7u="3n"}m.4G(i);E m}C b(j,k){6.J=1T k.27=="2y"?a.4E(k.27):k.27;6.2n=6.J.I;6.1y=6.J.5O[0];6.17=6.1y.I;6.H=j;6.B={1L:K,2d:K,2J:Q,2e:K,2w:Q,1q:Q,1J:Q,5Q:0,5L:0};1f(F l 16 k){6.B[l]=k[l]}6.3u=1;6.3s=1;6.1Y=0;6.1N=0;A(6.B.2J){A(!6.B.4L){c.1g(6.1y,"2f",6);c.1g(f,"2p",6)}A(!6.B.4f){c.1g(6.1y,c.1m("2g"),6);c.1g(f,c.1m("2k"),6)}A(!6.B.4e){c.1g(6.1y,"2o",6);c.1g(f,"2m",6)}}A(6.B.1J){6.2n[c.I.2r]=6.H.2P;6.2n[c.I.1R]=c.2Z?"0.48":"7z";6.2n.6b="0"}}b.5E={5B:C(i){4B(i.1H){G"2f":G"2g":G"4O":G"2o":6.3A(i);Y;G"28":G"21":G"4M":G"23":6.3z(i);Y;G"2p":G"2k":G"4N":G"2m":G"4P":G"4I":G"5C":G"4H":6.3w(i);Y}},26:C(){A(6.B.2J){c.15(6.1y,"2f",6);c.15(6.1y,c.1m("2g"),6);c.15(6.1y,"2o",6);c.15(f,"28",6);c.15(f,c.1m("21"),6);c.15(f,"23",6);c.15(f,"2p",6);c.15(f,c.1m("2k"),6);c.15(f,"2m",6)}A(6.B.2w){6.J.7A.7x(6.J)}},3A:C(j){F i=j.T?j.T[0]:j;j.11();j.2G();6.3C();6.1j=K;6.1Q=Q;6.4i=i.R;6.4h=i.P;6.2F=c.1r();A(!6.B.4L){c.1g(f,"28",6)}A(!6.B.4f){c.1g(f,c.1m("21"),6)}A(!6.B.4e){c.1g(f,"23",6)}6.H.Z("4d")},3z:C(n){F j=n.T?n.T[0]:n,k,i,o,m,l=c.1r();A(!6.1Q){6.H.Z("3x")}6.1Q=K;k=j.R-6.4i;6.4i=j.R;i=j.P-6.4h;6.4h=j.P;o=6.x+k;m=6.y+i;6.5s(o,m);n.11();n.2G()},3w:C(k){A(!6.1j){E}6.1j=Q;k.11();k.2G();c.15(f,"28",6);c.15(f,c.1m("21"),6);c.15(f,"23",6);A(6.H.B.1t){F i=6.H.4c(6.H.x,6.H.y);F j=6.B.3E||e.X(e.X(e.1x(e.M(6.H.x-i.x),1G),e.1x(e.M(6.H.y-i.y),1G)),1C);A(6.H.x!=i.x||6.H.y!=i.y){6.H.1X=0;6.H.1P=0;6.H.W=i;6.H.1i(i.x,i.y,j,6.H.B.1M)}}A(6.1Q){6.H.Z("1V")}},3C:C(i){i=i||0;6.17[c.I.1R]=i+"4m";A(!i&&c.2Z){6.17[c.I.1R]="0.48"}},2A:C(i){6.17[c.I.2A]=i},1v:C(){6.3C();A(6.B.1L&&!6.B.2d){6.17.47=6.H.1o?"44":"3n"}D{A(6.B.2d&&!6.B.1L){6.17.47=6.H.1k?"44":"3n"}D{6.17.47=6.H.1o||6.H.1k?"44":"3n"}}A(6.H.1o&&6.H.1k){c.4a(6.J,"5H");c.4b(6.J,"5N");A(6.B.2w&&6.B.3D){A(6.B.1L){6.J.I.2v="5u"}D{6.J.I.3t="5u"}}}D{c.4b(6.J,"5H");c.4a(6.J,"5N");A(6.B.2w&&6.B.3D){A(6.B.1L){6.J.I.2v="2s"}D{6.J.I.3t="2s"}}}F i=6.J.1Z;A(6.B.1L){6.1h=6.J.49;A(6.B.2e){6.1u=e.X(e.N(6.1h*6.1h/(6.H.2B||6.1h||1)),8);6.17.1b=6.1u+"1d"}D{6.1u=6.1y.49}6.1Y=6.1h-6.1u;A(6.B.1q=="5P"){6.3l=-6.1u+8;6.3q=6.1h-8}D{6.3l=0;6.3q=6.1Y}6.3u=6.B.5Q||(6.H.O&&(6.1Y/6.H.O))}A(6.B.2d){6.1e=6.J.4j;A(6.B.2e){6.1p=e.X(e.N(6.1e*6.1e/(6.H.2x||6.1e||1)),8);6.17.1c=6.1p+"1d"}D{6.1p=6.1y.4j}6.1N=6.1e-6.1p;A(6.B.1q=="5P"){6.3p=-6.1p+8;6.3r=6.1e-8}D{6.3p=0;6.3r=6.1N}6.1N=6.1e-6.1p;6.3s=6.B.5L||(6.H.S&&(6.1N/6.H.S))}6.4r()},4r:C(){F i=6.B.1L&&e.N(6.3u*6.H.x)||0,j=6.B.2d&&e.N(6.3s*6.H.y)||0;A(!6.B.7y){A(i<6.3l){A(6.B.1q=="V"){6.1b=e.X(6.1u+i,8);6.17.1b=6.1b+"1d"}i=6.3l}D{A(i>6.3q){A(6.B.1q=="V"){6.1b=e.X(6.1u-(i-6.1Y),8);6.17.1b=6.1b+"1d";i=6.1Y+6.1u-6.1b}D{i=6.3q}}D{A(6.B.1q=="V"&&6.1b!=6.1u){6.1b=6.1u;6.17.1b=6.1b+"1d"}}}A(j<6.3p){A(6.B.1q=="V"){6.1c=e.X(6.1p+j*3,8);6.17.1c=6.1c+"1d"}j=6.3p}D{A(j>6.3r){A(6.B.1q=="V"){6.1c=e.X(6.1p-(j-6.1N)*3,8);6.17.1c=6.1c+"1d";j=6.1N+6.1p-6.1c}D{j=6.3r}}D{A(6.B.1q=="V"&&6.1c!=6.1p){6.1c=6.1p;6.17.1c=6.1c+"1d"}}}}6.x=i;6.y=j;A(6.H.B.2z){6.17[c.I.2r]="5p("+i+"1d,"+j+"1d)"+6.H.2P}D{6.17.14=i+"1d";6.17.18=j+"1d"}},5s:C(i,j){A(i<0){i=0}D{A(i>6.1Y){i=6.1Y}}A(j<0){j=0}D{A(j>6.1N){j=6.1N}}i=6.B.1L?e.N(i/6.3u):6.H.x;j=6.B.2d?e.N(j/6.3s):6.H.y;6.H.1i(i,j)},1J:C(l,k){A(k&&!6.68){E}3j(6.4l);6.4l=3i;F j=l?7n:7o,i=l?0:1C;l=l?"1":"0";6.2n[c.I.1R]=j+"4m";6.4l=2Q((C(m){6.2n.6b=m;6.68=+m}).7l(6,l),i)}};g.7m=c;A(1T 4p!="1A"&&4p.5R){4p.5R=g}D{f.7r=g}})(7s,7p,7q);',62,494,'||||||this||||||||||||||||||||||||||||||if|options|function|else|return|var|case|scroller|style|wrapper|true|pages|abs|round|maxScrollX|pageY|false|pageX|maxScrollY|touches|length|scale|currentPage|max|break|_0||preventDefault|||left|removeEvent|in|indicatorStyle|top|indicators|keyBindings|width|height|px|wrapperHeight|for|addEvent|wrapperWidth|scrollTo|initiated|hasVerticalScroll|eventPassthrough|prefixPointerEvent|_1|hasHorizontalScroll|indicatorHeight|shrink|getTime|on|snap|indicatorWidth|refresh|isInTransition|min|indicator|keyAcceleration|undefined|zoomMax|300|zoomMin|enabled|useTransition|1000|type|startX|fade|startY|listenX|bounceEasing|maxPosY|wrapperOffset|directionY|moved|transitionDuration|scrollerStyle|typeof|className|scrollEnd|eventType|directionX|maxPosX|offsetHeight||pointermove||mousemove|directionLocked||destroy|el|touchmove|tap|goToPage|_2|mouseWheelSpeed|listenY|resize|touchstart|pointerdown|click|preventDefaultException|bounce|pointerup|bounceTime|mouseup|wrapperStyle|mousedown|touchend|fn|transform|2px|snapThreshold|wheelTimeout|right|defaultScrollbars|scrollerHeight|string|useTransform|transitionTimingFunction|scrollerWidth|zoom|box|directionLockThreshold|startTime|stopPropagation|scrollbars|detail|interactive|wheelDelta|originY|originX|cssText|target|translateZ|setTimeout|duration|border|destination|momentum|ease|scrollY|offsetLeft|deltaY|isBadAndroid|push|test|||||||||resetPosition|isAnimating|extend|offsetWidth|new|startScale|100|5625|null|clearTimeout|scrollX|minBoundaryX|_5|none|vertical|minBoundaryY|maxBoundaryX|maxBoundaryY|sizeRatioY|bottom|sizeRatioX|wheelDeltaY|_6|scrollStart|resizePolling|_4|_3|invertWheelDirection|transitionTime|customStyle|snapSpeed|toUpperCase|snapThresholdY|snapThresholdX|cy|255|cx|getComputedPosition|while|pointX|pointY|deltaX|120|wheel|mousewheel|scaled|keydown|flick|distX|sizing|distY|div||createElement|offsetTop|DOMMouseScroll|block|||display|001s|clientWidth|addClass|removeClass|_8|beforeScrollStart|disableMouse|disablePointer|resizeScrollbars|lastPointY|lastPointX|clientHeight|circular|fadeTimeout|ms|cubic|endTime|module|offset|updatePosition|horizontal|replace|substr|_7|split|bezier|hasClass|transformOrigin|pow|switch|sqrt|freeScroll|querySelector|fadeScrollbars|appendChild|mousecancel|pointercancel|shrinkScrollbars|zoomStart|disableTouch|MSPointerMove|MSPointerUp|MSPointerDown|touchcancel|hasTransform|_11|hasTransition|tagName|hasPerspective|touchesDistanceStart|resizeTimeout|INPUT|TEXTAREA|deceleration||HWCompositing|SELECT|quadratic|_15|call|scrollCancel||_9|_10|wheelDeltaX|_13|400|absStartY|_12|_14|changedTouches|hasTouch|zoomEnd|absStartX|hasPointer|position|absolute|_20|createEvent|translate|rgba|MSPointerEvent|_19|oTransitionEnd|8px|transitionend|webkitTransitionEnd|_16|_18|_17|charAt|handleEvent|MSPointerCancel|RegExp|prototype|appVersion|navigator|iScrollBothScrollbars|transitionDelay|1px|enable|speedRatioY|7px|iScrollLoneScrollbar|children|clip|speedRatioX|exports|down|up|Date|_22|keyTime|home|200|dispatchEvent||MSTransitionEnd|end|pageDown|pageUp|_23|_25|_21|visible|orientationchange|_24|opacity|MSPointer|removeEventListener|oRequestAnimationFrame|webkitRequestAnimationFrame|mozRequestAnimationFrame|msRequestAnimationFrame|MozT|webkitT|OT|msT|perspective|ontouchstart|now|ransform|0006|addEventListener|PointerEvent|transition|Android|Chrome|screenY|version|clientY|clientX|initMouseEvent|mouseWheel|screenX|view|BUTTON|_26|600|334|altKey|ctrlKey|metaKey|shiftKey|button|885|175|9375|275|offsetParent|join|back|94|Event|PI|MouseEvents|initEvent|984375|625|sin|elastic|disable|background||solid|webkit|moz|iScrollIndicator|iScrollHorizontalScrollbar|radius|3px|keyCode|default|object|charCodeAt|index|9999|requestAnimationFrame|wheelAction|bind|utils|250|500|document|Math|IScroll|window|hidden|pointerEvents|iScrollVerticalScrollbar|overflow|removeChild|ignoreBoundaries|0ms|parentNode|auto|scrollBy|scrollToElement|arguments|bindToWrapper|delete|isNaN|querySelectorAll|01|deltaMode|nodeType|snapStepY|snapStepX|getComputedStyle|splice|concat|indexOf|off|next|apply|prev|slice|interactiveScrollbars'.split('|'),0,{})) 2 | -------------------------------------------------------------------------------- /js/clip_module.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 依赖插件 3 | * - iscroll-zoom.js 4 | * - hammer.js 5 | * - lrz.all.bundle.js 6 | * 7 | * @brief 支持手势的裁图插件 8 | * 在移动设备上双指捏合为缩放,双指旋转可根据旋转方向每次旋转90度 9 | * 在PC设备上鼠标滚轮为缩放,每次双击则顺时针旋转90度 10 | * @option_param {array} size 截取框的宽和高组成的数组。默认值为[260,260] 11 | * @option_param {array} outputSize 输出图像的宽和高组成的数组。默认值为[0,0],表示输出图像原始大小 12 | * @option_param {string} outputType 指定输出图片的类型,可选 "jpg" 和 "png" 两种种类型,默认为 "jpg" 13 | * @option_param {string} file 上传图片的控件的选择器或者DOM对象 14 | * @option_param {string} source 需要裁剪图片的url地址。该参数表示当前立即开始裁剪的图片,不需要使用file控件获取。注意,该参数不支持跨域图片。 15 | * @option_param {string} view 显示截取后图像的容器的选择器或者DOM对象 16 | * @option_param {string} ok 确认截图按钮的选择器或者DOM对象 17 | * @option_param {function} loadStart 开始加载的回调函数。this指向 fileReader 对象,并将正在加载的 file 对象作为参数传入 18 | * @option_param {function} loadComplete 加载完成的回调函数。this指向图片对象,并将图片地址作为参数传入 19 | * @option_param {function} loadError 加载失败的回调函数。this指向 fileReader 对象,并将错误事件的 event 对象作为参数传入 20 | * @option_param {function} clipFinish 裁剪完成的回调函数。this指向原图片对象,会将裁剪出的图像数据DataURL作为参数传入 21 | * @option_param {object} lrzOption lrz压缩插件的配置参数 22 | * @lrzOption_param {Number} width 图片最大不超过的宽度,默认为原图宽度,高度不设时会适应宽度。 23 | * @lrzOption_param {Number} height 图片最大不超过的高度,默认为原图高度,宽度不设时会适应高度。 24 | * @lrzOption_param {Number} quality 图片压缩质量,取值 0 - 1,默认为0.7。 25 | */ 26 | define(['zepto.min.js', 'clip/iscroll-zoom.js', 'clip/hammer.js', 'clip/lrz.all.bundle.js'], function(require, exports, module) { 27 | var defaultOption = { 28 | size: [260, 260], 29 | outputSize: [0, 0], 30 | outputType: "jpg", 31 | file: "", 32 | source: "", 33 | view: "", 34 | ok: "", 35 | circle:false, 36 | loadStart: function() {}, 37 | loadComplete: function() {}, 38 | loadError: function() {}, 39 | clipFinish: function() {}, 40 | lrzOption: {quality:1} 41 | } 42 | 43 | function clipImage(container, option) { 44 | var size = option.size, 45 | circle=option.circle, 46 | outputSize = option.outputSize, 47 | lrzOption = option.lrzOption, 48 | outputType = option.outputType || "image/jpeg", 49 | file = option.file, 50 | source = option.source, 51 | view = option.view, 52 | ok = option.ok, 53 | loadStart = option.loadStart, 54 | loadComplete = option.loadComplete, 55 | loadError = option.loadError, 56 | clipFinish = option.clipFinish; 57 | 58 | var clipWidth = size[0] || 260, 59 | clipHeight = size[1] || 260, 60 | outputWidth = Math.max(outputSize[0], 0), 61 | outputHeight = Math.max(outputSize[1], 0); 62 | 63 | var $img, 64 | imgWidth, imgHeight, //图片当前的宽高 65 | imgLoaded; //图片是否已经加载完成 66 | 67 | var $container, // 容器,包含裁剪视图层和遮罩层 68 | $clipView, // 裁剪视图层,包含移动层 69 | $moveLayer, // 移动层,包含旋转层 70 | $rotateLayer, // 旋转层 71 | $view, // 最终截图后呈现的视图容器 72 | canvas = document.createElement("canvas"), // 图片裁剪用到的画布 73 | hammerManager, 74 | myScroll, // 图片的scroll对象,包含图片的位置与缩放信息 75 | containerWidth, 76 | containerHeight; 77 | 78 | var atRotation, // 是否正在旋转中 79 | curX, // 旋转层的当前X坐标 80 | curY, // 旋转层的当前Y坐标 81 | curAngle; // 旋转层的当前角度 82 | 83 | if(outputType === "jpg") { 84 | outputType = "image/jpeg"; 85 | } else if(outputType === "png") { 86 | outputType = "image/png"; 87 | } 88 | 89 | if(source) { 90 | createImg(source); 91 | } 92 | 93 | if($(file).length) { 94 | $(file).attr("accept", "image/*"); 95 | $(file).on("change", function() { 96 | if(!this.files.length) return; 97 | var files = this.files[0]; 98 | if(!/image\/\w+/.test(files.type)) { 99 | console.log("图片格式不正确,请选择正确格式的图片文件!"); 100 | return false; 101 | } else { 102 | var fileReader = new FileReader(); 103 | fileReader.onload = function(e) { 104 | lrz(files, lrzOption).then(function(rst) { 105 | createImg(rst.base64); 106 | }).catch(function(err) { 107 | loadError.call(this, err); 108 | }); 109 | }; 110 | fileReader.onerror = function(e) { 111 | loadError.call(this, e); 112 | }; 113 | fileReader.readAsDataURL(files); // 读取文件内容 114 | loadStart.call(fileReader, files); 115 | } 116 | }); 117 | } 118 | 119 | init(); 120 | initScroll(); 121 | initEvent(); 122 | 123 | $(ok).click(function() { //裁剪图片 124 | if(!imgLoaded) { 125 | console.log("亲,当前没有图片可以裁剪!"); 126 | } else { 127 | var local = loaclToLoacl($moveLayer, $clipView); 128 | var scale = myScroll.scale; 129 | var ctx = canvas.getContext("2d"); 130 | ctx.clearRect(0, 0, canvas.width, canvas.height); 131 | ctx.save(); 132 | 133 | if(!outputWidth || !outputHeight) { 134 | canvas.width = clipWidth / scale; 135 | canvas.height = clipHeight / scale; 136 | } else { 137 | canvas.width = outputWidth; 138 | canvas.height = outputHeight; 139 | ctx.scale(outputWidth / clipWidth * scale, outputHeight / clipHeight * scale); 140 | } 141 | ctx.translate(curX - local.x / scale, curY - local.y / scale); 142 | ctx.rotate(curAngle * Math.PI / 180); 143 | ctx.drawImage($img[0], 0, 0); 144 | ctx.restore(); 145 | try { 146 | var dataURL = canvas.toDataURL(outputType, 1); 147 | } catch(e) { 148 | throw new Error("截图失败!当前图片源文件可能存在跨域问题,请确保图片与应用同源。如果您是在本地环境下执行本程序,请更换至服务器环境。"); 149 | } 150 | $view.css("background-image", "url(" + dataURL + ")"); 151 | clipFinish.call($img[0], dataURL); 152 | } 153 | }); 154 | resize(); 155 | $(window).resize(resize); 156 | 157 | function initScroll() { 158 | var options = { 159 | zoom: true, 160 | scrollX: true, 161 | scrollY: true, 162 | freeScroll: true, 163 | mouseWheel: true, 164 | wheelAction: "zoom" 165 | } 166 | myScroll = new IScroll($clipView[0], options); 167 | } 168 | 169 | function resetScroll() { 170 | curX = 0; 171 | curY = 0; 172 | curAngle = 0; 173 | $rotateLayer.css({ 174 | "width": imgWidth, 175 | "height": imgHeight 176 | }); 177 | setTransform($rotateLayer, curX, curY, curAngle); 178 | calculateScale(imgWidth, imgHeight); 179 | myScroll.zoom(myScroll.options.zoomStart); 180 | refreshScroll(imgWidth, imgHeight,true); 181 | var posX = (clipWidth - imgWidth * myScroll.options.zoomStart) * .5, 182 | posY = (clipHeight - imgHeight * myScroll.options.zoomStart) * .5; 183 | myScroll.scrollTo(posX, posY); 184 | } 185 | 186 | function refreshScroll(width, height,flag) { 187 | $moveLayer.css({ 188 | "width": width, 189 | "height": height 190 | }); 191 | // 在移动设备上,尤其是Android设备,当为一个元素重置了宽高时 192 | // 该元素的offsetWidth/offsetHeight、clientWidth/clientHeight等属性并不会立即更新,导致相关的js程序出现错误 193 | // iscroll 在刷新方法中正是使用了 offsetWidth/offsetHeight 来获取scroller元素($moveLayer)的宽高 194 | // 因此需要手动将元素重新添加进文档,迫使浏览器强制更新元素的宽高 195 | //$clipView.append($moveLayer); 196 | if(flag){ 197 | setTimeout(function(){ 198 | myScroll.refresh(); 199 | },50); 200 | }else{ 201 | myScroll.refresh(); 202 | } 203 | } 204 | 205 | function initEvent() { 206 | var is_mobile = !!navigator.userAgent.match(/mobile/i); 207 | if(is_mobile) { 208 | hammerManager = new Hammer($moveLayer[0]); 209 | hammerManager.add(new Hammer.Rotate()); 210 | 211 | var rotation, rotateDirection; 212 | hammerManager.on("rotatemove", function(e) { 213 | if(atRotation) return; 214 | rotation = e.rotation; 215 | if(rotation > 180) { 216 | rotation -= 360; 217 | } else if(rotation < -180) { 218 | rotation += 360; 219 | } 220 | rotateDirection = rotation > 0 ? 1 : rotation < 0 ? -1 : 0; 221 | }); 222 | hammerManager.on("rotateend", function(e) { 223 | if(atRotation) return; 224 | 225 | if(Math.abs(rotation) > 30) { 226 | if(rotateDirection == 1) { 227 | // 顺时针 228 | rotateCW(e.center); 229 | } else if(rotateDirection == -1) { 230 | // 逆时针 231 | rotateCCW(e.center); 232 | } 233 | } 234 | }); 235 | } else { 236 | $moveLayer.on("dblclick", function(e) { 237 | rotateCW({ 238 | x: e.clientX, 239 | y: e.clientY 240 | }); 241 | }); 242 | } 243 | } 244 | 245 | function rotateCW(point) { 246 | rotateBy(90, point); 247 | } 248 | 249 | function rotateCCW(point) { 250 | rotateBy(-90, point); 251 | } 252 | 253 | function rotateBy(angle, point) { 254 | if(atRotation) return; 255 | atRotation = true; 256 | var loacl; 257 | if(!point) { 258 | loacl = loaclToLoacl($moveLayer, $clipView, clipWidth * .5, clipHeight * .5); 259 | } else { 260 | loacl = globalToLoacl($moveLayer, point.x, point.y); 261 | } 262 | var origin = calculateOrigin(curAngle, loacl), // 旋转中使用的参考点坐标 263 | originX = origin.x, 264 | originY = origin.y, 265 | 266 | // 旋转层以零位为参考点旋转到新角度后的位置,与以当前计算的参考点“从零度”旋转到新角度后的位置,之间的左上角偏移量 267 | offsetX = 0, 268 | offsetY = 0, 269 | // 移动层当前的位置(即旋转层旋转前的位置),与旋转层以当前计算的参考点从当前角度旋转到新角度后的位置,之间的左上角偏移量 270 | parentOffsetX = 0, 271 | parentOffsetY = 0, 272 | 273 | newAngle = curAngle + angle, 274 | 275 | curImgWidth, // 移动层的当前宽度 276 | curImgHeight; // 移动层的当前高度 277 | 278 | if(newAngle == 90 || newAngle == -270) { 279 | offsetX = originX + originY; 280 | offsetY = originY - originX; 281 | 282 | if(newAngle > curAngle) { 283 | parentOffsetX = imgHeight - originX - originY; 284 | parentOffsetY = originX - originY; 285 | } else if(newAngle < curAngle) { 286 | parentOffsetX = (imgHeight - originY) - (imgWidth - originX); 287 | parentOffsetY = originX + originY - imgHeight; 288 | } 289 | 290 | curImgWidth = imgHeight; 291 | curImgHeight = imgWidth; 292 | } else if(newAngle == 180 || newAngle == -180) { 293 | offsetX = originX * 2; 294 | offsetY = originY * 2; 295 | 296 | if(newAngle > curAngle) { 297 | parentOffsetX = (imgWidth - originX) - (imgHeight - originY); 298 | parentOffsetY = imgHeight - (originX + originY); 299 | } else if(newAngle < curAngle) { 300 | parentOffsetX = imgWidth - (originX + originY); 301 | parentOffsetY = (imgHeight - originY) - (imgWidth - originX); 302 | } 303 | 304 | curImgWidth = imgWidth; 305 | curImgHeight = imgHeight; 306 | } else if(newAngle == 270 || newAngle == -90) { 307 | offsetX = originX - originY; 308 | offsetY = originX + originY; 309 | 310 | if(newAngle > curAngle) { 311 | parentOffsetX = originX + originY - imgWidth; 312 | parentOffsetY = (imgWidth - originX) - (imgHeight - originY); 313 | } else if(newAngle < curAngle) { 314 | parentOffsetX = originY - originX; 315 | parentOffsetY = imgWidth - originX - originY; 316 | } 317 | 318 | curImgWidth = imgHeight; 319 | curImgHeight = imgWidth; 320 | } else if(newAngle == 0 || newAngle == 360 || newAngle == -360) { 321 | offsetX = 0; 322 | offsetY = 0; 323 | 324 | if(newAngle > curAngle) { 325 | parentOffsetX = originX - originY; 326 | parentOffsetY = originX + originY - imgWidth; 327 | } else if(newAngle < curAngle) { 328 | parentOffsetX = originX + originY - imgHeight; 329 | parentOffsetY = originY - originX; 330 | } 331 | 332 | curImgWidth = imgWidth; 333 | curImgHeight = imgHeight; 334 | } 335 | // 将触摸点设为旋转时的参考点 336 | // 改变参考点的同时,要计算坐标的偏移,从而保证图片位置不发生变化 337 | if(curAngle == 0) { 338 | curX = 0; 339 | curY = 0; 340 | } else if(curAngle == 90 || curAngle == -270) { 341 | curX -= originX + originY; 342 | curY -= originY - originX; 343 | } else if(curAngle == 180 || curAngle == -180) { 344 | curX -= originX * 2; 345 | curY -= originY * 2; 346 | } else if(curAngle == 270 || curAngle == -90) { 347 | curX -= originX - originY; 348 | curY -= originX + originY; 349 | } 350 | curX = curX.toFixed(2) - 0; 351 | curY = curY.toFixed(2) - 0; 352 | setTransform($rotateLayer, curX, curY, curAngle, originX, originY); 353 | 354 | // 开始旋转 355 | setTransition($rotateLayer, curX, curY, newAngle, 200, function() { 356 | atRotation = false; 357 | curAngle = newAngle % 360; 358 | // 旋转完成后将参考点设回零位 359 | // 同时加上偏移,保证图片位置看上去没有变化 360 | // 这里要另外要加上父容器(移动层)零位与自身之间的偏移量 361 | curX += offsetX + parentOffsetX; 362 | curY += offsetY + parentOffsetY; 363 | curX = curX.toFixed(2) - 0; 364 | curY = curY.toFixed(2) - 0; 365 | setTransform($rotateLayer, curX, curY, curAngle); 366 | // 相应的父容器(移动层)要减去与旋转层之间的偏移量 367 | // 这样看上去就好像图片没有移动 368 | myScroll.scrollTo( 369 | myScroll.x - parentOffsetX * myScroll.scale, 370 | myScroll.y - parentOffsetY * myScroll.scale 371 | ); 372 | calculateScale(curImgWidth, curImgHeight); 373 | if(myScroll.scale < myScroll.options.zoomMin) { 374 | myScroll.zoom(myScroll.options.zoomMin); 375 | } 376 | 377 | refreshScroll(curImgWidth, curImgHeight); 378 | }); 379 | } 380 | 381 | 382 | function resize() { 383 | hideAction($container, function() { 384 | containerWidth = $container.width(); 385 | containerHeight = $container.height(); 386 | }); 387 | } 388 | 389 | function loaclToLoacl($layerOne, $layerTwo, x, y) { // 计算$layerTwo上的x、y坐标在$layerOne上的坐标 390 | x = x || 0; 391 | y = y || 0; 392 | var layerOneOffset, layerTwoOffset; 393 | hideAction($layerOne, function() { 394 | layerOneOffset = $layerOne.offset(); 395 | }); 396 | hideAction($layerTwo, function() { 397 | layerTwoOffset = $layerTwo.offset(); 398 | }); 399 | return { 400 | x: layerTwoOffset.left - layerOneOffset.left + x, 401 | y: layerTwoOffset.top - layerOneOffset.top + y 402 | }; 403 | } 404 | 405 | function globalToLoacl($layer, x, y) { // 计算相对于窗口的x、y坐标在$layer上的坐标 406 | x = x || 0; 407 | y = y || 0; 408 | var layerOffset; 409 | hideAction($layer, function() { 410 | layerOffset = $layer.offset(); 411 | }); 412 | return { 413 | x: x + $(window).scrollLeft() - layerOffset.left, 414 | y: y + $(window).scrollTop() - layerOffset.top 415 | }; 416 | } 417 | 418 | function hideAction(jq, func) { 419 | if(typeof(func) == "function") func.call(this); 420 | } 421 | 422 | function calculateOrigin(curAngle, point) { 423 | var scale = myScroll.scale; 424 | var origin = {}; 425 | if(curAngle == 0) { 426 | origin.x = point.x / scale; 427 | origin.y = point.y / scale; 428 | } else if(curAngle == 90 || curAngle == -270) { 429 | origin.x = point.y / scale; 430 | origin.y = imgHeight - point.x / scale; 431 | } else if(curAngle == 180 || curAngle == -180) { 432 | origin.x = imgWidth - point.x / scale; 433 | origin.y = imgHeight - point.y / scale; 434 | } else if(curAngle == 270 || curAngle == -90) { 435 | origin.x = imgWidth - point.y / scale; 436 | origin.y = point.x / scale; 437 | } 438 | return origin; 439 | } 440 | 441 | function getScale(w1, h1, w2, h2) { 442 | var sx = w1 / w2; 443 | var sy = h1 / h2; 444 | return sx > sy ? sx : sy; 445 | } 446 | 447 | function calculateScale(width, height) { 448 | myScroll.options.zoomMin = getScale(clipWidth, clipHeight, width, height); 449 | myScroll.options.zoomMax = Math.max(1, myScroll.options.zoomMin); 450 | myScroll.options.zoomStart = Math.min(myScroll.options.zoomMax, getScale(containerWidth, containerHeight, width, height)); 451 | } 452 | //创建图片 453 | function createImg(src) { 454 | if($img) { 455 | $rotateLayer.html('');// 删除旧的图片以释放内存,防止IOS设备的webview崩溃 456 | } 457 | $img = $(" ").css({"user-select": "none","pointer-events": "none"}); 458 | $img.on('load', function() { 459 | imgLoaded = true; 460 | $rotateLayer.append(this); 461 | hideAction.call(this, $img, function() { 462 | imgWidth = this.naturalWidth; 463 | imgHeight = this.naturalHeight; 464 | }); 465 | hideAction($moveLayer, function() { 466 | resetScroll(); 467 | }); 468 | loadComplete.call(this, this.src); 469 | }); 470 | $img.attr("src", src); 471 | } 472 | 473 | function setTransform($obj, x, y, angle, originX, originY) { 474 | originX = originX || 0; 475 | originY = originY || 0; 476 | var style = {}; 477 | style[prefix + "transform"] = "translateZ(0) translate(" + x + "px," + y + "px) rotate(" + angle + "deg)"; 478 | style[prefix + "transform-origin"] = originX + "px " + originY + "px"; 479 | $obj.css(style); 480 | } 481 | 482 | function setTransition($obj, x, y, angle, dur, fn) { 483 | console.info(1) 484 | // 这里需要先读取之前设置好的transform样式,强制浏览器将该样式值渲染到元素 485 | // 否则浏览器可能出于性能考虑,将暂缓样式渲染,等到之后所有样式设置完成后再统一渲染 486 | // 这样就会导致之前设置的位移也被应用到动画中 487 | $obj.css(prefix + "transform"); 488 | $obj.css(prefix + "transition", prefix + "transform " + dur + "ms"); 489 | $obj.one(transitionEnd, function() { 490 | $obj.css(prefix + "transition", ""); 491 | fn.call(this); 492 | }); 493 | $obj.css(prefix + "transform", "translateZ(0) translate(" + x + "px," + y + "px) rotate(" + angle + "deg)"); 494 | } 495 | 496 | function init() { 497 | // 初始化容器 498 | $container = $(container).css({ 499 | "user-select": "none", 500 | "overflow": "hidden" 501 | }); 502 | if($container.css("position") == "static") $container.css("position", "relative"); 503 | // 创建裁剪视图层 504 | $clipView = $("
").css({ 505 | "position": "absolute", 506 | "left": "50%", 507 | "top": "50%", 508 | "width": clipWidth, 509 | "height": clipHeight, 510 | "margin-left": -clipWidth / 2, 511 | "margin-top": -clipHeight / 2 512 | }).appendTo($container); 513 | $moveLayer = $("").appendTo($clipView); 514 | $rotateLayer = $("").appendTo($moveLayer); 515 | // 创建遮罩 516 | var $mask = $("").css({ 517 | "position": "absolute", 518 | "width": clipWidth, 519 | "height": clipHeight, 520 | 'border':$container.height()+'px solid rgba(0, 0, 0, 0.498039)', 521 | 'top':-($container.height()+clipHeight)/2+'px', 522 | 'left':-(($container.height()*2+clipHeight)-$container.width())/2+'px', 523 | "pointer-events": "none" 524 | }).appendTo($container); 525 | var $mask_view=$('').css({ 526 | 'border':'1px dashed rgb(221, 221, 221)', 527 | 'height':clipHeight, 528 | 'margin-left':-1, 529 | 'margin-top':-1, 530 | }).appendTo($mask); 531 | if(circle){ 532 | $mask_view.css('border-radius','50%'); 533 | $mask.css('border-radius','50%'); 534 | } 535 | // 初始化视图容器 536 | $view = $(view); 537 | if($view.length) { 538 | $view.css({ 539 | "background-color": "#666", 540 | "background-repeat": "no-repeat", 541 | "background-position": "center", 542 | "background-size": "contain" 543 | }); 544 | } 545 | } 546 | 547 | //销毁 548 | function destroy() { 549 | $(file).off("change"); 550 | $(file) = null; 551 | if(hammerManager) { 552 | hammerManager.off("rotatemove"); 553 | hammerManager.off("rotateend"); 554 | hammerManager.destroy(); 555 | hammerManager = null; 556 | } else { 557 | $moveLayer.off("dblclick"); 558 | } 559 | myScroll.destroy(); 560 | myScroll = null; 561 | $container.empty(); 562 | $container = null; 563 | $clipView = null; 564 | $moveLayer = null; 565 | $rotateLayer = null; 566 | 567 | $view.css({ 568 | "background-color": "", 569 | "background-repeat": "", 570 | "background-position": "", 571 | "background-size": "" 572 | }); 573 | $view = null; 574 | } 575 | } 576 | 577 | //css3兼容性 578 | var prefix = '', 579 | transitionEnd; 580 | (function() { 581 | var eventPrefix, 582 | vendors = { 583 | Webkit: 'webkit', 584 | Moz: '', 585 | O: 'o' 586 | }, 587 | testEl = document.documentElement, 588 | normalizeEvent = function(name) { 589 | return eventPrefix ? eventPrefix + name : name.toLowerCase() 590 | }; 591 | for(var i in vendors) { 592 | if(testEl.style[i + 'TransitionProperty'] !== undefined) { 593 | prefix = '-' + i.toLowerCase() + '-'; 594 | eventPrefix = vendors[i]; 595 | break; 596 | } 597 | } 598 | transitionEnd = normalizeEvent('TransitionEnd'); 599 | })(); 600 | 601 | var exports = { 602 | clipImage: function(container, option) { 603 | clipImage(container, option); 604 | } 605 | }; 606 | module.exports = exports; 607 | }); --------------------------------------------------------------------------------