HarmonyOS ArkTS的声明式开发 自定义色盘
·

1.拆出背景颜色色盘提高性能
import { common2D, drawing } from '@kit.ArkGraphics2D';
//背景颜色色盘
export class DrawModifierBack extends DrawModifier {
uiContext: UIContext;
constructor(uiContext: UIContext) {
super();
this.uiContext = uiContext;
}
drawBehind(drawContext: DrawContext): void {
const canvas = drawContext.canvas;
const width = drawContext.size.width; // 逻辑宽度(vp)
const height = drawContext.size.height;
const centerX = this.uiContext.vp2px(width / 2); // 转换为像素坐标
const centerY = this.uiContext.vp2px(height / 2);
const radius = Math.min(centerX, centerY);
let centerPt: common2D.Point = { x: centerX, y: centerY };
// 绘制 HSV 色相环
const brush = new drawing.Brush();
const dstShader = drawing.ShaderEffect.createSweepGradient(
centerPt,
this.generateHsvColors(),
drawing.TileMode.REPEAT,
0,
360,
);
brush.setShaderEffect(dstShader)
canvas.attachBrush(brush)
canvas.drawCircle(centerX, centerY,radius)
const srcShader = drawing.ShaderEffect.createRadialGradient(
centerPt,
radius,
[0xFFFFFFFF,0x00FFFFFF],
drawing.TileMode.CLAMP,
);
brush.setShaderEffect(srcShader)
canvas.attachBrush(brush)
canvas.drawCircle(centerX, centerY,radius)
}
private generateHsvColors(): number[] {
return Array.from<number, number>({length: 36}, (_, i) => {
const h = i * 10;
const rgb = this.hsvToRgb(h,100, 100);
return 0xFF << 24 | rgb[0] << 16 | rgb[1] << 8 | rgb[2];
}).reverse();
}
// HSV 转 RGB 辅助函数
hsvToRgb(h: number, s: number, v: number): [number, number, number] {
s /= 100;
v /= 100;
const i = Math.floor(h / 60);
const f = h / 60 - i;
const p = v * (1 - s);
const q = v * (1 - s * f);
const t = v * (1 - s * (1 - f));
switch (i % 6) {
case 0: return [v * 255, t * 255, p * 255];
case 1: return [q * 255, v * 255, p * 255];
case 2: return [p * 255, v * 255, t * 255];
case 3: return [p * 255, q * 255, v * 255];
case 4: return [t * 255, p * 255, v * 255];
default: return [v * 255, p * 255, q * 255];
}
}
hsvToStr(h: number, s: number, v: number): string {
const rgb = this.hsvToRgb(h, s, v);
const r = rgb[0];
const g = rgb[1];
const b = rgb[2];
// 将 0-255 数值转为两位十六进制字符串
const toHex = (n: number): string => {
const hex = Math.round(n).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase();
}
}
2、取色圆的画布绘制
import { DrawModifierBack } from '../widget/DrawModifierBack';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct Index {
private fullModifier: DrawModifierBack = new DrawModifierBack(this.getUIContext());
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
private isDrawing: boolean = false
private lastX: number = 0
private lastY: number = 0
// 声明状态变量存储宽高
private canvasSize: number = 0
private colorRadius: number = 20
build() {
RelativeContainer() {
RelativeContainer() {
Canvas(this.context)
.width('100%')
.aspectRatio(1)
.backgroundColor(Color.Transparent)
.onAreaChange((oldArea, newArea) => {
this.canvasSize = Number(newArea.width)
this.upDateCircle(this.canvasSize/2, this.canvasSize/2, 0)
})
.onTouch((event: TouchEvent) => {
const touch = event.touches
const x = touch[0].x
const y = touch[0].y
switch (event.type) {
case TouchType.Down:
let size = this.pointToCircle(x,y,this.canvasSize)
if(size > this.canvasSize / 2) {
break
}
this.lastX = x
this.lastY = y
this.upDateCircle(this.lastX,this.lastY,Math.min(size/(this.canvasSize/2-this.colorRadius),1))
this.isDrawing = true
break
case TouchType.Move:
if (this.isDrawing) {
let size = this.pointToCircle(x,y,this.canvasSize)
let pos = this.findPoint(x, y, size, this.canvasSize,this.colorRadius)
this.lastX = pos[0]
this.lastY = pos[1]
this.upDateCircle(this.lastX,this.lastY,Math.min(size/(this.canvasSize/2-this.colorRadius),1))
}
break
case TouchType.Up:
this.isDrawing = false
break
}
})
}
.width('auto')
.height('auto')
.drawModifier(this.fullModifier)
}
.height('100%')
.width('100%')
}
private upDateCircle(x: number, y: number, v:number) {
// 清空画布
let h = this.angle(x,y, this.canvasSize)
let color = this.fullModifier.hsvToStr(h,v*100,100)
hilog.error(0x0000, 'testTag',`颜色回调自行处理${color}`)
this.context.clearRect(0, 0, this.canvasSize, this.canvasSize);
// 绘制新圆环
this.context.beginPath();
this.context.arc(x, y, this.colorRadius, 0, 2 * Math.PI);
this.context.fillStyle = color
this.context.strokeStyle = '#FFFFFF';
this.context.lineWidth = 3;
this.context.fill()
this.context.stroke();
}
private pointToCircle(x: number, y: number, size: number): number {
if (size <= 0) {
return 0;
}
const center = size / 2;
const dx = x - center;
const dy = y - center;
return Math.sqrt(dx * dx + dy * dy);
}
private findPoint(
x1: number,
y1: number,
circle: number,
size: number,
colorRadius: number,
colorStroke: number = 0
): [number, number] {
const r = size / 2 - (colorRadius + colorStroke);
if (circle > (size / 2 - colorRadius)) {
// 待开发逻辑
} else {
return [x1, y1];
}
const a = y1 - size / 2;
const b = x1 - size / 2;
let yColor = Math.sqrt((r * r) / ((b / a) * (b / a) + 1));
if (a < 0) {
yColor = -yColor;
}
const xColor = (b * yColor) / a + size / 2;
yColor += size / 2;
return [xColor, yColor];
}
private readonly RAD_TO_DEG: number = 180 / Math.PI;
// 计算角度
private angle(x: number, y: number, size: number): number {
const dx = x - size / 2;
const dy = y - size / 2;
let deg = Math.atan2(-dy, dx) * this.RAD_TO_DEG;
if (deg < 0) {
deg += 360;
}
return Math.min(Math.max(deg, 0), 360);
}
}
更多推荐

所有评论(0)