中国优质的IT技术网站
专业IT技术创作平台
IT职业在线教育平台
拍照, 相册选择图片进行裁剪
微信扫码分享
import image from '@ohos.multimedia.image'; import { resourceManager } from '@kit.LocalizationKit'; import { RectPosition, ActionType, Position, InitPosition } from '../model/Bean' @Entry @Component struct Index { @Provide pixelMap: image.PixelMap | undefined = undefined; @Provide pixelMapBackUp: image.PixelMap | undefined = undefined; @Provide imageInfo: image.ImageInfo | undefined = undefined; private settings: RenderingContextSettings = new RenderingContextSettings(true); private canvasContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private settings2: RenderingContextSettings = new RenderingContextSettings(true); private canvasContext2: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings2); private settings3: RenderingContextSettings = new RenderingContextSettings(true); private canvasContext3: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings3); private actionType: ActionType = ActionType.move; private rotateOn: boolean = false @State imageArea: RectPosition = { x: 0, y: 0, width: 0, height: 0 }; private touchPosition: Position = { x: 0, y: 0, }; private initPosition: InitPosition = { x: 0, y: 0, width: 0, height: 0, } @State isCrop: boolean = false @State cropImageInfo: image.ImageInfo | undefined = undefined; @State pixelMapChange: boolean = false @State @Watch('drawMask') clipRect: RectPosition = { x: 0, y: 0, height: 0, width: 0 }; build() { Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { if (this.isCrop) { if (this.pixelMapChange) { Image(this.pixelMap) .width(px2vp(this.cropImageInfo?.size.width)) .height(px2vp(this.cropImageInfo?.size.height)) .margin({ top: '10%' }) } else { Image(this.pixelMap) .width(px2vp(this.cropImageInfo?.size.width)) .height(px2vp(this.cropImageInfo?.size.height)) .margin({ top: '10%' }) } } else { Canvas(this.canvasContext) .width(px2vp(this.imageInfo?.size.width)) .height(px2vp(this.imageInfo?.size.height)) .onReady(() => { this.drawImage() }) .onAreaChange((value: Area, newVal: Area) => { // 获取图片位置xy this.initPosition.x = Math.round(newVal.position.x as number) this.initPosition.y = Math.round(newVal.position.y as number) }) // 蒙层 Canvas(this.canvasContext3) .position({ x: this.initPosition.x, y: this.initPosition.y }) .width(px2vp(this.imageInfo?.size.width)) .height(px2vp(this.imageInfo?.size.height)) // 裁剪框 Canvas(this.canvasContext2) .position({ x: this.clipRect.x, y: this.clipRect.y }) .width(this.clipRect.width) .height(this.clipRect.height) .onReady(() => { this.drawClipImage() }) .onTouch(event => { if (event.type === TouchType.Down) { this.isMove(event.target.area, event.touches[0]); this.touchPosition = { x: event.touches[0].screenX, y: event.touches[0].screenY } } else if (event.type === TouchType.Move) { let moveX = event.changedTouches[0].screenX - this.touchPosition.x; let moveY = event.changedTouches[0].screenY - this.touchPosition.y; this.touchPosition = { x: event.changedTouches[0].screenX, y: event.changedTouches[0].screenY } this.moveClipCanvas(moveX, moveY); } }) } Row() { Image($rawfile('rotate.png')) .width(40) .height(40) .onClick(() => { this.rotateImage() }) } .margin({ top: 50 }) .height('7%') .width('100%') .padding(30) Row() { Image($rawfile('reset.png')) .width(40) .height(40) .onClick(() => { this.cancel() }) Image($rawfile('crop.png')) .width(40) .height(40) .onClick(() => { this.clipImage() }) } .margin({ top: 10 }) .width('100%') .height('7%') .padding(30) .justifyContent(FlexAlign.SpaceBetween) } .width('100%') .height('100%') .backgroundColor('#000000') } // 旋转图片 async rotateImage() { if (this.rotateOn) { await this.pixelMap?.rotate(90) const info = await this.pixelMap?.getImageInfo() this.cropImageInfo = info if (this.pixelMapChange) { this.pixelMapChange = false } else { this.pixelMapChange = true } } } // 取消剪切 cancel() { this.pixelMap = this.pixelMapBackUp this.isCrop = false this.rotateOn = false } // 判断操作类型 isMove(area: Area, touch: TouchObject) { if (touch.x < 60 && touch.y < 60) { // 左上角 this.actionType = ActionType.topLeft } else if (touch.x < 60 && touch.y > (Number(area.height) - 60)) { // 左下 this.actionType = ActionType.bottomLeft } else if (touch.x > Number(area.width) - 60 && touch.y < 60) { // 右上 this.actionType = ActionType.topRight } else if (touch.x > Number(area.width) - 60 && touch.y > (Number(area.height) - 60)) { // 右下 this.actionType = ActionType.bottomRight } else { this.actionType = ActionType.move } } // 绘制背景图 async drawImage() { await this.initData('test.jpg') if (this.imageInfo != undefined) { this.canvasContext.drawImage(this.pixelMap, 0, 0, px2vp(this.imageInfo.size.width), px2vp(this.imageInfo.size.height)); this.canvasContext.save(); } } // 绘制蒙层 drawMask() { this.canvasContext3.clearRect(0, 0, this.imageInfo?.size.width, this.imageInfo?.size.height); this.canvasContext3.fillStyle = 'rgba(0,0,0,0.7)'; this.canvasContext3.fillRect(0, 0, px2vp(this.imageInfo?.size.width), px2vp(this.imageInfo?.size.height)); this.canvasContext3.clearRect(this.clipRect.x - this.initPosition.x, this.clipRect.y - this.initPosition.y, this.clipRect.width, this.clipRect.height); } // 绘制裁剪框 drawClipImage() { this.canvasContext2.clearRect(0, 0, this.clipRect.width, this.clipRect.height); this.canvasContext2.lineWidth = 6 this.canvasContext2.strokeStyle = '#ffffff' this.canvasContext2.beginPath() this.canvasContext2.moveTo(0, 20) this.canvasContext2.lineTo(0, 0); this.canvasContext2.lineTo(20, 0); this.canvasContext2.moveTo(this.clipRect.width - 20, 0); this.canvasContext2.lineTo(this.clipRect.width, 0); this.canvasContext2.lineTo(this.clipRect.width, 20); this.canvasContext2.moveTo(0, this.clipRect.height - 20); this.canvasContext2.lineTo(0, this.clipRect.height); this.canvasContext2.lineTo(20, this.clipRect.height); this.canvasContext2.moveTo(this.clipRect.width - 20, this.clipRect.height); this.canvasContext2.lineTo(this.clipRect.width, this.clipRect.height); this.canvasContext2.lineTo(this.clipRect.width, this.clipRect.height - 20); this.canvasContext2.stroke() this.canvasContext2.beginPath(); this.canvasContext2.lineWidth = 0.5; let height = Math.round(this.clipRect.height / 3); for (let index = 0; index <= 3; index++) { let y = index === 3 ? this.clipRect.height : height * index; this.canvasContext2.moveTo(0, y); this.canvasContext2.lineTo(this.clipRect.width, y); } let width = Math.round(this.clipRect.width / 3); for (let index = 0; index <= 3; index++) { let x = index === 3 ? this.clipRect.width : width * index; this.canvasContext2.moveTo(x, 0); this.canvasContext2.lineTo(x, this.clipRect.height); } this.canvasContext2.stroke(); } // 获取pixelMap与imageInfo async initData(fileName: string) { const context: Context = getContext(this); const resourceMgr: resourceManager.ResourceManager = context.resourceManager; const fileData = await resourceMgr.getRawFileContent(fileName); const buffer = fileData.buffer; const imageSource: image.ImageSource = image.createImageSource(buffer); const pixelMap: image.PixelMap = await imageSource.createPixelMap() this.pixelMap = pixelMap this.pixelMapBackUp = pixelMap const imageInfo = await pixelMap.getImageInfo() this.imageInfo = imageInfo // 裁剪框初始位置 this.initPosition.width = px2vp(Math.round(this.imageInfo.size.width)) this.initPosition.height = px2vp(Math.round(this.imageInfo.size.height)) this.clipRect.height = px2vp(this.imageInfo.size.height) this.clipRect.width = px2vp(this.imageInfo.size.width) this.clipRect.x = this.initPosition.x this.clipRect.y = this.initPosition.y } // 裁剪图片 async clipImage() { let x = this.clipRect.x - this.initPosition.x; let y = this.clipRect.y - this.initPosition.y; console.log('x= ' + x + ' y = ' + y + 'height = ' + this.clipRect.height + 'width = ' + this.clipRect.width) await this.pixelMap?.crop({ x: vp2px(x), y: vp2px(y), size: { height: vp2px(this.clipRect.height), width: vp2px(this.clipRect.width) } }) this.cropImageInfo = await this.pixelMap?.getImageInfo(); this.isCrop = true this.rotateOn = true } // 裁剪框位置和大小变化 初始位置为图片的初始坐标 移动的坐标 moveClipCanvas(moveX: number, moveY: number) { let clipRect: RectPosition = { x: this.clipRect.x, y: this.clipRect.y, width: this.clipRect.width, height: this.clipRect.height } switch (this.actionType) { case ActionType.move: clipRect.x += moveX; clipRect.y += moveY; break; case ActionType.topLeft: clipRect.x += moveX; clipRect.y += moveY; clipRect.width += -moveX; clipRect.height += -moveY; break; case ActionType.topRight: clipRect.y += moveY; clipRect.width += moveX; clipRect.height += -moveY; break; case ActionType.bottomLeft: clipRect.x += moveX; clipRect.width += -moveX; clipRect.height += moveY; break; case ActionType.bottomRight: clipRect.width += moveX; clipRect.height += moveY; break; default: break; } // 偏移坐标小于初始位置 if (clipRect.x < this.initPosition.x) { clipRect.x = this.initPosition.x; } if (clipRect.y < this.initPosition.y) { clipRect.y = this.initPosition.y; } // 横坐标限制位置 if (clipRect.width + clipRect.x > this.initPosition.width + this.initPosition.x) { if (this.actionType === ActionType.move) { clipRect.x = this.initPosition.width + this.initPosition.x - clipRect.width; } else { clipRect.width = this.initPosition.width + this.initPosition.x - clipRect.x; } } // 纵坐标限制 if (clipRect.height + clipRect.y > this.initPosition.height + this.initPosition.y) { if (this.actionType === ActionType.move) { clipRect.y = this.initPosition.height + this.initPosition.y - clipRect.height; } else { clipRect.height = this.initPosition.height + this.initPosition.y - clipRect.y; } } this.clipRect = { x: Math.round(clipRect.x), y: Math.round(clipRect.y), width: Math.round(clipRect.width), height: Math.round(clipRect.height) }; } }