uploader.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. (function( factory ) {
  2. if ( !window.jQuery ) {
  3. alert('jQuery is required.')
  4. }
  5. jQuery(function() {
  6. factory.call( null, jQuery );
  7. });
  8. })(function( $ ) {
  9. var Uploader = (function() {
  10. // -------setting-------
  11. // 如果使用原始大小,超大的图片可能会出现 Croper UI 卡顿,所以这里建议先缩小后再crop.
  12. var FRAME_WIDTH = 1600;
  13. var _ = WebUploader;
  14. var Uploader = _.Uploader;
  15. var uploaderContainer = $('.uploader-container');
  16. var uploader, file;
  17. if ( !Uploader.support() ) {
  18. alert( 'Web Uploader 不支持您的浏览器!');
  19. throw new Error( 'WebUploader does not support the browser you are using.' );
  20. }
  21. // hook,
  22. // 在文件开始上传前进行裁剪。
  23. Uploader.register({
  24. 'before-send-file': 'cropImage'
  25. }, {
  26. cropImage: function( file ) {
  27. var data = file._cropData,
  28. image, deferred;
  29. file = this.request( 'get-file', file );
  30. deferred = _.Deferred();
  31. image = new _.Lib.Image();
  32. deferred.always(function() {
  33. image.destroy();
  34. image = null;
  35. });
  36. image.once( 'error', deferred.reject );
  37. image.once( 'load', function() {
  38. image.crop( data.x, data.y, data.width, data.height, data.scale );
  39. });
  40. image.once( 'complete', function() {
  41. var blob, size;
  42. // 移动端 UC / qq 浏览器的无图模式下
  43. // ctx.getImageData 处理大图的时候会报 Exception
  44. // INDEX_SIZE_ERR: DOM Exception 1
  45. try {
  46. blob = image.getAsBlob();
  47. size = file.size;
  48. file.source = blob;
  49. file.size = blob.size;
  50. file.trigger( 'resize', blob.size, size );
  51. deferred.resolve();
  52. } catch ( e ) {
  53. console.log( e );
  54. // 出错了直接继续,让其上传原始图片
  55. deferred.resolve();
  56. }
  57. });
  58. file._info && image.info( file._info );
  59. file._meta && image.meta( file._meta );
  60. image.loadFromBlob( file.source );
  61. return deferred.promise();
  62. }
  63. });
  64. return {
  65. init: function( selectCb ) {
  66. uploader = new Uploader({
  67. pick: {
  68. id: '#filePicker',
  69. multiple: false
  70. },
  71. // 设置用什么方式去生成缩略图。
  72. thumb: {
  73. quality: 70,
  74. // 不允许放大
  75. allowMagnify: false,
  76. // 是否采用裁剪模式。如果采用这样可以避免空白内容。
  77. crop: false
  78. },
  79. // 禁掉分块传输,默认是开起的。
  80. chunked: false,
  81. // 禁掉上传前压缩功能,因为会手动裁剪。
  82. compress: false,
  83. // fileSingleSizeLimit: 2 * 1024 * 1024,
  84. server: '../server/fileupload.php',
  85. swf: '../Uploader.swf',
  86. fileNumLimit: 1,
  87. onError: function() {
  88. var args = [].slice.call(arguments, 0);
  89. alert(args.join('\n'));
  90. }
  91. });
  92. uploader.on('fileQueued', function( _file ) {
  93. file = _file;
  94. uploader.makeThumb( file, function( error, src ) {
  95. if ( error ) {
  96. alert('不能预览');
  97. return;
  98. }
  99. selectCb( src );
  100. }, FRAME_WIDTH, 1 ); // 注意这里的 height 值是 1,被当成了 100% 使用。
  101. });
  102. },
  103. crop: function( data ) {
  104. var scale = Croper.getImageSize().width / file._info.width;
  105. data.scale = scale;
  106. file._cropData = {
  107. x: data.x1,
  108. y: data.y1,
  109. width: data.width,
  110. height: data.height,
  111. scale: data.scale
  112. };
  113. },
  114. upload: function() {
  115. uploader.upload();
  116. }
  117. }
  118. })();
  119. var Croper = (function() {
  120. var container = $('.cropper-wraper');
  121. var $image = container.find('.img-container img');
  122. var btn = $('.upload-btn');
  123. var isBase64Supported, callback;
  124. $image.cropper({
  125. aspectRatio: 16 / 9,
  126. preview: ".img-preview",
  127. done: function(data) {
  128. // console.log(data);
  129. }
  130. });
  131. function srcWrap( src, cb ) {
  132. // we need to check this at the first time.
  133. if (typeof isBase64Supported === 'undefined') {
  134. (function() {
  135. var data = new Image();
  136. var support = true;
  137. data.onload = data.onerror = function() {
  138. if( this.width != 1 || this.height != 1 ) {
  139. support = false;
  140. }
  141. }
  142. data.src = src;
  143. isBase64Supported = support;
  144. })();
  145. }
  146. if ( isBase64Supported ) {
  147. cb( src );
  148. } else {
  149. // otherwise we need server support.
  150. // convert base64 to a file.
  151. $.ajax('../server/preview.php', {
  152. method: 'POST',
  153. data: src,
  154. dataType:'json'
  155. }).done(function( response ) {
  156. if (response.result) {
  157. cb( response.result );
  158. } else {
  159. alert("预览出错");
  160. }
  161. });
  162. }
  163. }
  164. btn.on('click', function() {
  165. callback && callback($image.cropper("getData"));
  166. return false;
  167. });
  168. return {
  169. setSource: function( src ) {
  170. // 处理 base64 不支持的情况。
  171. // 一般出现在 ie6-ie8
  172. srcWrap( src, function( src ) {
  173. $image.cropper("setImgSrc", src);
  174. });
  175. container.removeClass('webuploader-element-invisible');
  176. return this;
  177. },
  178. getImageSize: function() {
  179. var img = $image.get(0);
  180. return {
  181. width: img.naturalWidth,
  182. height: img.naturalHeight
  183. }
  184. },
  185. setCallback: function( cb ) {
  186. callback = cb;
  187. return this;
  188. },
  189. disable: function() {
  190. $image.cropper("disable");
  191. return this;
  192. },
  193. enable: function() {
  194. $image.cropper("enable");
  195. return this;
  196. }
  197. }
  198. })();
  199. var container = $('.uploader-container');
  200. Uploader.init(function( src ) {
  201. Croper.setSource( src );
  202. // 隐藏选择按钮。
  203. container.addClass('webuploader-element-invisible');
  204. // 当用户选择上传的时候,开始上传。
  205. Croper.setCallback(function( data ) {
  206. Uploader.crop(data);
  207. Uploader.upload();
  208. });
  209. });
  210. });