DelPhotoPage.ets 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { CropController, CropView, IBestToast, YTAvoid, YTLog, yTRouter, YTUserRequest } from 'basic'
  2. import { fileIo } from '@kit.CoreFileKit'
  3. import { util } from '@kit.ArkTS'
  4. import { emitter } from '@kit.BasicServicesKit'
  5. @Builder
  6. function delPhotoPageBuilder() {
  7. NavDestination() {
  8. DelPhotoPage()
  9. }
  10. .hideTitleBar(true)
  11. }
  12. @Component
  13. struct DelPhotoPage {
  14. @StorageProp(YTAvoid.SAFE_BOTTOM_KEY) private safeBottom: number = 0
  15. @State private selectPhoto: string = ''
  16. @State private frameWidth: number = 220
  17. @State private frameHeight: number = 220
  18. @State private startWidth: number = 220
  19. @State private startHeight: number = 220
  20. private declare type: 'bill' | 'header' | 'image'
  21. private controller: CropController = new CropController()
  22. private declare context: Context
  23. aboutToAppear(): void {
  24. this.selectPhoto = yTRouter.getDelPhotoParam().src
  25. this.type = yTRouter.getDelPhotoParam().type
  26. const tempContext = this.getUIContext().getHostContext()
  27. if (tempContext === undefined) {
  28. //抛出异常
  29. throw new Error('DelPhotoPage context is null')
  30. } else {
  31. this.context = tempContext
  32. }
  33. YTAvoid.setStatusBarContentColor('#FFFFFFFF', this.context)
  34. }
  35. aboutToDisappear(): void {
  36. YTAvoid.setStatusBarContentColor('#FF000000', this.context)
  37. }
  38. build() {
  39. Column() {
  40. Stack({ alignContent: Alignment.Center }) {
  41. CropView({
  42. src: this.selectPhoto,
  43. controller: this.controller, // 控制器必须设置
  44. maskColor: '#4D000000',
  45. frameWidth: this.frameWidth,
  46. frameHeight: this.frameHeight
  47. })
  48. .width("100%")
  49. .layoutWeight(1)
  50. .backgroundColor(Color.Black)
  51. Column() {
  52. Row() {
  53. Text()
  54. .height(30)
  55. .aspectRatio(1)
  56. .border({ width: { left: 8, top: 8 }, color: Color.White })
  57. .offset({ x: -8, y: -8 })
  58. .borderRadius({ topLeft: 5 })
  59. .gesture(
  60. PanGesture({ distance: 1 })
  61. .onActionStart(() => {
  62. // 记录拖拽开始时的初始尺寸
  63. this.startWidth = this.frameWidth
  64. this.startHeight = this.frameHeight
  65. })
  66. .onActionUpdate(event => {
  67. // 基于初始尺寸计算新尺寸
  68. const newWidth = Math.max(220, this.startWidth - event.offsetX)
  69. const newHeight = Math.max(220, this.startHeight - event.offsetY)
  70. // 同时更新两个维度
  71. this.frameWidth = newWidth
  72. this.frameHeight = newHeight
  73. })
  74. )
  75. Text()
  76. .height(30)
  77. .aspectRatio(1)
  78. .border({ width: { right: 8, top: 8 }, color: Color.White })
  79. .offset({ x: 8, y: -8 })
  80. .borderRadius({ topRight: 5 })
  81. .gesture(
  82. PanGesture({ distance: 1 })
  83. .onActionStart(() => {
  84. // 记录拖拽开始时的初始尺寸
  85. this.startWidth = this.frameWidth
  86. this.startHeight = this.frameHeight
  87. })
  88. .onActionUpdate(event => {
  89. // 基于初始尺寸计算新尺寸
  90. const newWidth = Math.max(220, this.startWidth + event.offsetX)
  91. const newHeight = Math.max(220, this.startHeight - event.offsetY)
  92. // 同时更新两个维度
  93. this.frameWidth = newWidth
  94. this.frameHeight = newHeight
  95. })
  96. )
  97. }
  98. .width('100%')
  99. .height(25)
  100. .justifyContent(FlexAlign.SpaceBetween)
  101. .borderRadius(8)
  102. Row() {
  103. Text()
  104. .height(30)
  105. .aspectRatio(1)
  106. .border({ width: { left: 8, bottom: 8 }, color: Color.White })
  107. .offset({ x: -8, y: 8 })
  108. .borderRadius({ bottomLeft: 5 })
  109. .gesture(
  110. PanGesture({ distance: 1 })
  111. .onActionStart(() => {
  112. // 记录拖拽开始时的初始尺寸
  113. this.startWidth = this.frameWidth
  114. this.startHeight = this.frameHeight
  115. })
  116. .onActionUpdate(event => {
  117. // 基于初始尺寸计算新尺寸
  118. const newWidth = Math.max(220, this.startWidth - event.offsetX)
  119. const newHeight = Math.max(220, this.startHeight + event.offsetY)
  120. // 同时更新两个维度
  121. this.frameWidth = newWidth
  122. this.frameHeight = newHeight
  123. })
  124. )
  125. Text()
  126. .height(30)
  127. .aspectRatio(1)
  128. .border({ width: { right: 8, bottom: 8 }, color: Color.White })
  129. .borderRadius({ bottomRight: 5 })
  130. .offset({ x: 8, y: 8 })
  131. .gesture(
  132. PanGesture({ distance: 1 })
  133. .onActionStart(() => {
  134. // 记录拖拽开始时的初始尺寸
  135. this.startWidth = this.frameWidth
  136. this.startHeight = this.frameHeight
  137. })
  138. .onActionUpdate(event => {
  139. // 基于初始尺寸计算新尺寸
  140. const newWidth = Math.max(220, this.startWidth + event.offsetX)
  141. const newHeight = Math.max(220, this.startHeight + event.offsetY)
  142. // 同时更新两个维度
  143. this.frameWidth = newWidth
  144. this.frameHeight = newHeight
  145. })
  146. )
  147. }
  148. .width('100%')
  149. .height(25)
  150. .justifyContent(FlexAlign.SpaceBetween)
  151. }
  152. .width(this.frameWidth)
  153. .height(this.frameHeight)
  154. .justifyContent(FlexAlign.SpaceBetween)
  155. .hitTestBehavior(HitTestMode.Transparent)
  156. }
  157. .layoutWeight(1)
  158. Row() {
  159. Image($r('app.media.back'))
  160. .width(36)
  161. .aspectRatio(1)
  162. .onClick(() => {
  163. yTRouter.routerBack()
  164. })
  165. Image($r('app.media.make_sure'))
  166. .height(56)
  167. .aspectRatio(1)
  168. .onClick(() => {
  169. //使用 controller 获取裁剪图片
  170. this.controller.cropWithPath({ format: 'image/jpeg', quality: 100 })
  171. .then(async (path) => {
  172. // path 为裁剪后的文件路径
  173. try {
  174. const photoName = util.generateRandomUUID()
  175. const photoType = '.jpeg'
  176. const fullpath = this.context.cacheDir + '/' + photoName + photoType
  177. const photo = fileIo.openSync(path)
  178. await fileIo.copyFile(photo.fd, fullpath)
  179. if (this.type == 'header') {
  180. IBestToast.showLoading({ message: '上传中...' })
  181. YTUserRequest.uploadHeadImg(this.getUIContext().getHostContext()!, fullpath, () => {
  182. YTUserRequest.refreshUserInfo(() => {
  183. IBestToast.hide()
  184. setTimeout(() => {
  185. IBestToast.show({ message: '头像修改成功', type: 'success' })
  186. }, 100)
  187. })
  188. })
  189. yTRouter.routerBack()
  190. }
  191. if (this.type == 'image') {
  192. IBestToast.showLoading({ message: '上传中...' })
  193. YTUserRequest.uploadFile(this.getUIContext().getHostContext()!, fullpath, (url) => {
  194. emitter.emit('upLoadEnd', { data: url })
  195. IBestToast.hide()
  196. yTRouter.routerBack()
  197. })
  198. }
  199. } catch (e) {
  200. YTLog.error(e)
  201. }
  202. })
  203. })
  204. Image($r('app.media.rotate'))
  205. .height(36)
  206. .aspectRatio(1)
  207. .onClick(() => {
  208. this.controller.rotate()
  209. })
  210. }
  211. .width('100%')
  212. .height(84)
  213. .justifyContent(FlexAlign.SpaceAround)
  214. }
  215. .padding({ bottom: this.safeBottom })
  216. }
  217. }