forked from floraachy/ImageKnife
278 lines
11 KiB
Plaintext
278 lines
11 KiB
Plaintext
/*
|
|
* Copyright (C) 2021 Huawei Device Co., Ltd.
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
import {
|
|
GrayscaleTransformation,
|
|
ImageKnifeComponent,
|
|
ImageKnifeData,
|
|
ImageKnifeOption,
|
|
RotateImageTransformation,
|
|
SketchFilterTransformation,
|
|
ScaleTypeHelper,
|
|
IDrawLifeCycle,
|
|
ScaleType,
|
|
ImageKnifeGlobal,
|
|
BaseTransform
|
|
} from '@ohos/libraryimageknife'
|
|
import ArkWorker from '@ohos.worker'
|
|
import worker from '@ohos.worker';
|
|
import image from '@ohos.multimedia.image';
|
|
|
|
@Entry
|
|
@Component
|
|
struct TestImageKnifeOptionChangedPage4 {
|
|
|
|
@State imageKnifeOption1: ImageKnifeOption =
|
|
{
|
|
loadSrc: $r('app.media.jpgSample'),
|
|
|
|
placeholderSrc: $r('app.media.icon_loading'),
|
|
errorholderSrc: $r('app.media.icon_failed'),
|
|
|
|
thumbSizeMultiplier: 0.1,
|
|
drawLifeCycle: this.createViewLifeCycle()
|
|
};
|
|
private mTimerId: number = 0
|
|
|
|
build() {
|
|
Scroll() {
|
|
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
|
Flex({ direction: FlexDirection.Row }) {
|
|
Button("网络jpg")
|
|
.onClick(() => {
|
|
let rotateTrans: BaseTransform<image.PixelMap> = new RotateImageTransformation(180)
|
|
this.imageKnifeOption1 = {
|
|
loadSrc: "https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
|
|
|
|
placeholderSrc: $r('app.media.icon_loading'),
|
|
errorholderSrc: $r('app.media.icon_failed'),
|
|
|
|
thumbSizeMultiplier: 0.1,
|
|
transformation: rotateTrans,
|
|
drawLifeCycle: this.createViewLifeCycle()
|
|
};
|
|
}).margin({ left: 5 }).backgroundColor(Color.Blue)
|
|
Button("网络png")
|
|
.onClick(() => {
|
|
this.imageKnifeOption1 = {
|
|
loadSrc: "https://img-blog.csdnimg.cn/20191215043500229.png",
|
|
|
|
placeholderSrc: $r('app.media.icon_loading'),
|
|
errorholderSrc: $r('app.media.icon_failed'),
|
|
|
|
thumbSizeMultiplier: 0.1,
|
|
transformations: [new RotateImageTransformation(180)],
|
|
drawLifeCycle: this.createViewLifeCycle()
|
|
};
|
|
}).margin({ left: 5 }).backgroundColor(Color.Blue)
|
|
}.margin({ top: 15 })
|
|
|
|
Flex({ direction: FlexDirection.Row }) {
|
|
Button("网络bmp")
|
|
.onClick(() => {
|
|
this.imageKnifeOption1 = {
|
|
loadSrc: "https://img-blog.csdn.net/20140514114029140",
|
|
|
|
placeholderSrc: $r('app.media.icon_loading'),
|
|
errorholderSrc: $r('app.media.icon_failed'),
|
|
|
|
thumbSizeMultiplier: 0.1,
|
|
transformations: [new GrayscaleTransformation()],
|
|
drawLifeCycle: this.createViewLifeCycle()
|
|
};
|
|
}).margin({ left: 5 }).backgroundColor(Color.Blue)
|
|
Button("网络webp")
|
|
.onClick(() => {
|
|
this.imageKnifeOption1 = {
|
|
loadSrc: "https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp",
|
|
|
|
placeholderSrc: $r('app.media.icon_loading'),
|
|
errorholderSrc: $r('app.media.icon_failed'),
|
|
|
|
thumbSizeMultiplier: 0.1,
|
|
transformations: [new SketchFilterTransformation()],
|
|
drawLifeCycle: this.createViewLifeCycle()
|
|
};
|
|
}).margin({ left: 5 }).backgroundColor(Color.Blue)
|
|
}.margin({ top: 15 })
|
|
|
|
Text("下面为展示图片区域").margin({ top: 5 })
|
|
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
|
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
|
}.width(400).height(400).margin({ top: 10 }).backgroundColor(Color.Pink)
|
|
|
|
}
|
|
}
|
|
.width('100%')
|
|
.height('100%')
|
|
}
|
|
|
|
aboutToAppear() {
|
|
|
|
}
|
|
|
|
aboutToDisappear() {
|
|
|
|
}
|
|
|
|
drawMainAnimate_index: number = 0;
|
|
drawMainAnimate_context?: CanvasRenderingContext2D = undefined;
|
|
drawMainAnimate_scaleType: ScaleType = ScaleType.FIT_CENTER;
|
|
drawMainAnimate_imagePixelMap?: PixelMap = undefined;
|
|
drawMainAnimate_widthPixel: number = 0;
|
|
drawMainAnimate_heightPixel: number = 0;
|
|
drawMainAnimate_compWidth: number = 0;
|
|
drawMainAnimate_compHeight: number = 0;
|
|
drawMainAnimate = () => {
|
|
console.log('drawMainAnimate index = ' + this.drawMainAnimate_index)
|
|
|
|
let clipScale = (this.drawMainAnimate_index / 30.0)
|
|
this.drawMainAnimate_context?.save()
|
|
this.drawMainAnimate_context?.beginPath();
|
|
let path2d = new Path2D()
|
|
let maxRadius = Math.sqrt(this.drawMainAnimate_compWidth / 2 * this.drawMainAnimate_compWidth / 2 + this.drawMainAnimate_compHeight / 2 * this.drawMainAnimate_compHeight / 2)
|
|
path2d.arc(this.drawMainAnimate_compWidth / 2, this.drawMainAnimate_compHeight / 2, maxRadius * clipScale, 0, Math.PI * 2)
|
|
this.drawMainAnimate_context?.clip(path2d)
|
|
this.drawMainAnimate_context?.save()
|
|
ScaleTypeHelper.drawImageWithScaleType(this.drawMainAnimate_context!, this.drawMainAnimate_scaleType, this.drawMainAnimate_imagePixelMap, px2vp(this.drawMainAnimate_widthPixel), px2vp(this.drawMainAnimate_heightPixel), this.drawMainAnimate_compWidth, this.drawMainAnimate_compHeight, 0, 0)
|
|
this.drawMainAnimate_context?.restore();
|
|
this.drawMainAnimate_context?.restore();
|
|
if (this.drawMainAnimate_index < 30) {
|
|
this.drawMainAnimate_index++
|
|
let nextFunc = this.drawMainAnimate
|
|
|
|
this.mTimerId = setTimeout(nextFunc, 1000 / 30.0)
|
|
} else {
|
|
// 不做处理
|
|
}
|
|
}
|
|
|
|
private stopAnimate() {
|
|
if (this.mTimerId > 0) {
|
|
clearTimeout(this.mTimerId)
|
|
this.mTimerId = 0
|
|
} else {
|
|
|
|
}
|
|
}
|
|
|
|
private createViewLifeCycle(): IDrawLifeCycle {
|
|
let viewLifeCycle: IDrawLifeCycle = {
|
|
// 展示占位图
|
|
displayPlaceholder: (context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) => {
|
|
|
|
this.stopAnimate()
|
|
return false;
|
|
},
|
|
// 展示加载进度
|
|
displayProgress: (context: CanvasRenderingContext2D, progress: number, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) => {
|
|
|
|
this.stopAnimate()
|
|
context.save();
|
|
context.clearRect(0, 0, compWidth, compHeight)
|
|
let pi = Math.PI * 2 / 100; //pi 讲圆的周长划分为100份
|
|
let rate = progress - 25;
|
|
let diameter = compWidth > compHeight ? compHeight : compWidth
|
|
context.lineWidth = Math.floor(diameter * 0.03)
|
|
context.lineCap = "round"
|
|
context.fillStyle = "white"
|
|
context.font = Math.floor(diameter * 0.5) + 'px'
|
|
let x0 = (compWidth - diameter) / 2.0 + Math.floor(diameter * 0.5)
|
|
let y0 = (compHeight - diameter) / 2.0 + Math.floor(diameter * 0.1)
|
|
let x1 = (compWidth - diameter) / 2.0 + Math.floor(diameter * 0.5)
|
|
let y1 = (compHeight - diameter) / 2.0 + Math.floor(diameter * 0.8)
|
|
let gradient = context.createLinearGradient(x0, y0, x1, y1)
|
|
gradient.addColorStop(0, "#11ffe4")
|
|
gradient.addColorStop(0.5, "#03c6fd")
|
|
gradient.addColorStop(1, "#10a5ff")
|
|
context.clearRect(0, 0, compWidth, compHeight)
|
|
context.shadowBlur = 0
|
|
context.beginPath()
|
|
context.strokeStyle = "#15222d"
|
|
let radius = Math.floor(diameter * 0.3)
|
|
let arcX = compWidth / 2.0
|
|
let arcY = compHeight / 2.0
|
|
context.arc(arcX, arcY, radius, 0, Math.PI * 2, true)
|
|
context.stroke()
|
|
context.beginPath()
|
|
let showText = rate + 25 + '%'
|
|
let metrics = context.measureText(showText)
|
|
let textX = (compWidth / 2.0) - metrics.width / 2.0
|
|
let textY = (compHeight / 2.0) + metrics.height * 0.3
|
|
context.fillText(showText, textX, textY)
|
|
context.stroke()
|
|
context.beginPath()
|
|
context.strokeStyle = gradient
|
|
context.arc(arcX, arcY, radius, pi * -25, pi * rate)
|
|
context.stroke();
|
|
context.restore();
|
|
return true;
|
|
},
|
|
// 展示缩略图
|
|
displayThumbSizeMultiplier: (context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) => {
|
|
|
|
this.stopAnimate()
|
|
return false;
|
|
},
|
|
|
|
// 展示主图
|
|
displayMainSource: (context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) => {
|
|
this.stopAnimate()
|
|
if (data.isPixelMap()) {
|
|
|
|
data.drawPixelMap?.imagePixelMap?.getImageInfo().then((imageInfo) => {
|
|
let scaleType = (typeof imageKnifeOption.mainScaleType == 'number') ? imageKnifeOption.mainScaleType : ScaleType.FIT_CENTER
|
|
console.log('imageinfo width =' + imageInfo.size.width + ' height=' + imageInfo.size.height + 'scaleType=' + scaleType)
|
|
|
|
|
|
this.drawMainAnimate_index = 0;
|
|
this.drawMainAnimate_context = context;
|
|
this.drawMainAnimate_scaleType = scaleType
|
|
this.drawMainAnimate_imagePixelMap = data.drawPixelMap?.imagePixelMap
|
|
this.drawMainAnimate_widthPixel = imageInfo.size.width
|
|
this.drawMainAnimate_heightPixel = imageInfo.size.height
|
|
this.drawMainAnimate_compWidth = compWidth
|
|
this.drawMainAnimate_compHeight = compHeight
|
|
|
|
let func = this.drawMainAnimate
|
|
|
|
this.mTimerId = setTimeout(func, 1000 / 30.0)
|
|
|
|
console.log('TestImageKnifeOptionChangedPage4 drawMainSource end!')
|
|
})
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
// 展示重试图层
|
|
displayRetryholder: (context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) => {
|
|
|
|
this.stopAnimate()
|
|
return false;
|
|
},
|
|
|
|
// 展示失败占位图
|
|
displayErrorholder: (context: CanvasRenderingContext2D, data: ImageKnifeData, imageKnifeOption: ImageKnifeOption, compWidth: number, compHeight: number, setGifTimeId?: (timeId: number) => void) => {
|
|
|
|
this.stopAnimate()
|
|
return false;
|
|
}
|
|
}
|
|
return viewLifeCycle;
|
|
}
|
|
}
|
|
|
|
|