compress.vue 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. <template>
  2. <view class="compress">
  3. <canvas :style="{ width: canvasSize.width,height: canvasSize.height}" canvas-id="myCanvas"></canvas>
  4. </view>
  5. </template>
  6. <script>
  7. export default {
  8. data() {
  9. return {
  10. pic:'',
  11. canvasSize: {
  12. width: 0,
  13. height: 0
  14. }
  15. }
  16. },
  17. methods: {
  18. // 压缩
  19. compress(params) {
  20. return new Promise(async (resolve, reject) => {
  21. // 等待图片信息
  22. let info = await this.getImageInfo(params.src).then(info=>info).catch(err=>err);
  23. if(!info){
  24. reject('获取图片信息异常');
  25. return;
  26. }
  27. // 设置最大 & 最小 尺寸
  28. const maxSize = params.maxSize || 1080;
  29. const minSize = params.minSize || 640;
  30. // 当前图片尺寸
  31. let {width,height} = info;
  32. // 非 H5 平台进行最小尺寸校验
  33. // #ifndef H5
  34. if(width <= minSize && height <= minSize){
  35. resolve(params.src);
  36. return;
  37. }
  38. // #endif
  39. // 最大尺寸计算
  40. if (width > maxSize || height > maxSize) {
  41. if (width > height) {
  42. height = Math.floor(height / (width / maxSize));
  43. width = maxSize;
  44. } else {
  45. width = Math.floor(width / (height / maxSize));
  46. height = maxSize;
  47. }
  48. }
  49. // 设置画布尺寸
  50. this.$set(this,"canvasSize",{
  51. width: `${width}rpx`,
  52. height: `${height}rpx`
  53. });
  54. // Vue.nextTick 回调在 App 有异常,则使用 setTimeout 等待DOM更新
  55. setTimeout(() => {
  56. const ctx = uni.createCanvasContext('myCanvas', this);
  57. ctx.clearRect(0,0,width, height)
  58. ctx.drawImage(info.path, 0, 0, uni.upx2px(width), uni.upx2px(height));
  59. ctx.draw(false, () => {
  60. uni.canvasToTempFilePath({
  61. x: 0,
  62. y: 0,
  63. width: uni.upx2px(width),
  64. height: uni.upx2px(height),
  65. destWidth: width,
  66. destHeight: height,
  67. canvasId: 'myCanvas',
  68. fileType: params.fileType || 'png',
  69. quality: params.quality || 0.9,
  70. success: (res) => {
  71. // 在H5平台下,tempFilePath 为 base64
  72. resolve(res.tempFilePath);
  73. },
  74. fail:(err)=>{
  75. reject(null);
  76. }
  77. },this);
  78. });
  79. }, 300);
  80. });
  81. },
  82. // 获取图片信息
  83. getImageInfo(src){
  84. return new Promise((resolve, reject)=>{
  85. uni.getImageInfo({
  86. src,
  87. success: (info)=> {
  88. resolve(info);
  89. },
  90. fail: () => {
  91. reject(null);
  92. }
  93. });
  94. });
  95. },
  96. // 批量压缩
  97. batchCompress(params){
  98. // index:进度,done:成功,fail:失败
  99. let [index,done,fail] = [0,0,0];
  100. // 压缩完成的路径集合
  101. let paths = [];
  102. // 批量压缩方法
  103. let batch = ()=>{
  104. return new Promise((resolve, reject)=>{
  105. // 开始
  106. let start = async ()=>{
  107. params.progress && params.progress({
  108. done,
  109. fail,
  110. count:params.batchSrc.length
  111. });
  112. // 等待图片压缩方法返回
  113. let path = await next();
  114. if(path){
  115. done++;
  116. paths.push(path);
  117. }else{
  118. fail++;
  119. }
  120. index++;
  121. // 压缩完成
  122. if(index >= params.batchSrc.length){
  123. resolve(true);
  124. }else{
  125. start();
  126. }
  127. }
  128. start();
  129. });
  130. }
  131. // 依次调用压缩方法
  132. let next = ()=>{
  133. return this.compress({
  134. src:params.batchSrc[index],
  135. maxSize:params.maxSize,
  136. fileType:params.fileType,
  137. quality:params.quality,
  138. minSize:params.minSize
  139. })
  140. }
  141. // 全部压缩完成后调用
  142. return new Promise(async (resolve, reject)=>{
  143. // 批量压缩方法回调
  144. let res = await batch();
  145. if(res){
  146. resolve(paths);
  147. }else{
  148. reject(null);
  149. }
  150. });
  151. }
  152. }
  153. }
  154. </script>
  155. <style lang="scss" scoped>
  156. .compress{
  157. position: fixed;
  158. width: 12px;
  159. height: 12px;
  160. overflow: hidden;
  161. top: -99999px;
  162. left: 0;
  163. }
  164. </style>