Files
doodle-mini/miniprogram/focusPages/shared/shapes/shapeSymbolShapes.ts
T
2025-12-17 10:43:56 +08:00

156 lines
4.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 图形符号配对专用的图形定义
* 所有图形保持大小一致
*/
export interface ShapeSymbolShape {
id: string;
name: string;
}
export const SHAPE_SYMBOL_SHAPES: ShapeSymbolShape[] = [
{ id: 'circle', name: '圆形' },
{ id: 'square', name: '正方形' },
{ id: 'triangle', name: '三角形' },
{ id: 'diamond', name: '菱形' },
{ id: 'trapezoid', name: '梯形' },
{ id: 'ellipse', name: '椭圆' },
{ id: 'star', name: '五角星' },
{ id: 'pentagon', name: '五边形' },
{ id: 'heart', name: '心形' },
];
/**
* 绘制图形(无边框,仅填充)
* 所有图形保持相同的大小
*/
export function drawShapeSymbolShape(
ctx: RenderingContext,
shapeId: string,
x: number,
y: number,
size: number,
fillColor: string,
): void {
ctx.save();
ctx.translate(x, y);
const radius = size / 2;
ctx.fillStyle = fillColor;
switch (shapeId) {
case 'circle':
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2);
ctx.fill();
break;
case 'square':
ctx.fillRect(-radius, -radius, size, size);
break;
case 'triangle':
ctx.beginPath();
ctx.moveTo(0, -radius);
ctx.lineTo(-radius, radius);
ctx.lineTo(radius, radius);
ctx.closePath();
ctx.fill();
break;
case 'diamond':
ctx.beginPath();
ctx.moveTo(0, -radius);
ctx.lineTo(radius, 0);
ctx.lineTo(0, radius);
ctx.lineTo(-radius, 0);
ctx.closePath();
ctx.fill();
break;
case 'trapezoid':
ctx.beginPath();
const topWidth = radius * 0.6;
ctx.moveTo(-topWidth, -radius * 0.7);
ctx.lineTo(topWidth, -radius * 0.7);
ctx.lineTo(radius, radius * 0.7);
ctx.lineTo(-radius, radius * 0.7);
ctx.closePath();
ctx.fill();
break;
case 'ellipse':
ctx.beginPath();
ctx.ellipse(0, 0, radius * 0.8, radius * 0.6, 0, 0, Math.PI * 2);
ctx.fill();
break;
case 'star':
// 五角星
ctx.beginPath();
for (let i = 0; i < 5; i++) {
const angle1 = (i * 2 * Math.PI) / 5 - Math.PI / 2;
const angle2 = ((i + 0.5) * 2 * Math.PI) / 5 - Math.PI / 2;
const r1 = radius;
const r2 = radius * 0.4;
const x1 = Math.cos(angle1) * r1;
const y1 = Math.sin(angle1) * r1;
const x2 = Math.cos(angle2) * r2;
const y2 = Math.sin(angle2) * r2;
if (i === 0) {
ctx.moveTo(x1, y1);
} else {
ctx.lineTo(x1, y1);
}
ctx.lineTo(x2, y2);
}
ctx.closePath();
ctx.fill();
break;
case 'pentagon':
ctx.beginPath();
for (let i = 0; i < 5; i++) {
const angle = (i * 2 * Math.PI) / 5 - Math.PI / 2;
const px = Math.cos(angle) * radius;
const py = Math.sin(angle) * radius;
if (i === 0) ctx.moveTo(px, py);
else ctx.lineTo(px, py);
}
ctx.closePath();
ctx.fill();
break;
case 'heart':
// 爱心路径(参考 shapes.ts 中的 SVG 路径)
// SVG路径:M50,35 C35,20 20,35 25,50 C30,65 50,80 50,80 C50,80 70,65 75,50 C80,35 65,20 50,35Z
// SVG中心为(50,50),高度约为60(从y=20到y=80
// 使用scale=60使心形高度约为size,与其他图形保持一致
const scale = 60;
function tx(px: number) {
return ((px - 50) / scale) * size;
}
function ty(py: number) {
return ((py - 50) / scale) * size;
}
ctx.beginPath();
ctx.moveTo(tx(50), ty(35));
ctx.bezierCurveTo(tx(35), ty(20), tx(20), ty(35), tx(25), ty(50));
ctx.bezierCurveTo(tx(30), ty(65), tx(50), ty(80), tx(50), ty(80));
ctx.bezierCurveTo(tx(50), ty(80), tx(70), ty(65), tx(75), ty(50));
ctx.bezierCurveTo(tx(80), ty(35), tx(65), ty(20), tx(50), ty(35));
ctx.closePath();
ctx.fill();
break;
default:
// 默认绘制圆形
ctx.beginPath();
ctx.arc(0, 0, radius, 0, Math.PI * 2);
ctx.fill();
}
ctx.restore();
}