cropper.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  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 route_util from '../../../utils/route_util';
  6. const { BtHelper } = require('../../../devices/bt_helper');
  7. Page({
  8. /**
  9. * 页面的初始数据
  10. */
  11. data: {
  12. src: "",
  13. width: 300,//宽度
  14. height: 300,//高度
  15. max_width: 300,
  16. max_height: 300,
  17. disable_rotate: true, //是否禁用旋转
  18. disable_ratio: true, //锁定比例
  19. limit_move: true, //是否限制移动
  20. showProgress: false,
  21. _imageBuffer: null,
  22. progress: 0,
  23. },
  24. cropper: null,
  25. // 将 RGBA 数据转换为 RGB565 格式
  26. RGBAtoRGB565(data) {
  27. const rgb565Array = new Uint16Array(data.length / 4);
  28. for (let i = 0; i < data.length; i += 4) {
  29. const r = data[i];
  30. const g = data[i + 1];
  31. const b = data[i + 2];
  32. // 转换为 RGB565
  33. const rgb565 = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
  34. rgb565Array[i / 4] = rgb565;
  35. }
  36. return rgb565Array;
  37. },
  38. // 保存为 .bin 文件
  39. saveAsBinFile(data, width, height) {
  40. const arrayBuffer = data.buffer;
  41. wx.getFileSystemManager().writeFile({
  42. filePath: `${wx.env.USER_DATA_PATH}/image_rgb565_${width}x${height}.bin`,
  43. data: arrayBuffer,
  44. encoding: 'binary',
  45. success: () => {
  46. wx.showToast({
  47. title: '保存成功',
  48. icon: 'success',
  49. });
  50. },
  51. fail: (err) => {
  52. console.error('文件保存失败:', err);
  53. },
  54. });
  55. },
  56. cropperload(e) {
  57. console.log('cropper加载完成');
  58. },
  59. upload() {
  60. let that = this;
  61. wx.chooseImage({
  62. count: 1,
  63. sizeType: ['original', 'compressed'],
  64. sourceType: ['album'],
  65. success(res) {
  66. wx.showLoading({
  67. title: '加载中',
  68. })
  69. const tempFilePaths = res.tempFilePaths[0];
  70. //重置图片角度、缩放、位置
  71. that.cropper.imgReset();
  72. that.setData({
  73. src: tempFilePaths
  74. });
  75. }
  76. })
  77. },
  78. loadimage(e) {
  79. wx.hideLoading();
  80. console.log('图片', e);
  81. this.cropper.imgReset();
  82. },
  83. clickcut(e) {
  84. console.log("clickcut:", e.detail);
  85. //图片预览
  86. wx.previewImage({
  87. current: e.detail.url, // 当前显示图片的http链接
  88. urls: [e.detail.url] // 需要预览的图片http链接列表
  89. })
  90. },
  91. cancel() {
  92. wx.navigateBack({
  93. delta: -1
  94. })
  95. },
  96. submit() {
  97. let _this = this
  98. wx.showLoading({
  99. title: '图片裁剪中',
  100. })
  101. this.cropper.getImg((obj) => {
  102. // app.globalData.imgSrc = obj.url;
  103. console.log("裁剪图片:", obj);
  104. _this.readLocalFileAndConvertToBase64(obj.url);
  105. // _this.readBinFile("../../pagesA/images/th01.bin");
  106. });
  107. },
  108. submitTest() {
  109. route_util.jump("../../pagesA/index/index")
  110. },
  111. // 读取本地文件并转换为 Base64 字符串
  112. readLocalFileAndConvertToBase64(filePath) {
  113. const fs = wx.getFileSystemManager();
  114. let _this = this;
  115. fs.readFile({
  116. filePath: filePath,
  117. encoding: 'base64',
  118. success: (res) => {
  119. // const base64Data = 'data:image/png;base64,' + res.data;
  120. // let rgbData = _this.RGBAtoRGB565(res.data)
  121. let rgbData = res.data
  122. console.log("转换rgb:", rgbData.length)
  123. _this.data._imageBuffer = rgbData;
  124. wx.hideLoading();
  125. wx.showLoading({
  126. title: '开始传输图片',
  127. })
  128. _this.startImage();
  129. },
  130. fail: (err) => {
  131. console.error('读取文件失败:', err);
  132. }
  133. });
  134. },
  135. readBinFile(filePath) {
  136. const fs = wx.getFileSystemManager();
  137. fs.readFile({
  138. filePath: filePath,
  139. encoding: '', // 不指定编码以获取原始二进制数据
  140. success: (res) => {
  141. console.log("读取 .bin 文件成功:", res.data);
  142. // 处理读取到的二进制数据
  143. this.processBinData(res.data);
  144. },
  145. fail: (err) => {
  146. console.error('读取 .bin 文件失败:', err);
  147. },
  148. });
  149. },
  150. checkAndRequestImagePermission: function () {
  151. const self = this;
  152. // 检查用户是否已经授权访问相册
  153. wx.getSetting({
  154. success(res) {
  155. if (!res.authSetting['scope.writePhotosAlbum']) {
  156. // 用户未授权访问相册,请求用户授权
  157. wx.authorize({
  158. scope: 'scope.writePhotosAlbum',
  159. success() {
  160. // 用户同意授权
  161. console.log('用户已授权访问相册');
  162. // 可以在这里执行访问相册的操作
  163. },
  164. fail() {
  165. // 用户拒绝授权
  166. console.log('用户拒绝授权访问相册');
  167. wx.showModal({
  168. title: '提示',
  169. content: '您拒绝了访问相册的权限,请在设置中手动开启',
  170. showCancel: false,
  171. success(res) {
  172. if (res.confirm) {
  173. // 跳转到设置页面
  174. wx.openSetting({
  175. success(settingRes) {
  176. if (settingRes.authSetting['scope.writePhotosAlbum']) {
  177. console.log('用户已在设置中开启访问相册的权限');
  178. // 可以在这里执行访问相册的操作
  179. } else {
  180. console.log('用户仍未授权访问相册');
  181. }
  182. }
  183. });
  184. }
  185. }
  186. });
  187. }
  188. });
  189. } else {
  190. // 用户已授权访问相册
  191. console.log('用户已授权访问相册');
  192. // 可以在这里执行访问相册的操作
  193. }
  194. }
  195. });
  196. // 检查用户是否已经授权使用相机
  197. wx.getSetting({
  198. success(res) {
  199. if (!res.authSetting['scope.camera']) {
  200. // 用户未授权使用相机,请求用户授权
  201. wx.authorize({
  202. scope: 'scope.camera',
  203. success() {
  204. // 用户同意授权
  205. console.log('用户已授权使用相机');
  206. // 可以在这里执行使用相机的操作
  207. },
  208. fail() {
  209. // 用户拒绝授权
  210. console.log('用户拒绝授权使用相机');
  211. wx.showModal({
  212. title: '提示',
  213. content: '您拒绝了使用相机的权限,请在设置中手动开启',
  214. showCancel: false,
  215. success(res) {
  216. if (res.confirm) {
  217. // 跳转到设置页面
  218. wx.openSetting({
  219. success(settingRes) {
  220. if (settingRes.authSetting['scope.camera']) {
  221. console.log('用户已在设置中开启使用相机的权限');
  222. // 可以在这里执行使用相机的操作
  223. } else {
  224. console.log('用户仍未授权使用相机');
  225. }
  226. }
  227. });
  228. }
  229. }
  230. });
  231. }
  232. });
  233. } else {
  234. // 用户已授权使用相机
  235. console.log('用户已授权使用相机');
  236. // 可以在这里执行使用相机的操作
  237. }
  238. }
  239. });
  240. },
  241. startImage() {
  242. BtHelper.getInstance().send(BtCmd.wallPaper(1));
  243. },
  244. sliceDataIntoChunks(data, chunkSize) {
  245. const chunks = [];
  246. for (let i = 0; i < data.length; i += chunkSize) {
  247. const chunk = data.slice(i, i + chunkSize);
  248. chunks.push(chunk);
  249. }
  250. return chunks;
  251. },
  252. startSendImage(imageBuffer) {
  253. if (imageBuffer == null) {
  254. wx.showToast({
  255. title: '图片裁剪失败',
  256. icon: 'none'
  257. })
  258. _this.endImage(2)
  259. return;
  260. }
  261. // _this.sendImage(imageBuffer, 0)
  262. // }
  263. },
  264. async sendImage(imageBuffer, index) {
  265. let _this = this
  266. // if (index >= chunkSize) {
  267. // wx.showModal({
  268. // title: '图片上传成功1',
  269. // showCancel: false
  270. // })
  271. // _this.endImage(0)
  272. // return;
  273. // }
  274. let chunks = this.sliceDataIntoChunks(imageBuffer, 20);
  275. let next = 0;
  276. let total = imageBuffer.length;
  277. for (let i = 0; i < chunks.length; i++) {
  278. const chunk = chunks[i];
  279. next += chunk.length;
  280. console.log("发送图片数据:", i, next, chunk)
  281. let res = await BtHelper.getInstance().wallPaperSyncData(chunk);
  282. let nowDate = Date.now()
  283. if (i === chunks.length - 1 && res) {
  284. wx.showModal({
  285. title: '图片上传成功' + i + " / " + nowDate,
  286. showCancel: false
  287. })
  288. _this.endImage(0)
  289. } else if (!res) {
  290. wx.showModal({
  291. title: '图片上传失败了',
  292. showCancel: false
  293. })
  294. _this.endImage(2)
  295. break;
  296. }
  297. _this.updateProgress(next, total);
  298. }
  299. },
  300. endImage(value) {
  301. BtHelper.getInstance().wallPaper(value);
  302. },
  303. startProgress() {
  304. this.setData({
  305. progress: 0,
  306. showProgress: true
  307. })
  308. },
  309. updateProgress(chunk, total) {
  310. let progress = chunk / total;
  311. let _this = this
  312. if (chunk >= total) {
  313. _this.setData({
  314. progress: 0,
  315. showProgress: false,
  316. // showCropImg: false
  317. });
  318. wx.showToast({
  319. title: '图片上传成功',
  320. })
  321. _this.endImage(0)
  322. } else {
  323. _this.setData({
  324. progress: progress,
  325. });
  326. }
  327. },
  328. /**
  329. * 生命周期函数--监听页面加载
  330. */
  331. onLoad(options) {
  332. console.log(options.param)
  333. // let json = JSON.parse(options.param)
  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. console.log("裁剪页:", EnumCmdEvent)
  345. switch (name) {
  346. case EnumCmdEvent.wallpaper:
  347. let otaCmd = event.wallpaper;
  348. let kind = event.heiJiaoKind;
  349. console.log("裁剪页:", otaCmd, kind)
  350. if (otaCmd === 1 && kind == 1) {
  351. // 开始发送
  352. _this.sendImage(_this.data._imageBuffer, 0)
  353. _this.startProgress()
  354. } else if (otaCmd === 0 && kind == 1) {
  355. // 发送结束
  356. // _this.endImage(0)
  357. } else if (kind == 0) {
  358. wx.hideLoading()
  359. wx.showModal({
  360. title: '图片上传失败了',
  361. showCancel: false
  362. })
  363. }
  364. break;
  365. default:
  366. break;
  367. }
  368. }, this)
  369. },
  370. /**
  371. * 生命周期函数--监听页面初次渲染完成
  372. */
  373. onReady() {
  374. },
  375. /**
  376. * 生命周期函数--监听页面显示
  377. */
  378. onShow() {
  379. },
  380. /**
  381. * 生命周期函数--监听页面隐藏
  382. */
  383. onHide() {
  384. },
  385. /**
  386. * 生命周期函数--监听页面卸载
  387. */
  388. onUnload() {
  389. EventManager.removeNotification(CmdEvent.eventName, this);
  390. },
  391. /**
  392. * 页面相关事件处理函数--监听用户下拉动作
  393. */
  394. onPullDownRefresh() {
  395. },
  396. /**
  397. * 页面上拉触底事件的处理函数
  398. */
  399. onReachBottom() {
  400. },
  401. /**
  402. * 用户点击右上角分享
  403. */
  404. onShareAppMessage() {
  405. }
  406. })