cropper.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. // pages/piano/cropper/cropper.js
  2. const { BtCmd } = require('../../../devices/bluetooth/bt_cmd');
  3. import EventManager from '../../../utils/event_bus'
  4. import { EnumCmdEvent, CmdEvent } from '../../../devices/cmd_key_event';
  5. import js_md5 from '../../../utils/js_md5';
  6. const { BtHelper } = require('../../../devices/bt_helper');
  7. Page({
  8. /**
  9. * 页面的初始数据
  10. */
  11. data: {
  12. navbarData: {
  13. showCapsule: 1, //是否显示左上角图标 1表示显示 0表示不显示
  14. title: '壁纸设置', //导航栏 中间的标题
  15. },
  16. src: "",
  17. width: 320,//宽度
  18. height: 320,//高度
  19. showProgress: false,
  20. _chunks: [],
  21. progress: 0,
  22. _timer: null,
  23. _imgUrl: null,
  24. _imgMD5: null,
  25. _imgIndex: null,
  26. _imgNext: 0,
  27. },
  28. cropper: null,
  29. callback() {
  30. let that = this
  31. if (this.data._chunks.length > 0) {
  32. wx.showModal({
  33. title: '保存壁纸中,确定要中断退出吗?',
  34. content: '',
  35. complete: (res) => {
  36. if (res.confirm) {
  37. that.endImage(2)
  38. wx.navigateBack({
  39. delta: 1,
  40. })
  41. }
  42. }
  43. })
  44. } else {
  45. wx.navigateBack({
  46. delta: 1,
  47. })
  48. }
  49. },
  50. cropperload(e) {
  51. console.log('cropper加载完成');
  52. },
  53. upload() {
  54. let that = this;
  55. wx.chooseMedia({
  56. count: 1,
  57. mediaType: ['image'],
  58. sourceType: ['album'],
  59. success(res) {
  60. wx.showLoading({
  61. title: '加载中',
  62. })
  63. const tempFilePaths = res.tempFiles[0].tempFilePath;
  64. // //重置壁纸角度、缩放、位置
  65. that.cropper.imgReset();
  66. that.setData({
  67. src: tempFilePaths
  68. });
  69. // that.testUpload(tempFilePaths)
  70. }, fail(res) {
  71. console.log(res)
  72. }
  73. })
  74. },
  75. loadimage(e) {
  76. wx.hideLoading();
  77. console.log('壁纸', e);
  78. this.cropper.imgReset();
  79. },
  80. clickcut(e) {
  81. console.log("clickcut:", e.detail);
  82. //壁纸预览
  83. wx.previewImage({
  84. current: e.detail.url,
  85. urls: [e.detail.url]
  86. })
  87. },
  88. cancel() {
  89. wx.navigateBack({
  90. delta: -1
  91. })
  92. },
  93. submit() {
  94. let _this = this
  95. // 读取裁剪的jpg图片
  96. const fs = wx.getFileSystemManager();
  97. this.cropper.getImg((obj) => {
  98. wx.showLoading({
  99. title: '壁纸裁剪中',
  100. })
  101. // app.globalData.imgSrc = obj.url;
  102. console.log("裁剪壁纸:", obj);
  103. _this.data._imgUrl = obj.url
  104. fs.readFile({
  105. filePath: obj.url,
  106. encoding: '', // 不指定编码以获取原始二进制数据
  107. success: (obj) => {
  108. console.log("加载文件成功:", obj.data.byteLength, obj.data.length)
  109. fs.getFileInfo({
  110. "filePath": _this.data._imgUrl, "digestAlgorithm": "md5", success: (res) => {
  111. console.log("md5:", res)
  112. console.log("加载文件成功:", obj.data.byteLength, obj.data.length, obj.getFileInfo)
  113. let binData = obj.data;
  114. let myMd5 = _this.getImgMde5(binData)
  115. wx.setClipboardData({
  116. data: myMd5,
  117. })
  118. _this.sliceDataIntoChunks(binData, 128);
  119. console.log("加载文件成功2:", binData.byteLength, binData.length)
  120. _this.data._imageBufferLength = binData.byteLength ?? binData.length
  121. wx.hideLoading();
  122. wx.showLoading({
  123. title: '开始传输壁纸',
  124. })
  125. _this.data._imgMD5 = myMd5
  126. _this.data._imgIndex = 0
  127. console.log("md5 2:", res.digest)
  128. _this.startImage()
  129. }, fail: (err) => {
  130. console.error('getFileInfo失败:', err);
  131. },
  132. })
  133. },
  134. fail: (err) => {
  135. console.error('读取 .bin 文件失败:', err);
  136. },
  137. });
  138. });
  139. // 651kb的
  140. // _this.downloadAndSaveFile("https://music-play.oss-cn-shenzhen.aliyuncs.com/backOss/file/8770a6097d9940b59032d099b2fdde3b.bin");
  141. },
  142. checkAndRequestImagePermission: function () {
  143. const _this = this;
  144. // 检查用户是否已经授权访问相册
  145. wx.getSetting({
  146. success(res) {
  147. if (!res.authSetting['scope.writePhotosAlbum']) {
  148. // 用户未授权访问相册,请求用户授权
  149. wx.authorize({
  150. scope: 'scope.writePhotosAlbum',
  151. success() {
  152. // 用户同意授权
  153. console.log('用户已授权访问相册1');
  154. _this.upload()
  155. // 可以在这里执行访问相册的操作
  156. },
  157. fail() {
  158. // 用户拒绝授权
  159. console.log('用户拒绝授权访问相册');
  160. wx.showModal({
  161. title: '提示',
  162. content: '您拒绝了访问相册的权限,无法上传壁纸',
  163. showCancel: false,
  164. success(res) {
  165. if (res.confirm) {
  166. // 跳转到设置页面
  167. wx.openSetting({
  168. success(settingRes) {
  169. if (settingRes.authSetting['scope.writePhotosAlbum']) {
  170. console.log('用户已在设置中开启访问相册的权限');
  171. // 可以在这里执行访问相册的操作
  172. _this.upload(); //上传壁纸
  173. } else {
  174. console.log('用户仍未授权访问相册');
  175. }
  176. }
  177. });
  178. }
  179. }
  180. });
  181. }
  182. });
  183. } else {
  184. // 用户已授权访问相册
  185. console.log('用户已授权访问相册2');
  186. // 可以在这里执行访问相册的操作
  187. }
  188. }
  189. });
  190. },
  191. async startImage() {
  192. console.log("开始发送壁纸数据: 0x78",)
  193. BtHelper.sendCallBack(BtCmd.wallPaper(1), function (res) {
  194. if (!res) {
  195. wx.hideLoading()
  196. wx.showToast({
  197. title: '发送失败',
  198. icon: 'none'
  199. })
  200. }
  201. });
  202. },
  203. sliceDataIntoChunks(data, chunkSize) {
  204. let buffer = data;
  205. console.log("发送壁纸数据:", buffer.byteLength, buffer.length)
  206. let total = buffer.byteLength || buffer.length
  207. const chunks = [];
  208. // for (let i = 0; i < data.length; i += chunkSize) {
  209. for (let i = 0; i < total; i += chunkSize) {
  210. const chunk = buffer.slice(i, i + chunkSize);
  211. chunks.push(chunk);
  212. }
  213. // const sliceSize = chunkSize / 2; // 每个 RGB565 占 2 字节
  214. // const chunks = [];
  215. // for (let i = 0; i < total; i += sliceSize) {
  216. // chunks.push(buffer.slice(i, i + sliceSize));
  217. // }
  218. this.data._chunks = chunks;
  219. },
  220. getImgMde5(buffer) {
  221. let md5ctx = js_md5.md5_init();
  222. js_md5.md5_update(md5ctx, buffer, buffer.byteLength ?? buffer.length);
  223. let result = js_md5.md5_final(md5ctx);
  224. let md5 = js_md5.md5_encode_hex(result, 16);
  225. console.log("result:", md5);
  226. return md5
  227. },
  228. sendImageMD5() {
  229. let lengthCode = this.data._chunks.length
  230. console.log("发送壁纸MD5 1:", lengthCode, this.data._imgMD5)
  231. let value = BtCmd.sendWiFiInfo("99", this.data._imgMD5)
  232. console.log("发送壁纸MD5 2:", value)
  233. BtHelper.sendCallBack(BtCmd.wallPaperMD5(value), function (res) {
  234. if (!res) {
  235. wx.hideLoading()
  236. wx.showToast({
  237. title: '发送失败',
  238. icon: 'none'
  239. })
  240. }
  241. });
  242. },
  243. async sendImage(index) {
  244. let _this = this
  245. wx.hideLoading()
  246. let chunks = _this.data._chunks
  247. let total = _this.data._imageBufferLength;
  248. let btHelper = BtHelper.getInstance();
  249. // let i = 0;
  250. // _this.data._timer = setInterval(async () => {
  251. if (index > chunks.length - 1) {
  252. _this.endImage(0)
  253. return;
  254. }
  255. const chunk = chunks[index];
  256. _this.data._imgNext += (chunk.byteLength ?? chunk.length);
  257. // console.log("发送壁纸数据1:", index, ":", _this.data._imgNext, ":", chunk.length, ":", chunk.byteLength, ":", total, chunks.length)
  258. let res = await btHelper.wallPaperSyncData(chunk);
  259. // let res = true;
  260. // btHelper.wallPaperData(chunk);
  261. if (!res) {
  262. wx.showModal({
  263. title: '壁纸上传失败',
  264. showCancel: false
  265. })
  266. _this.endImage(2)
  267. }
  268. _this.data._imgIndex += 1;
  269. _this.updateProgress(_this.data._imgNext, total);
  270. // }, 30);
  271. },
  272. async delay(ms) {
  273. return new Promise(resolve => setTimeout(resolve, ms));
  274. },
  275. endImage(value) {
  276. let _this = this
  277. // console.log("结束壁纸上传:", value)
  278. if (_this.data._timer) {
  279. clearInterval(_this.data._timer)
  280. _this.data._timer = null
  281. }
  282. _this.setData({
  283. progress: 0,
  284. showProgress: false
  285. })
  286. _this.data._chunks = []
  287. _this.data._imgNext = 0
  288. _this.data._imgMD5 = null
  289. _this.data._imgIndex = 0
  290. BtHelper.getInstance().wallPaper(value);
  291. },
  292. startProgress() {
  293. this.setData({
  294. progress: 0,
  295. showProgress: true
  296. })
  297. },
  298. updateProgress(chunk, total) {
  299. let progress = parseFloat((chunk / total * 100).toFixed(2));
  300. let _this = this
  301. if (chunk >= total) {
  302. _this.setData({
  303. progress: 100,
  304. showCropImg: false
  305. });
  306. } else {
  307. _this.setData({
  308. progress: progress,
  309. });
  310. }
  311. },
  312. failSend(showToast) {
  313. let _this = this
  314. _this.data._chunks = null
  315. _this.data._imgMD5 = null
  316. _this.data._imgIndex = 0
  317. _this.data._imgNext = 0
  318. wx.hideLoading()
  319. if (showToast) {
  320. wx.showModal({
  321. title: '壁纸上传失败了',
  322. showCancel: false
  323. })
  324. }
  325. _this.setData({
  326. progress: 0,
  327. showCropImg: false
  328. });
  329. },
  330. /**
  331. * 生命周期函数--监听页面加载
  332. */
  333. onLoad(options) {
  334. this.checkAndRequestImagePermission()
  335. this.cropper = this.selectComponent("#image-cropper");
  336. this.cropper.imgReset();
  337. // this.setData({
  338. // scr:json,
  339. // })
  340. this.upload(); //上传壁纸
  341. let _this = this;
  342. EventManager.addNotification(CmdEvent.eventName, function (event) {
  343. let name = event.cmdEvent;
  344. let value = event.wallpaper;
  345. let kind = event.heiJiaoKind;
  346. console.log("裁剪页:", name, value, kind)
  347. switch (name) {
  348. case EnumCmdEvent.wallpaper:
  349. //0x78
  350. // 小程序:0x78, 1。 开启壁纸
  351. // 黑胶回:0x78, 2, 1 ,1。 0x78, 2, 0, 2 。 1成功,2失败
  352. // 小程序:0x80, [参考wifi指令], [0x22,总长度,0x33,包长,包数,0x44,md5长,md5]
  353. // 黑胶回:0x80, 1, 1。 0x80, 0, 2。 1成功,2失败
  354. // 小程序:0x79, 数据长度,数据
  355. // 黑胶回:0x79, 1, 1 。0x79, 0, 2 。 1成功,2失败
  356. // 小程序:0x78, 0。结束了
  357. // 黑胶回:0x78, 2, 0, 1 。 0x78, 2, 0, 3 。 0流程成功,3流程失败
  358. // 小程序: 0x78, 2。异常结束
  359. if (value === 1 && kind == 1) {
  360. // 开始校验md5
  361. _this.sendImageMD5()
  362. // _this.sendImage()
  363. _this.startProgress()
  364. } else if (value === 0 && (kind == 2 || kind == 3)) {
  365. // 发送失败
  366. _this.failSend(true)
  367. } else if (value === 0 && kind == 1) {
  368. // 发送完成
  369. _this.failSend(false)
  370. wx.showModal({
  371. title: '上传壁纸成功',
  372. showCancel: false,
  373. success(res) {
  374. if (res.confirm) {
  375. const pages = getCurrentPages();
  376. // 获取上一级页面实例
  377. const prevPage = pages[pages.length - 2];
  378. // 传递参数
  379. prevPage.setData({
  380. topImg: {
  381. "pic": _this.data._imgUrl,
  382. }
  383. });
  384. wx.navigateBack({
  385. delta: 1,
  386. })
  387. }
  388. }
  389. })
  390. }
  391. break;
  392. case EnumCmdEvent.wallPaperMD5:
  393. // 0x80
  394. console.log("开始发送MD5回复", kind, value)
  395. // 收到回复md5,开始发送图片
  396. if (kind == 1 && value === 1) {
  397. _this.sendImage(0)
  398. } else {
  399. _this.failSend(true)
  400. }
  401. break;
  402. case EnumCmdEvent.wallPaperData:
  403. // 0x79
  404. // 收到回复md5,开始发送图片
  405. if (kind == 1 && value === 1) {
  406. _this.sendImage(_this.data._imgIndex)
  407. } else {
  408. _this.failSend(true)
  409. }
  410. break;
  411. default:
  412. break;
  413. }
  414. }, this)
  415. },
  416. /**
  417. * 生命周期函数--监听页面初次渲染完成
  418. */
  419. onReady() {
  420. },
  421. /**
  422. * 生命周期函数--监听页面显示
  423. */
  424. onShow() {
  425. },
  426. /**
  427. * 生命周期函数--监听页面隐藏
  428. */
  429. onHide() {
  430. },
  431. /**
  432. * 生命周期函数--监听页面卸载
  433. */
  434. onUnload() {
  435. EventManager.removeNotification(CmdEvent.eventName, this);
  436. },
  437. /**
  438. * 页面相关事件处理函数--监听用户下拉动作
  439. */
  440. onPullDownRefresh() {
  441. },
  442. /**
  443. * 页面上拉触底事件的处理函数
  444. */
  445. onReachBottom() {
  446. },
  447. /**
  448. * 用户点击右上角分享
  449. */
  450. onShareAppMessage() {
  451. }
  452. })