feat:测试页位置迁移,适配 tabbar
This commit is contained in:
@@ -79,6 +79,6 @@
|
||||
clickable
|
||||
data-name="shapePrint"
|
||||
is-link
|
||||
url="/pages/shapePrint/index" />
|
||||
url="/demoPages/shapePrint/index" />
|
||||
</van-cell-group>
|
||||
</view>
|
||||
|
||||
@@ -1,627 +0,0 @@
|
||||
// 引入形状和颜色数据
|
||||
import { shapes, colors } from './shapes';
|
||||
|
||||
Page({
|
||||
data: {
|
||||
// 可选择的形状列表
|
||||
availableShapes: shapes,
|
||||
// 可选择的颜色列表
|
||||
availableColors: colors,
|
||||
// 已选择的形状列表
|
||||
selectedShapes: [],
|
||||
// 当前选中的形状类型
|
||||
currentShapeType: 'circle',
|
||||
// 当前选中的颜色
|
||||
currentColor: '#FF4444',
|
||||
// 生成的图片
|
||||
generatedImage: null,
|
||||
// 是否正在生成
|
||||
isGenerating: false,
|
||||
// 背景选项
|
||||
backgrounds: [
|
||||
{ name: '纯白', value: '#FFFFFF' },
|
||||
{ name: '米黄', value: '#FAF5E8' },
|
||||
{ name: '淡灰', value: '#F5F5F5' },
|
||||
],
|
||||
bgColor: '#FFFFFF',
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
console.log('形状绘制页面加载完成');
|
||||
},
|
||||
|
||||
// 选择形状类型
|
||||
selectShape(e) {
|
||||
const shapeId = e.currentTarget.dataset.shapeId;
|
||||
this.setData({
|
||||
currentShapeType: shapeId,
|
||||
});
|
||||
},
|
||||
|
||||
// 选择颜色
|
||||
selectColor(e) {
|
||||
const color = e.currentTarget.dataset.color;
|
||||
this.setData({
|
||||
currentColor: color,
|
||||
});
|
||||
},
|
||||
|
||||
// 添加形状到选中列表
|
||||
addShape() {
|
||||
const { currentShapeType, currentColor, selectedShapes } = this.data;
|
||||
const shape = shapes.find((s) => s.id === currentShapeType);
|
||||
|
||||
if (shape) {
|
||||
const newShape = {
|
||||
id: Date.now(),
|
||||
type: shape.type,
|
||||
name: shape.name,
|
||||
color: currentColor,
|
||||
shapeId: currentShapeType,
|
||||
drawFunction: shape.drawFunction,
|
||||
};
|
||||
|
||||
this.setData({
|
||||
selectedShapes: [...selectedShapes, newShape],
|
||||
});
|
||||
|
||||
wx.showToast({
|
||||
title: `添加了${shape.name}`,
|
||||
icon: 'success',
|
||||
duration: 1000,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 删除选中的形状
|
||||
removeShape(e) {
|
||||
const index = e.currentTarget.dataset.index;
|
||||
const selectedShapes = [...this.data.selectedShapes];
|
||||
selectedShapes.splice(index, 1);
|
||||
this.setData({
|
||||
selectedShapes,
|
||||
});
|
||||
},
|
||||
|
||||
// 清空所有形状
|
||||
clearShapes() {
|
||||
this.setData({
|
||||
selectedShapes: [],
|
||||
});
|
||||
},
|
||||
|
||||
// 设置背景颜色
|
||||
setBackground(e) {
|
||||
this.setData({
|
||||
bgColor: e.detail.value,
|
||||
});
|
||||
},
|
||||
|
||||
// 创建形状的SVG预览
|
||||
createShapePreview(shape) {
|
||||
const svgContent = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="60" height="60">
|
||||
${shape.svg}
|
||||
</svg>
|
||||
`;
|
||||
|
||||
const base64 = wx.arrayBufferToBase64(
|
||||
new TextEncoder().encode(svgContent),
|
||||
);
|
||||
return `data:image/svg+xml;base64,${base64}`;
|
||||
},
|
||||
|
||||
// 绘制各种形状的函数
|
||||
drawCircle(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, size * 0.4, 0, Math.PI * 2);
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawSquare(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const squareSize = size * 0.8;
|
||||
const startX = x - squareSize / 2;
|
||||
const startY = y - squareSize / 2;
|
||||
if (filled) ctx.fillRect(startX, startY, squareSize, squareSize);
|
||||
ctx.strokeRect(startX, startY, squareSize, squareSize);
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawRectangle(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const rectWidth = size * 0.9;
|
||||
const rectHeight = size * 0.6;
|
||||
const startX = x - rectWidth / 2;
|
||||
const startY = y - rectHeight / 2;
|
||||
if (filled) ctx.fillRect(startX, startY, rectWidth, rectHeight);
|
||||
ctx.strokeRect(startX, startY, rectWidth, rectHeight);
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawTriangle(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const triangleSize = size * 0.8;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y - triangleSize / 2);
|
||||
ctx.lineTo(x - triangleSize / 2, y + triangleSize / 2);
|
||||
ctx.lineTo(x + triangleSize / 2, y + triangleSize / 2);
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawOval(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
ctx.beginPath();
|
||||
ctx.ellipse(x, y, size * 0.45, size * 0.3, 0, 0, Math.PI * 2);
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawDiamond(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const diamondSize = size * 0.4;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y - diamondSize);
|
||||
ctx.lineTo(x + diamondSize, y);
|
||||
ctx.lineTo(x, y + diamondSize);
|
||||
ctx.lineTo(x - diamondSize, y);
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawStar(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const outerRadius = size * 0.4;
|
||||
const innerRadius = size * 0.2;
|
||||
ctx.beginPath();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const angle = (i * Math.PI) / 5;
|
||||
const radius = i % 2 === 0 ? outerRadius : innerRadius;
|
||||
const pointX = x + Math.cos(angle - Math.PI / 2) * radius;
|
||||
const pointY = y + Math.sin(angle - Math.PI / 2) * radius;
|
||||
if (i === 0) ctx.moveTo(pointX, pointY);
|
||||
else ctx.lineTo(pointX, pointY);
|
||||
}
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawHeart(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const heartSize = size * 0.4;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x, y + heartSize * 0.3);
|
||||
ctx.bezierCurveTo(
|
||||
x - heartSize * 0.5,
|
||||
y - heartSize * 0.3,
|
||||
x - heartSize,
|
||||
y + heartSize * 0.1,
|
||||
x,
|
||||
y + heartSize * 0.8,
|
||||
);
|
||||
ctx.bezierCurveTo(
|
||||
x + heartSize,
|
||||
y + heartSize * 0.1,
|
||||
x + heartSize * 0.5,
|
||||
y - heartSize * 0.3,
|
||||
x,
|
||||
y + heartSize * 0.3,
|
||||
);
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawHexagon(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const radius = size * 0.4;
|
||||
ctx.beginPath();
|
||||
for (let i = 0; i < 6; i++) {
|
||||
const angle = (i * Math.PI) / 3;
|
||||
const pointX = x + Math.cos(angle) * radius;
|
||||
const pointY = y + Math.sin(angle) * radius;
|
||||
if (i === 0) ctx.moveTo(pointX, pointY);
|
||||
else ctx.lineTo(pointX, pointY);
|
||||
}
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawPentagon(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const radius = size * 0.4;
|
||||
ctx.beginPath();
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const angle = (i * 2 * Math.PI) / 5 - Math.PI / 2;
|
||||
const pointX = x + Math.cos(angle) * radius;
|
||||
const pointY = y + Math.sin(angle) * radius;
|
||||
if (i === 0) ctx.moveTo(pointX, pointY);
|
||||
else ctx.lineTo(pointX, pointY);
|
||||
}
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawSemicircle(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const radius = size * 0.4;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, Math.PI);
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
drawTrapezoid(ctx, x, y, size, color, filled = true) {
|
||||
ctx.save();
|
||||
if (filled) {
|
||||
ctx.fillStyle = color;
|
||||
}
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 3;
|
||||
const trapezoidSize = size * 0.4;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x - trapezoidSize * 0.6, y - trapezoidSize * 0.5);
|
||||
ctx.lineTo(x + trapezoidSize * 0.6, y - trapezoidSize * 0.5);
|
||||
ctx.lineTo(x + trapezoidSize, y + trapezoidSize * 0.5);
|
||||
ctx.lineTo(x - trapezoidSize, y + trapezoidSize * 0.5);
|
||||
ctx.closePath();
|
||||
if (filled) ctx.fill();
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
// 绘制形状的通用方法
|
||||
drawShape(ctx, shape, x, y, size, filled = true) {
|
||||
const color = filled ? shape.color : 'transparent';
|
||||
|
||||
switch (shape.drawFunction) {
|
||||
case 'drawCircle':
|
||||
this.drawCircle(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawSquare':
|
||||
this.drawSquare(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawRectangle':
|
||||
this.drawRectangle(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawTriangle':
|
||||
this.drawTriangle(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawOval':
|
||||
this.drawOval(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawDiamond':
|
||||
this.drawDiamond(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawStar':
|
||||
this.drawStar(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawHeart':
|
||||
this.drawHeart(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawHexagon':
|
||||
this.drawHexagon(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawPentagon':
|
||||
this.drawPentagon(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawSemicircle':
|
||||
this.drawSemicircle(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
case 'drawTrapezoid':
|
||||
this.drawTrapezoid(ctx, x, y, size, color, filled);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// 生成A4纸张大小的图片
|
||||
async generateImage() {
|
||||
if (this.data.selectedShapes.length === 0) {
|
||||
wx.showToast({
|
||||
title: '请先添加形状',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setData({ isGenerating: true });
|
||||
|
||||
try {
|
||||
const query = wx.createSelectorQuery().in(this);
|
||||
|
||||
query
|
||||
.select('#mainCanvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec((res) => {
|
||||
if (!res[0] || !res[0].node) {
|
||||
this.setData({ isGenerating: false });
|
||||
wx.showToast({
|
||||
title: 'Canvas 获取失败',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const canvas = res[0].node;
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
// A4纸张尺寸 (595x842 点,按照72DPI)
|
||||
const dpr = wx.getSystemInfoSync().pixelRatio;
|
||||
const a4Width = 595;
|
||||
const a4Height = 842;
|
||||
|
||||
canvas.width = a4Width * dpr;
|
||||
canvas.height = a4Height * dpr;
|
||||
ctx.scale(dpr, dpr);
|
||||
|
||||
// 清空画布并设置背景
|
||||
ctx.clearRect(0, 0, a4Width, a4Height);
|
||||
ctx.fillStyle = this.data.bgColor;
|
||||
ctx.fillRect(0, 0, a4Width, a4Height);
|
||||
|
||||
// 绘制标题
|
||||
this.drawTitle(ctx, a4Width);
|
||||
|
||||
// 绘制上半部分:带颜色的形状示例
|
||||
this.drawUpperSection(ctx, a4Width, a4Height);
|
||||
|
||||
// 绘制分割线
|
||||
this.drawDividerLine(ctx, a4Width, a4Height * 0.45);
|
||||
|
||||
// 绘制下半部分:无颜色的练习区域
|
||||
this.drawLowerSection(ctx, a4Width, a4Height);
|
||||
|
||||
// 导出图片
|
||||
wx.canvasToTempFilePath({
|
||||
canvas: canvas,
|
||||
success: (res) => {
|
||||
this.setData({
|
||||
generatedImage: res.tempFilePath,
|
||||
isGenerating: false,
|
||||
});
|
||||
wx.showToast({
|
||||
title: '图片生成成功',
|
||||
icon: 'success',
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('导出图片失败:', err);
|
||||
this.setData({ isGenerating: false });
|
||||
wx.showToast({
|
||||
title: '图片生成失败',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('生成图片出错:', error);
|
||||
this.setData({ isGenerating: false });
|
||||
wx.showToast({
|
||||
title: '生成出错,请重试',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 绘制标题
|
||||
drawTitle(ctx, canvasWidth) {
|
||||
ctx.save();
|
||||
ctx.fillStyle = '#333';
|
||||
ctx.font = 'bold 32px Arial';
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.fillText('形状涂色练习', canvasWidth / 2, 30);
|
||||
|
||||
ctx.font = '20px Arial';
|
||||
ctx.fillText('给相同的形状涂上相同的颜色', canvasWidth / 2, 75);
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
// 绘制上半部分:带颜色的形状示例
|
||||
drawUpperSection(ctx, canvasWidth, canvasHeight) {
|
||||
const { selectedShapes } = this.data;
|
||||
const startY = 120;
|
||||
const sectionHeight = canvasHeight * 0.32;
|
||||
const shapeSize = 60;
|
||||
const cols = Math.min(selectedShapes.length, 6);
|
||||
const rows = Math.ceil(selectedShapes.length / cols);
|
||||
|
||||
const cellWidth = (canvasWidth - 120) / cols;
|
||||
const cellHeight = sectionHeight / Math.max(rows, 1);
|
||||
|
||||
selectedShapes.forEach((shape, index) => {
|
||||
const row = Math.floor(index / cols);
|
||||
const col = index % cols;
|
||||
|
||||
const x = 60 + col * cellWidth + cellWidth / 2;
|
||||
const y = startY + row * cellHeight + cellHeight / 2;
|
||||
|
||||
this.drawShape(ctx, shape, x, y, shapeSize, true);
|
||||
});
|
||||
},
|
||||
|
||||
// 绘制分割线
|
||||
drawDividerLine(ctx, canvasWidth, y) {
|
||||
ctx.save();
|
||||
ctx.strokeStyle = '#333';
|
||||
ctx.lineWidth = 2;
|
||||
ctx.setLineDash([10, 5]);
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(60, y);
|
||||
ctx.lineTo(canvasWidth - 60, y);
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
},
|
||||
|
||||
// 绘制下半部分:无颜色的练习区域
|
||||
drawLowerSection(ctx, canvasWidth, canvasHeight) {
|
||||
const { selectedShapes } = this.data;
|
||||
const startY = canvasHeight * 0.5;
|
||||
const sectionHeight = canvasHeight * 0.45;
|
||||
const shapeSize = 50;
|
||||
|
||||
// 计算网格布局
|
||||
const cols = 8;
|
||||
const rows = 6;
|
||||
const cellWidth = (canvasWidth - 120) / cols;
|
||||
const cellHeight = sectionHeight / rows;
|
||||
|
||||
// 生成随机形状排列
|
||||
const practiceShapes = [];
|
||||
const totalShapes = cols * rows;
|
||||
|
||||
for (let i = 0; i < totalShapes; i++) {
|
||||
const randomShape = selectedShapes[i % selectedShapes.length];
|
||||
practiceShapes.push({
|
||||
...randomShape,
|
||||
color: 'transparent', // 练习区域不填充颜色
|
||||
});
|
||||
}
|
||||
|
||||
// 打乱顺序
|
||||
for (let i = practiceShapes.length - 1; i > 0; i--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[practiceShapes[i], practiceShapes[j]] = [
|
||||
practiceShapes[j],
|
||||
practiceShapes[i],
|
||||
];
|
||||
}
|
||||
|
||||
practiceShapes.forEach((shape, index) => {
|
||||
const row = Math.floor(index / cols);
|
||||
const col = index % cols;
|
||||
|
||||
const x = 60 + col * cellWidth + cellWidth / 2;
|
||||
const y = startY + row * cellHeight + cellHeight / 2;
|
||||
|
||||
this.drawShape(ctx, shape, x, y, shapeSize, false);
|
||||
});
|
||||
},
|
||||
|
||||
// 保存到相册
|
||||
saveToAlbum() {
|
||||
if (!this.data.generatedImage) {
|
||||
wx.showToast({
|
||||
title: '请先生成图片',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wx.saveImageToPhotosAlbum({
|
||||
filePath: this.data.generatedImage,
|
||||
success: () => {
|
||||
wx.showToast({
|
||||
title: '保存成功',
|
||||
icon: 'success',
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
if (err.errMsg.includes('auth deny')) {
|
||||
this.showAuthGuide();
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: '保存失败',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 显示授权引导
|
||||
showAuthGuide() {
|
||||
wx.showModal({
|
||||
title: '权限申请',
|
||||
content: '需要相册访问权限才能保存图片,请在设置中开启权限',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.openSetting();
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 预览生成的图片
|
||||
previewImage() {
|
||||
if (!this.data.generatedImage) return;
|
||||
|
||||
wx.previewImage({
|
||||
current: this.data.generatedImage,
|
||||
urls: [this.data.generatedImage],
|
||||
});
|
||||
},
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"navigationBarTitleText": "图形绘制 示例",
|
||||
"navigationBarBackgroundColor": "#d2e7d8",
|
||||
"homeButton": true,
|
||||
"backgroundColor": "#e8eddb",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
@@ -1,538 +0,0 @@
|
||||
.container {
|
||||
padding: 20rpx;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
padding: 30rpx;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 25rpx;
|
||||
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.15);
|
||||
|
||||
.title {
|
||||
font-size: 40rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
display: block;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.section {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 25rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 25rpx;
|
||||
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.15);
|
||||
backdrop-filter: blur(10rpx);
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
margin-bottom: 25rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 2rpx solid #f0f0f0;
|
||||
padding-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
background: linear-gradient(45deg, #ff6b6b, #ee5a24);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 15rpx 25rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: 24rpx;
|
||||
box-shadow: 0 4rpx 15rpx rgba(255, 107, 107, 0.4);
|
||||
}
|
||||
|
||||
/* 形状选择器 */
|
||||
.shape-selector {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(200rpx, 1fr));
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.shape-option {
|
||||
height: 140rpx;
|
||||
border: 3rpx solid #e0e0e0;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(145deg, #ffffff, #f0f0f0);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
&.active {
|
||||
border-color: #667eea;
|
||||
background: linear-gradient(145deg, #e3f2fd, #bbdefb);
|
||||
transform: translateY(-5rpx);
|
||||
box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.3);
|
||||
|
||||
.shape-name {
|
||||
color: #667eea;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shape-preview-box {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-bottom: 10rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.shape-icon {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
border: 2rpx solid #666;
|
||||
|
||||
&.shape-icon-circle {
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.shape-icon-square {
|
||||
border-radius: 5rpx;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.shape-icon-rectangle {
|
||||
width: 60rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 5rpx;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.shape-icon-triangle {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: none;
|
||||
border-left: 25rpx solid transparent;
|
||||
border-right: 25rpx solid transparent;
|
||||
border-bottom: 45rpx solid #666;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.shape-icon-oval {
|
||||
border-radius: 50%;
|
||||
width: 60rpx;
|
||||
height: 40rpx;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.shape-icon-diamond {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: none;
|
||||
border-left: 25rpx solid transparent;
|
||||
border-right: 25rpx solid transparent;
|
||||
border-top: 25rpx solid transparent;
|
||||
border-bottom: 25rpx solid #666;
|
||||
background: transparent;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&.shape-icon-star {
|
||||
position: relative;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: none;
|
||||
border-left: 25rpx solid transparent;
|
||||
border-right: 25rpx solid transparent;
|
||||
border-bottom: 18rpx solid #666;
|
||||
background: transparent;
|
||||
transform: rotate(35deg);
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -25rpx;
|
||||
top: -12rpx;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 25rpx solid transparent;
|
||||
border-right: 25rpx solid transparent;
|
||||
border-bottom: 18rpx solid #666;
|
||||
transform: rotate(-70deg);
|
||||
}
|
||||
}
|
||||
|
||||
&.shape-icon-heart {
|
||||
position: relative;
|
||||
width: 40rpx;
|
||||
height: 35rpx;
|
||||
border: none;
|
||||
background: #666;
|
||||
transform: rotate(-45deg);
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 20rpx;
|
||||
height: 30rpx;
|
||||
background: #666;
|
||||
border-radius: 20rpx 20rpx 0 0;
|
||||
transform: rotate(-45deg);
|
||||
transform-origin: 0 100%;
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 20rpx;
|
||||
}
|
||||
|
||||
&::after {
|
||||
top: -15rpx;
|
||||
transform: rotate(45deg);
|
||||
transform-origin: 100% 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.shape-icon-hexagon {
|
||||
width: 40rpx;
|
||||
height: 22rpx;
|
||||
background: #666;
|
||||
border: none;
|
||||
position: relative;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 20rpx solid transparent;
|
||||
border-right: 20rpx solid transparent;
|
||||
}
|
||||
|
||||
&::before {
|
||||
bottom: 100%;
|
||||
border-bottom: 11rpx solid #666;
|
||||
}
|
||||
|
||||
&::after {
|
||||
top: 100%;
|
||||
border-top: 11rpx solid #666;
|
||||
}
|
||||
}
|
||||
|
||||
&.shape-icon-pentagon {
|
||||
position: relative;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: none;
|
||||
border-left: 25rpx solid transparent;
|
||||
border-right: 25rpx solid transparent;
|
||||
border-bottom: 30rpx solid #666;
|
||||
background: transparent;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -18rpx;
|
||||
top: 30rpx;
|
||||
width: 36rpx;
|
||||
height: 15rpx;
|
||||
background: #666;
|
||||
}
|
||||
}
|
||||
|
||||
&.shape-icon-semicircle {
|
||||
width: 50rpx;
|
||||
height: 25rpx;
|
||||
border: 2rpx solid #666;
|
||||
border-bottom: none;
|
||||
border-radius: 50rpx 50rpx 0 0;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.shape-icon-trapezoid {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: none;
|
||||
border-left: 15rpx solid transparent;
|
||||
border-right: 15rpx solid transparent;
|
||||
border-bottom: 40rpx solid #666;
|
||||
background: transparent;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -25rpx;
|
||||
top: 40rpx;
|
||||
width: 50rpx;
|
||||
height: 2rpx;
|
||||
background: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shape-name {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 颜色选择器 */
|
||||
.color-selector {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120rpx, 1fr));
|
||||
gap: 20rpx;
|
||||
}
|
||||
|
||||
.color-option {
|
||||
height: 100rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 3rpx solid #e0e0e0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
&.active {
|
||||
border-color: #667eea;
|
||||
transform: scale(1.05);
|
||||
box-shadow: 0 0 0 6rpx rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.color-name {
|
||||
color: white;
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
text-shadow: 1rpx 1rpx 2rpx rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
/* 添加按钮 */
|
||||
.add-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 20rpx;
|
||||
background: linear-gradient(45deg, #667eea, #764ba2);
|
||||
border: none;
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 25rpx rgba(102, 126, 234, 0.4);
|
||||
|
||||
.add-icon {
|
||||
font-size: 40rpx;
|
||||
margin-right: 10rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
/* 已选择的形状 */
|
||||
.selected-shapes {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15rpx;
|
||||
}
|
||||
|
||||
.selected-shape {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
background: linear-gradient(145deg, #f8f9fa, #e9ecef);
|
||||
border-radius: 20rpx;
|
||||
border: 2rpx solid #e0e0e0;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4rpx 15rpx rgba(0, 0, 0, 0.1);
|
||||
|
||||
&:active {
|
||||
background: linear-gradient(145deg, #ffebee, #ffcdd2);
|
||||
border-color: #ff5722;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.shape-preview {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 20rpx;
|
||||
border: 2rpx solid #333;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.shape-details {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5rpx;
|
||||
}
|
||||
|
||||
.shape-info {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.color-info {
|
||||
font-size: 22rpx;
|
||||
color: #666;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.remove-hint {
|
||||
font-size: 20rpx;
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* 设置项 */
|
||||
.setting-item {
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.setting-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-bottom: 15rpx;
|
||||
display: block;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.bg-radio-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 25rpx;
|
||||
margin-top: 15rpx;
|
||||
}
|
||||
|
||||
.bg-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10rpx;
|
||||
padding: 10rpx 15rpx;
|
||||
border-radius: 15rpx;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-intro {
|
||||
margin-top: 30rpx;
|
||||
padding: 25rpx;
|
||||
background: linear-gradient(145deg, #f0f8ff, #e6f3ff);
|
||||
border-radius: 15rpx;
|
||||
border-left: 5rpx solid #667eea;
|
||||
}
|
||||
|
||||
.intro-title {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
margin-bottom: 15rpx;
|
||||
}
|
||||
|
||||
.intro-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
display: block;
|
||||
margin-bottom: 8rpx;
|
||||
padding-left: 15rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.generate-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 20rpx;
|
||||
margin-bottom: 20rpx;
|
||||
background: linear-gradient(45deg, #4CAF50, #45a049);
|
||||
border: none;
|
||||
color: white;
|
||||
box-shadow: 0 8rpx 25rpx rgba(76, 175, 80, 0.4);
|
||||
|
||||
&:disabled {
|
||||
background: #ccc;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.save-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
border-radius: 20rpx;
|
||||
background: linear-gradient(45deg, #ff9800, #f57c00);
|
||||
border: none;
|
||||
color: white;
|
||||
box-shadow: 0 8rpx 25rpx rgba(255, 152, 0, 0.4);
|
||||
}
|
||||
|
||||
/* 隐藏的画布 */
|
||||
.hidden-canvas {
|
||||
position: fixed;
|
||||
top: -9999rpx;
|
||||
left: -9999rpx;
|
||||
width: 595px;
|
||||
height: 842px;
|
||||
}
|
||||
|
||||
/* 预览图片 */
|
||||
.preview-image {
|
||||
width: 100%;
|
||||
max-height: 600rpx;
|
||||
border-radius: 20rpx;
|
||||
border: 3rpx solid #e0e0e0;
|
||||
background-color: white;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 8rpx 25rpx rgba(0, 0, 0, 0.15);
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.preview-hint {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-top: 20rpx;
|
||||
padding: 15rpx;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
border-radius: 15rpx;
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
<view class="container">
|
||||
<!-- 标题 -->
|
||||
<view class="header">
|
||||
<text class="title">形状涂色练习生成器</text>
|
||||
<text class="subtitle">为小朋友制作涂色练习页</text>
|
||||
</view>
|
||||
|
||||
<!-- 形状选择区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">选择形状</view>
|
||||
<view class="shape-selector">
|
||||
<view
|
||||
wx:for="{{availableShapes}}"
|
||||
wx:key="id"
|
||||
class="shape-option {{currentShapeType === item.id ? 'active' : ''}}"
|
||||
data-shape-id="{{item.id}}"
|
||||
bindtap="selectShape">
|
||||
<!-- 使用简单的CSS形状预览 -->
|
||||
<view class="shape-preview-box">
|
||||
<view class="shape-icon shape-icon-{{item.id}}"></view>
|
||||
</view>
|
||||
<text class="shape-name">{{item.name}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 颜色选择区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">选择颜色</view>
|
||||
<view class="color-selector">
|
||||
<view
|
||||
wx:for="{{availableColors}}"
|
||||
wx:key="value"
|
||||
class="color-option {{currentColor === item.value ? 'active' : ''}}"
|
||||
style="background-color: {{item.value}}"
|
||||
data-color="{{item.value}}"
|
||||
bindtap="selectColor">
|
||||
<view class="color-name">{{item.name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 添加按钮 -->
|
||||
<view class="section">
|
||||
<button class="add-btn" bindtap="addShape" type="primary">
|
||||
<text class="add-icon">+</text>
|
||||
添加 {{currentShapeType === 'circle' ? '圆形' : currentShapeType ===
|
||||
'square' ? '正方形' : currentShapeType === 'rectangle' ? '长方形' :
|
||||
currentShapeType === 'triangle' ? '三角形' : currentShapeType ===
|
||||
'oval' ? '椭圆形' : currentShapeType === 'diamond' ? '菱形' :
|
||||
currentShapeType === 'star' ? '星形' : currentShapeType === 'heart'
|
||||
? '心形' : currentShapeType === 'hexagon' ? '六边形' :
|
||||
currentShapeType === 'pentagon' ? '五边形' : currentShapeType ===
|
||||
'semicircle' ? '半圆形' : currentShapeType === 'trapezoid' ? '梯形'
|
||||
: '形状'}}
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 已选择的形状列表 -->
|
||||
<view class="section" wx:if="{{selectedShapes.length > 0}}">
|
||||
<view class="section-title">
|
||||
已选择的形状 ({{selectedShapes.length}})
|
||||
<button class="clear-btn" bindtap="clearShapes" size="mini">
|
||||
清空
|
||||
</button>
|
||||
</view>
|
||||
<view class="selected-shapes">
|
||||
<view
|
||||
wx:for="{{selectedShapes}}"
|
||||
wx:key="id"
|
||||
class="selected-shape"
|
||||
data-index="{{index}}"
|
||||
bindlongpress="removeShape">
|
||||
<view
|
||||
class="shape-preview"
|
||||
style="background-color: {{item.color}}"></view>
|
||||
<view class="shape-details">
|
||||
<text class="shape-info">{{item.name}}</text>
|
||||
<text class="color-info">{{item.color}}</text>
|
||||
</view>
|
||||
<text class="remove-hint">长按删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 设置区域 -->
|
||||
<view class="section">
|
||||
<view class="section-title">打印设置</view>
|
||||
|
||||
<view class="setting-item">
|
||||
<text class="setting-label">背景颜色:</text>
|
||||
<radio-group bindchange="setBackground" class="bg-radio-group">
|
||||
<label
|
||||
wx:for="{{backgrounds}}"
|
||||
wx:key="value"
|
||||
class="bg-option">
|
||||
<radio
|
||||
value="{{item.value}}"
|
||||
checked="{{bgColor === item.value}}"
|
||||
color="#1976d2" />
|
||||
<text>{{item.name}}</text>
|
||||
</label>
|
||||
</radio-group>
|
||||
</view>
|
||||
|
||||
<view class="feature-intro">
|
||||
<text class="intro-title">功能说明:</text>
|
||||
<text class="intro-text">• 上半部分:带颜色的形状示例</text>
|
||||
<text class="intro-text">• 下半部分:无颜色的练习区域</text>
|
||||
<text class="intro-text">• 图片大小:A4 纸张,适合打印</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="section">
|
||||
<button
|
||||
class="generate-btn"
|
||||
bindtap="generateImage"
|
||||
type="primary"
|
||||
loading="{{isGenerating}}"
|
||||
disabled="{{selectedShapes.length === 0}}">
|
||||
{{isGenerating ? '生成中...' : '生成练习页'}}
|
||||
</button>
|
||||
|
||||
<button
|
||||
wx:if="{{generatedImage}}"
|
||||
class="save-btn"
|
||||
bindtap="saveToAlbum"
|
||||
type="warn">
|
||||
保存到相册
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- Canvas 画布 (隐藏) -->
|
||||
<canvas type="2d" id="mainCanvas" class="hidden-canvas"> </canvas>
|
||||
|
||||
<!-- 预览生成的图片 -->
|
||||
<view class="section" wx:if="{{generatedImage}}">
|
||||
<view class="section-title">生成的练习页</view>
|
||||
<image
|
||||
src="{{generatedImage}}"
|
||||
class="preview-image"
|
||||
mode="aspectFit"
|
||||
bindtap="previewImage" />
|
||||
<text class="preview-hint">点击图片可放大预览 • A4尺寸 • 适合打印</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -1,105 +0,0 @@
|
||||
// shapes.js - 幼儿园到小学三年级基本几何形状定义
|
||||
const shapes = [
|
||||
{
|
||||
id: 'circle',
|
||||
name: '圆形',
|
||||
type: 'circle',
|
||||
svg: '<circle cx="50" cy="50" r="40" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawCircle',
|
||||
},
|
||||
{
|
||||
id: 'square',
|
||||
name: '正方形',
|
||||
type: 'rect',
|
||||
svg: '<rect x="10" y="10" width="80" height="80" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawSquare',
|
||||
},
|
||||
{
|
||||
id: 'rectangle',
|
||||
name: '长方形',
|
||||
type: 'rect',
|
||||
svg: '<rect x="5" y="25" width="90" height="50" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawRectangle',
|
||||
},
|
||||
{
|
||||
id: 'triangle',
|
||||
name: '三角形',
|
||||
type: 'triangle',
|
||||
svg: '<polygon points="50,10 20,80 80,80" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawTriangle',
|
||||
},
|
||||
{
|
||||
id: 'oval',
|
||||
name: '椭圆形',
|
||||
type: 'oval',
|
||||
svg: '<ellipse cx="50" cy="50" rx="40" ry="25" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawOval',
|
||||
},
|
||||
{
|
||||
id: 'diamond',
|
||||
name: '菱形',
|
||||
type: 'diamond',
|
||||
svg: '<polygon points="50,10 80,50 50,90 20,50" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawDiamond',
|
||||
},
|
||||
{
|
||||
id: 'star',
|
||||
name: '星形',
|
||||
type: 'star',
|
||||
svg: '<polygon points="50,5 60,35 90,35 70,55 80,85 50,70 20,85 30,55 10,35 40,35" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawStar',
|
||||
},
|
||||
{
|
||||
id: 'heart',
|
||||
name: '心形',
|
||||
type: 'heart',
|
||||
svg: '<path d="M50,85 C30,65 10,45 10,25 C10,15 20,5 30,5 C40,5 50,15 50,25 C50,15 60,5 70,5 C80,5 90,15 90,25 C90,45 70,65 50,85 Z" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawHeart',
|
||||
},
|
||||
{
|
||||
id: 'hexagon',
|
||||
name: '六边形',
|
||||
type: 'hexagon',
|
||||
svg: '<polygon points="25,15 75,15 90,50 75,85 25,85 10,50" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawHexagon',
|
||||
},
|
||||
{
|
||||
id: 'pentagon',
|
||||
name: '五边形',
|
||||
type: 'pentagon',
|
||||
svg: '<polygon points="50,10 80,35 65,75 35,75 20,35" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawPentagon',
|
||||
},
|
||||
{
|
||||
id: 'semicircle',
|
||||
name: '半圆形',
|
||||
type: 'semicircle',
|
||||
svg: '<path d="M 15 50 A 35 35 0 0 1 85 50 Z" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawSemicircle',
|
||||
},
|
||||
{
|
||||
id: 'trapezoid',
|
||||
name: '梯形',
|
||||
type: 'trapezoid',
|
||||
svg: '<polygon points="30,20 70,20 85,80 15,80" stroke="#333" stroke-width="2" fill="none"/>',
|
||||
drawFunction: 'drawTrapezoid',
|
||||
},
|
||||
];
|
||||
|
||||
// 颜色选项
|
||||
const colors = [
|
||||
{ name: '红色', value: '#FF4444' },
|
||||
{ name: '蓝色', value: '#4A90E2' },
|
||||
{ name: '绿色', value: '#7ED321' },
|
||||
{ name: '黄色', value: '#F5A623' },
|
||||
{ name: '紫色', value: '#9013FE' },
|
||||
{ name: '橙色', value: '#FF8F00' },
|
||||
{ name: '粉色', value: '#E91E63' },
|
||||
{ name: '青色', value: '#00BCD4' },
|
||||
{ name: '深绿', value: '#4CAF50' },
|
||||
{ name: '深蓝', value: '#2196F3' },
|
||||
{ name: '棕色', value: '#8D6E63' },
|
||||
{ name: '灰色', value: '#9E9E9E' },
|
||||
];
|
||||
|
||||
export { shapes, colors };
|
||||
Reference in New Issue
Block a user