utils.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. export const networkReg = /^(http|\/\/)/;
  2. export const isBase64 = (path) => /^data:image\/(\w+);base64/.test(path);
  3. export function sleep(delay) {
  4. return new Promise(resolve => setTimeout(resolve, delay))
  5. }
  6. let {platform, SDKVersion} = uni.getSystemInfoSync()
  7. export const isPC = /windows|mac/.test(platform)
  8. // 缓存图片
  9. let cache = {}
  10. export function isNumber(value) {
  11. return /^-?\d+(\.\d+)?$/.test(value);
  12. }
  13. export function toPx(value, baseSize, isDecimal = false) {
  14. // 如果是数字
  15. if (typeof value === 'number') {
  16. return value
  17. }
  18. // 如果是字符串数字
  19. if (isNumber(value)) {
  20. return value * 1
  21. }
  22. // 如果有单位
  23. if (typeof value === 'string') {
  24. const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g
  25. const results = reg.exec(value);
  26. if (!value || !results) {
  27. return 0;
  28. }
  29. const unit = results[3];
  30. value = parseFloat(value);
  31. let res = 0;
  32. if (unit === 'rpx') {
  33. res = uni.upx2px(value);
  34. } else if (unit === 'px') {
  35. res = value * 1;
  36. } else if (unit === '%') {
  37. res = value * toPx(baseSize) / 100;
  38. } else if (unit === 'em') {
  39. res = value * toPx(baseSize || 14);
  40. }
  41. return isDecimal ? res.toFixed(2) * 1 : Math.round(res);
  42. }
  43. return 0
  44. }
  45. // 计算版本
  46. export function compareVersion(v1, v2) {
  47. v1 = v1.split('.')
  48. v2 = v2.split('.')
  49. const len = Math.max(v1.length, v2.length)
  50. while (v1.length < len) {
  51. v1.push('0')
  52. }
  53. while (v2.length < len) {
  54. v2.push('0')
  55. }
  56. for (let i = 0; i < len; i++) {
  57. const num1 = parseInt(v1[i], 10)
  58. const num2 = parseInt(v2[i], 10)
  59. if (num1 > num2) {
  60. return 1
  61. } else if (num1 < num2) {
  62. return -1
  63. }
  64. }
  65. return 0
  66. }
  67. function gte(version) {
  68. // #ifdef MP-ALIPAY
  69. SDKVersion = my.SDKVersion
  70. // #endif
  71. return compareVersion(SDKVersion, version) >= 0;
  72. }
  73. export function canIUseCanvas2d() {
  74. // #ifdef MP-WEIXIN
  75. return gte('2.9.2');
  76. // #endif
  77. // #ifdef MP-ALIPAY
  78. return gte('2.7.15');
  79. // #endif
  80. // #ifdef MP-TOUTIAO
  81. return gte('1.78.0');
  82. // #endif
  83. return false
  84. }
  85. // #ifdef MP
  86. export const prefix = () => {
  87. // #ifdef MP-TOUTIAO
  88. return tt
  89. // #endif
  90. // #ifdef MP-WEIXIN
  91. return wx
  92. // #endif
  93. // #ifdef MP-BAIDU
  94. return swan
  95. // #endif
  96. // #ifdef MP-ALIPAY
  97. return my
  98. // #endif
  99. // #ifdef MP-QQ
  100. return qq
  101. // #endif
  102. // #ifdef MP-360
  103. return qh
  104. // #endif
  105. }
  106. // #endif
  107. /**
  108. * base64转路径
  109. * @param {Object} base64
  110. */
  111. export function base64ToPath(base64) {
  112. const [, format] = /^data:image\/(\w+);base64,/.exec(base64) || [];
  113. return new Promise((resolve, reject) => {
  114. // #ifdef MP
  115. const fs = uni.getFileSystemManager()
  116. //自定义文件名
  117. if (!format) {
  118. reject(new Error('ERROR_BASE64SRC_PARSE'))
  119. }
  120. const time = new Date().getTime();
  121. let pre = prefix()
  122. // #ifdef MP-TOUTIAO
  123. const filePath = `${pre.getEnvInfoSync().common.USER_DATA_PATH}/${time}.${format}`
  124. // #endif
  125. // #ifndef MP-TOUTIAO
  126. const filePath = `${pre.env.USER_DATA_PATH}/${time}.${format}`
  127. // #endif
  128. fs.writeFile({
  129. filePath,
  130. data: base64.split(',')[1],
  131. encoding: 'base64',
  132. success() {
  133. resolve(filePath)
  134. },
  135. fail(err) {
  136. console.error(err)
  137. reject(err)
  138. }
  139. })
  140. // #endif
  141. // #ifdef H5
  142. // mime类型
  143. let mimeString = base64.split(',')[0].split(':')[1].split(';')[0];
  144. //base64 解码
  145. let byteString = atob(base64.split(',')[1]);
  146. //创建缓冲数组
  147. let arrayBuffer = new ArrayBuffer(byteString.length);
  148. //创建视图
  149. let intArray = new Uint8Array(arrayBuffer);
  150. for (let i = 0; i < byteString.length; i++) {
  151. intArray[i] = byteString.charCodeAt(i);
  152. }
  153. resolve(URL.createObjectURL(new Blob([intArray], {
  154. type: mimeString
  155. })))
  156. // #endif
  157. // #ifdef APP-PLUS
  158. const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
  159. bitmap.loadBase64Data(base64, () => {
  160. if (!format) {
  161. reject(new Error('ERROR_BASE64SRC_PARSE'))
  162. }
  163. const time = new Date().getTime();
  164. const filePath = `_doc/uniapp_temp/${time}.${format}`
  165. bitmap.save(filePath, {},
  166. () => {
  167. bitmap.clear()
  168. resolve(filePath)
  169. },
  170. (error) => {
  171. bitmap.clear()
  172. reject(error)
  173. })
  174. }, (error) => {
  175. bitmap.clear()
  176. reject(error)
  177. })
  178. // #endif
  179. })
  180. }
  181. /**
  182. * 路径转base64
  183. * @param {Object} string
  184. */
  185. export function pathToBase64(path) {
  186. if (/^data:/.test(path)) return path
  187. return new Promise((resolve, reject) => {
  188. // #ifdef H5
  189. let image = new Image();
  190. image.setAttribute("crossOrigin", 'Anonymous');
  191. image.onload = function() {
  192. let canvas = document.createElement('canvas');
  193. canvas.width = this.naturalWidth;
  194. canvas.height = this.naturalHeight;
  195. canvas.getContext('2d').drawImage(image, 0, 0);
  196. let result = canvas.toDataURL('image/png')
  197. resolve(result);
  198. canvas.height = canvas.width = 0
  199. }
  200. image.src = path + '?v=' + Math.random()
  201. image.onerror = (error) => {
  202. reject(error);
  203. };
  204. // #endif
  205. // #ifdef MP
  206. if (uni.canIUse('getFileSystemManager')) {
  207. uni.getFileSystemManager().readFile({
  208. filePath: path,
  209. encoding: 'base64',
  210. success: (res) => {
  211. resolve('data:image/png;base64,' + res.data)
  212. },
  213. fail: (error) => {
  214. console.error({error, path})
  215. reject(error)
  216. }
  217. })
  218. }
  219. // #endif
  220. // #ifdef APP-PLUS
  221. plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), (entry) => {
  222. entry.file((file) => {
  223. const fileReader = new plus.io.FileReader()
  224. fileReader.onload = (data) => {
  225. resolve(data.target.result)
  226. }
  227. fileReader.onerror = (error) => {
  228. reject(error)
  229. }
  230. fileReader.readAsDataURL(file)
  231. }, reject)
  232. }, reject)
  233. // #endif
  234. })
  235. }
  236. export function getImageInfo(path, useCORS) {
  237. const isCanvas2D = this && this.canvas && this.canvas.createImage
  238. return new Promise(async (resolve, reject) => {
  239. // let time = +new Date()
  240. let src = path.replace(/^@\//,'/')
  241. if (cache[path] && cache[path].errMsg) {
  242. resolve(cache[path])
  243. } else {
  244. try {
  245. // #ifdef MP || APP-PLUS
  246. if (isBase64(path) && (isCanvas2D ? isPC : true)) {
  247. src = await base64ToPath(path)
  248. }
  249. // #endif
  250. // #ifdef H5
  251. if(useCORS) {
  252. src = await pathToBase64(path)
  253. }
  254. // #endif
  255. } catch (error) {
  256. reject({
  257. ...error,
  258. src
  259. })
  260. }
  261. // #ifndef APP-NVUE
  262. if(isCanvas2D && !isPC) {
  263. const img = this.canvas.createImage()
  264. img.onload = function() {
  265. const image = {
  266. path: img,
  267. width: img.width,
  268. height: img.height
  269. }
  270. cache[path] = image
  271. resolve(cache[path])
  272. }
  273. img.onerror = function(err) {
  274. reject({err,path})
  275. }
  276. img.src = src
  277. return
  278. }
  279. // #endif
  280. uni.getImageInfo({
  281. src,
  282. success: (image) => {
  283. const localReg = /^\.|^\/(?=[^\/])/;
  284. // #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO
  285. image.path = localReg.test(src) ? `/${image.path}` : image.path;
  286. // #endif
  287. if(isCanvas2D) {
  288. const img = this.canvas.createImage()
  289. img.onload = function() {
  290. image.path = img
  291. cache[path] = image
  292. resolve(cache[path])
  293. }
  294. img.onerror = function(err) {
  295. reject({err,path})
  296. }
  297. img.src = src
  298. return
  299. }
  300. // #ifdef APP-PLUS
  301. // console.log('getImageInfo', +new Date() - time)
  302. // ios 比较严格 可能需要设置跨域
  303. if(uni.getSystemInfoSync().osName == 'ios' && useCORS) {
  304. pathToBase64(image.path).then(base64 => {
  305. image.path = base64
  306. cache[path] = image
  307. resolve(cache[path])
  308. }).catch(err => {
  309. console.error({err, path})
  310. reject({err,path})
  311. })
  312. return
  313. }
  314. // #endif
  315. cache[path] = image
  316. resolve(cache[path])
  317. },
  318. fail(err) {
  319. console.error({err, path})
  320. reject({err,path})
  321. }
  322. })
  323. }
  324. })
  325. }
  326. // #ifdef APP-PLUS
  327. const getLocalFilePath = (path) => {
  328. if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path
  329. .indexOf('_downloads') === 0) {
  330. return path
  331. }
  332. if (path.indexOf('file://') === 0) {
  333. return path
  334. }
  335. if (path.indexOf('/storage/emulated/0/') === 0) {
  336. return path
  337. }
  338. if (path.indexOf('/') === 0) {
  339. const localFilePath = plus.io.convertAbsoluteFileSystem(path)
  340. if (localFilePath !== path) {
  341. return localFilePath
  342. } else {
  343. path = path.substr(1)
  344. }
  345. }
  346. return '_www/' + path
  347. }
  348. // #endif