diff --git a/miniprogram/components/shape-card-v1/shape-card copy.less b/miniprogram/components/shape-card-v1/shape-card copy.less
deleted file mode 100644
index 9f139cd..0000000
--- a/miniprogram/components/shape-card-v1/shape-card copy.less
+++ /dev/null
@@ -1,57 +0,0 @@
-.shape-card {
- position: relative;
- width: 300rpx;
- height: 300rpx;
- border-radius: 16rpx;
- // background: #f5f5f5;
- background: #ffffff;
- border: 1rpx solid rgba(242, 242, 242, 1);
- box-shadow: 0rpx 16rpx 24rpx rgba(184, 210, 188, 0.2);
-
- .shape-card-img-wrapper {
- padding: 16rpx;
- width: 100%;
- height: 200rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- box-sizing: border-box;
-
- .shape-card-img {
- width: 180rpx;
- height: 180rpx;
- }
- }
-
- .shape-card-footer {
- margin-inline: 32rpx;
- padding-block: 16rpx;
- display: flex;
- justify-content: start;
- align-items: center;
- border-top: 1rpx solid #CCCCCC;
-
- .shape-card-footer-color {
- width: 60rpx;
- height: 60rpx;
- border-radius: 50%;
- border: 2rpx solid #141414;
- margin-right: 34rpx;
- }
-
- .shape-card-footer-name {
- font-size: 28rpx;
- color: #141414;
- }
- }
-
- .delete-icon {
- position: absolute;
- top: -18rpx;
- right: -18rpx;
-
- .delete-icon-inner {
- color: rgba(255, 0, 0, 0.7);
- }
- }
-}
\ No newline at end of file
diff --git a/miniprogram/components/shape-card-v1/shape-card.json b/miniprogram/components/shape-card-v1/shape-card.json
deleted file mode 100644
index 44daf20..0000000
--- a/miniprogram/components/shape-card-v1/shape-card.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "component": true,
- "styleIsolation": "apply-shared",
- "usingComponents": {
- "van-icon": "@vant/weapp/icon/index"
- }
-}
diff --git a/miniprogram/components/shape-card-v1/shape-card.less b/miniprogram/components/shape-card-v1/shape-card.less
deleted file mode 100644
index 70fd139..0000000
--- a/miniprogram/components/shape-card-v1/shape-card.less
+++ /dev/null
@@ -1,58 +0,0 @@
-.shape-card {
- position: relative;
- width: 240rpx;
- height: 240rpx;
- border-radius: 16rpx;
- // background: #f5f5f5;
- background: #ffffff;
- border: 1rpx solid rgba(242, 242, 242, 1);
- box-shadow: 0rpx 16rpx 24rpx rgba(184, 210, 188, 0.2);
-
- .shape-card-img-wrapper {
- padding: 16rpx;
- width: 100%;
- height: 120rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- box-sizing: border-box;
-
- .shape-card-img {
- width: 120rpx;
- height: 120rpx;
- color: skyblue;
- }
- }
-
- .shape-card-footer {
- margin-inline: 32rpx;
- padding-block: 16rpx;
- display: flex;
- justify-content: start;
- align-items: center;
- border-top: 1rpx solid #CCCCCC;
-
- .shape-card-footer-color {
- width: 60rpx;
- height: 60rpx;
- border-radius: 50%;
- border: 2rpx solid #141414;
- margin-right: 34rpx;
- }
-
- .shape-card-footer-name {
- font-size: 28rpx;
- color: #141414;
- }
- }
-
- .delete-icon {
- position: absolute;
- top: -18rpx;
- right: -18rpx;
-
- .delete-icon-inner {
- color: rgba(255, 0, 0, 0.7);
- }
- }
-}
\ No newline at end of file
diff --git a/miniprogram/components/shape-card-v1/shape-card.ts b/miniprogram/components/shape-card-v1/shape-card.ts
deleted file mode 100644
index 1450f19..0000000
--- a/miniprogram/components/shape-card-v1/shape-card.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-Component({
- /**
- * 组件的属性列表
- */
- properties: {
- key: {
- type: Number,
- value: 0,
- },
- img: {
- type: String,
- value: '',
- },
- name: {
- type: String,
- value: '',
- },
- color: {
- type: String,
- value: '',
- },
- },
- /**
- * 组件的方法列表
- */
- methods: {
- onDelete() {
- const { key } = this.data;
- this.triggerEvent('onDelete', { key });
- },
- onColorTap() {
- const { key, color } = this.data;
- this.triggerEvent('onColorTap', { key, color });
- },
- },
-});
diff --git a/miniprogram/components/shape-card-v1/shape-card.wxml b/miniprogram/components/shape-card-v1/shape-card.wxml
deleted file mode 100644
index f3e8cd7..0000000
--- a/miniprogram/components/shape-card-v1/shape-card.wxml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/miniprogram/components/shape-card/shape-card copy.less b/miniprogram/components/shape-card/shape-card copy.less
deleted file mode 100644
index 9f139cd..0000000
--- a/miniprogram/components/shape-card/shape-card copy.less
+++ /dev/null
@@ -1,57 +0,0 @@
-.shape-card {
- position: relative;
- width: 300rpx;
- height: 300rpx;
- border-radius: 16rpx;
- // background: #f5f5f5;
- background: #ffffff;
- border: 1rpx solid rgba(242, 242, 242, 1);
- box-shadow: 0rpx 16rpx 24rpx rgba(184, 210, 188, 0.2);
-
- .shape-card-img-wrapper {
- padding: 16rpx;
- width: 100%;
- height: 200rpx;
- display: flex;
- justify-content: center;
- align-items: center;
- box-sizing: border-box;
-
- .shape-card-img {
- width: 180rpx;
- height: 180rpx;
- }
- }
-
- .shape-card-footer {
- margin-inline: 32rpx;
- padding-block: 16rpx;
- display: flex;
- justify-content: start;
- align-items: center;
- border-top: 1rpx solid #CCCCCC;
-
- .shape-card-footer-color {
- width: 60rpx;
- height: 60rpx;
- border-radius: 50%;
- border: 2rpx solid #141414;
- margin-right: 34rpx;
- }
-
- .shape-card-footer-name {
- font-size: 28rpx;
- color: #141414;
- }
- }
-
- .delete-icon {
- position: absolute;
- top: -18rpx;
- right: -18rpx;
-
- .delete-icon-inner {
- color: rgba(255, 0, 0, 0.7);
- }
- }
-}
\ No newline at end of file
diff --git a/miniprogram/components/shape-card/shape-card.less b/miniprogram/components/shape-card/shape-card.less
index bb7b411..7d26112 100644
--- a/miniprogram/components/shape-card/shape-card.less
+++ b/miniprogram/components/shape-card/shape-card.less
@@ -27,8 +27,8 @@
}
.shape-color {
- width: 72rpx;
- height: 72rpx;
+ width: 60rpx;
+ height: 60rpx;
border-radius: 50%;
border: 1rpx solid #141414;
background-color: skyblue;
diff --git a/miniprogram/components/shape-card/shape-card.ts b/miniprogram/components/shape-card/shape-card.ts
index 68050c6..ea46f99 100644
--- a/miniprogram/components/shape-card/shape-card.ts
+++ b/miniprogram/components/shape-card/shape-card.ts
@@ -11,7 +11,7 @@ Component({
type: String,
value: '',
},
- color: {
+ fillColor: {
type: String,
value: '',
},
@@ -34,7 +34,7 @@ Component({
* 监听属性变化
*/
observers: {
- 'svg, color': function () {
+ 'svg, fillColor': function () {
this.generateSvgDataUri();
}
},
@@ -46,12 +46,24 @@ Component({
* 生成完整的 SVG Data URI
*/
generateSvgDataUri() {
- const { svg, color } = this.data;
+ const { svg, fillColor } = this.data;
+ if (fillColor === 'transparent') return;
if (!svg) return;
- // 创建完整的 SVG 字符串,替换填充颜色
- const coloredSvg = svg.replace(/fill="#ff0000"/g, `fill="${color || '#ff0000'}"`);
- const completeSvg = ``;
+ // 处理 fill 属性:无论原来有没有 fill,都要赋值为 fillColor
+ let processedSvg = svg;
+
+ // 1. 如果有 fill 属性,全部替换为 fillColor
+ if (/fill="[^"]*"/.test(processedSvg)) {
+ processedSvg = processedSvg.replace(/fill="[^"]*"/g, `fill="${fillColor || '#ff0000'}"`);
+ } else {
+ // 2. 没有 fill 属性,则在第一个标签内加上 fill
+ processedSvg = processedSvg.replace(
+ /(<(?:circle|rect|polygon|ellipse|path|line)[^>]*?)(\/?>)/,
+ `$1 fill="${fillColor || '#ff0000'}"$2`
+ );
+ }
+ const completeSvg = ``;
// 转换为 Data URI
const svgDataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(completeSvg)}`;
@@ -65,8 +77,13 @@ Component({
this.triggerEvent('onDelete', { key });
},
onColorTap() {
- const { key, color } = this.data;
- this.triggerEvent('onColorTap', { key, color });
+ const { key, fillColor } = this.data;
+ this.triggerEvent('onColorTap', { key, fillColor });
+ },
+
+ onShapeTap() {
+ const { key } = this.data;
+ this.triggerEvent('onShapeTap', { key });
},
},
});
diff --git a/miniprogram/components/shape-card/shape-card.wxml b/miniprogram/components/shape-card/shape-card.wxml
index a1aee73..dd9873c 100644
--- a/miniprogram/components/shape-card/shape-card.wxml
+++ b/miniprogram/components/shape-card/shape-card.wxml
@@ -1,9 +1,13 @@
-
+
{
+ const completeSvg = ``;
+ const svgDataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(completeSvg)}`;
+ return {
+ ...shape,
+ svgDataUrl: svgDataUri
+ };
+ });
+ console.log('shapesWithDataUrl---:', shapesWithDataUrl);
+ this.setData({
+ shapes: shapesWithDataUrl
+ });
+ },
+ },
+ /**
+ * 组件的方法列表
+ */
+ methods: {
+ onClose() {
+ this.triggerEvent('onClose');
+ },
+
+ onSelectShape(e: WechatMiniprogram.TouchEvent) {
+ const { index } = e.currentTarget.dataset;
+ const { currentShapeKey, shapes } = this.data;
+
+ if (currentShapeKey) {
+
+ // 单选模式:currentShapeKey 不为空时,只能选中一个形状
+ this.setData({
+ shapes: shapes.map((item, i) => ({
+ ...item,
+ checked: i === index
+ }))
+ });
+ } else {
+ // 多选模式:currentShapeKey 为空时,支持多选,最多可选6个
+ let shapesCopy = this.data.shapes.map(item => ({ ...item }));
+ const targetIndex = index;
+
+ // 统计当前已选中的数量
+ const checkedCount = shapesCopy.filter(item => item.checked).length;
+
+ if (shapesCopy[targetIndex].checked) {
+ // 如果已选中,则取消选中
+ shapesCopy[targetIndex].checked = false;
+ } else {
+ if (checkedCount >= 6) {
+ wx.showToast({
+ title: '最多可选择6个形状',
+ icon: 'none',
+ duration: 1500
+ });
+ return;
+ }
+ // 如果未选中,则添加到选中列表
+ shapesCopy[targetIndex].checked = true;
+ }
+
+ this.setData({
+ shapes: shapesCopy,
+ });
+ }
+ },
+
+ onChange() {
+ const { selectedShape, selectedShapes, currentShapeKey } = this.data;
+
+ if (currentShapeKey) {
+ // 单选模式:返回单个选中的形状
+ this.triggerEvent('onChange', { shape: selectedShape, currentShapeKey });
+ } else {
+ // 多选模式:返回选中的形状数组
+ this.triggerEvent('onChange', { shapes: selectedShapes });
+ }
+ },
+
+ // 获取选中状态的 CSS 类名
+ getShapeClass(shapeId: string): string {
+ const { currentShapeKey, selectedShapes } = this.data;
+
+ if (currentShapeKey) {
+ // 单选模式:检查是否等于当前选中的形状
+ return shapeId === currentShapeKey ? 'selected single-mode' : '';
+ } else {
+ // 多选模式:检查是否在选中列表中
+ return selectedShapes.includes(shapeId) ? 'selected multi-mode' : '';
+ }
+ },
+ },
+});
diff --git a/miniprogram/components/shape-picker/shape-picker.wxml b/miniprogram/components/shape-picker/shape-picker.wxml
new file mode 100644
index 0000000..a84ea49
--- /dev/null
+++ b/miniprogram/components/shape-picker/shape-picker.wxml
@@ -0,0 +1,46 @@
+
+
+ 选择形状{{ currentShapeKey ? '' : '(多选)' }}
+
+
+
+
+
+
+
+
+
+
+ {{item.name}}
+
+
+
+
+
+ 确认选择{{ !currentShapeKey && selectedShapes.length > 0 ? '('
+ + selectedShapes.length + '个)' : '' }}
+
+
+
+
diff --git a/miniprogram/constants/shapes.ts b/miniprogram/constants/shapes.ts
index 554958f..a8d1c4a 100644
--- a/miniprogram/constants/shapes.ts
+++ b/miniprogram/constants/shapes.ts
@@ -6,7 +6,18 @@
*
*/
-const SHAPES = [
+interface ShapeCard {
+ id: string;
+ name: string;
+ type: string;
+ svg: string;
+ svgDataUrl?: string;
+ fillColor: string;
+ drawFunction?: string;
+ checked?: boolean;
+}
+
+const SHAPES: ShapeCard[] = [
// 三角形
{
id: 'obtuse-triangle',
@@ -14,13 +25,15 @@ const SHAPES = [
type: 'triangle',
// svg: '',
svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawTriangle',
},
{
id: 'right-triangle',
name: '直角三角形',
type: 'triangle',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawTriangle',
},
{
@@ -28,7 +41,8 @@ const SHAPES = [
name: '等腰三角形',
type: 'triangle',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawTriangle',
},
// 四边形
@@ -37,7 +51,8 @@ const SHAPES = [
name: '正方形',
type: 'rect',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawSquare',
},
{
@@ -45,7 +60,8 @@ const SHAPES = [
name: '长方形',
type: 'rect',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawRectangle',
},
{
@@ -53,7 +69,8 @@ const SHAPES = [
name: '平行四边形',
type: 'rect',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawParallelogram',
},
{
@@ -61,7 +78,8 @@ const SHAPES = [
name: '菱形',
type: 'rect',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawParallelogram',
},
{
@@ -69,7 +87,8 @@ const SHAPES = [
name: "梯形",
type: 'rect',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawTrapezoid',
},
// 五边形
@@ -78,7 +97,8 @@ const SHAPES = [
name: '五边形',
type: 'rect',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawHexagon',
},
@@ -87,7 +107,8 @@ const SHAPES = [
id: 'hexagon',
name: '六边形',
type: 'rect',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawHexagon',
},
// 五角星
@@ -95,7 +116,8 @@ const SHAPES = [
id: 'pentagram',
name: '五角星',
type: 'rect',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawPentagram',
},
// 心形
@@ -103,7 +125,8 @@ const SHAPES = [
id: 'heart',
name: '心形',
type: 'rect',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawHeart',
},
// 圆形
@@ -111,7 +134,8 @@ const SHAPES = [
id: 'circle',
name: '圆形',
type: 'circle',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawCircle',
},
// 椭圆
@@ -119,7 +143,8 @@ const SHAPES = [
id: 'ellipse',
name: '椭圆',
type: 'circle',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawEllipse',
},
// 半圆
@@ -128,7 +153,8 @@ const SHAPES = [
name: '半圆',
type: 'circle',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawSemicircle',
},
// 扇形
@@ -137,7 +163,8 @@ const SHAPES = [
name: '扇形',
type: 'circle',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawSector',
},
// 圆环
@@ -146,9 +173,10 @@ const SHAPES = [
name: '圆环',
type: 'circle',
// svg: '',
- svg: '',
+ svg: '',
+ fillColor: '#ff0000',
drawFunction: 'drawRing',
},
];
-export { SHAPES };
\ No newline at end of file
+export { SHAPES, ShapeCard };
\ No newline at end of file
diff --git a/miniprogram/pages/shape/index.json b/miniprogram/pages/shape/index.json
index b19c868..685d1ea 100644
--- a/miniprogram/pages/shape/index.json
+++ b/miniprogram/pages/shape/index.json
@@ -9,6 +9,7 @@
"van-icon": "@vant/weapp/icon/index",
"van-popup": "@vant/weapp/popup/index",
"toy-button": "../../ui/button/button",
- "shape-card": "../../components/shape-card/shape-card"
+ "shape-card": "../../components/shape-card/shape-card",
+ "shape-picker": "../../components/shape-picker/shape-picker"
}
}
diff --git a/miniprogram/pages/shape/index.ts b/miniprogram/pages/shape/index.ts
index 19eea84..487e040 100644
--- a/miniprogram/pages/shape/index.ts
+++ b/miniprogram/pages/shape/index.ts
@@ -1,11 +1,99 @@
-import { SHAPES } from '../../constants/shapes';
+import { SHAPES, ShapeCard } from '../../constants/shapes';
+import { WATER_COLORS, PAPER_SIZE } from '../../constants/colors';
+
+
Page({
data: {
- shapeList: SHAPES,
+ shapeList: [] as ShapeCard[],
+ showSelectShapePopup: false,
+ currentShapeKey: '',
},
onLoad() {
},
+
+ openSelectShapePopup(e: any) {
+ const { key } = e.detail;
+ this.setData({
+ showSelectShapePopup: true,
+ currentShapeKey: key
+ });
+ },
+
+ closeSelectShapePopup() {
+ this.setData({
+ showSelectShapePopup: false,
+ currentShapeKey: ''
+ });
+ },
+
+ onChangeShape(e: any) {
+ const { shape, currentShapeKey, shapes } = e.detail;
+ console.log('shape', shape);
+ console.log('shapes', shapes);
+ if (currentShapeKey) {
+ this.setData({
+ showSelectShapePopup: false,
+ currentShapeKey: '',
+ shapeList: this.data.shapeList.map(item => {
+ if (item.id === currentShapeKey) {
+ return { ...item, fillColor: item.fillColor };
+ }
+ return item;
+ })
+ });
+ } else {
+ // 随机从 WATER_COLORS.basic12 中获取不重复的颜色
+ const colorList = WATER_COLORS.basic12.map(item => item.hex);
+ const colorsCopy = [...colorList];
+ for (let i = colorsCopy.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [colorsCopy[i], colorsCopy[j]] = [colorsCopy[j], colorsCopy[i]];
+ }
+ const selectedColors = colorsCopy.slice(0, shapes.length);
+
+ this.setData({
+ showSelectShapePopup: false,
+ currentShapeKey: '',
+ shapeList: shapes.map((item: ShapeCard, idx: number) => ({
+ ...item,
+ fillColor: selectedColors[idx] || item.fillColor
+ }))
+ });
+ }
+ },
+ /**
+ * 随机生成6个图形
+ */
+ refreshShapeCard() {
+ // 随机取6个图形
+ const shapesCopy = [...SHAPES];
+ for (let i = shapesCopy.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [shapesCopy[i], shapesCopy[j]] = [shapesCopy[j], shapesCopy[i]];
+ }
+ const selectedShapes = shapesCopy.slice(0, 6);
+
+ // 随机取6个颜色
+ const colorList = WATER_COLORS.basic12.map(item => item.hex);
+ const colorsCopy = [...colorList];
+ for (let i = colorsCopy.length - 1; i > 0; i--) {
+ const j = Math.floor(Math.random() * (i + 1));
+ [colorsCopy[i], colorsCopy[j]] = [colorsCopy[j], colorsCopy[i]];
+ }
+ const selectedColors = colorsCopy.slice(0, 6);
+
+ // 分配颜色到图形
+ const shapeList = selectedShapes.map((shape, idx) => ({
+ ...shape,
+ fillColor: selectedColors[idx]
+ }));
+
+ // 更新数据
+ this.setData({
+ shapeList
+ });
+ }
});
\ No newline at end of file
diff --git a/miniprogram/pages/shape/index.wxml b/miniprogram/pages/shape/index.wxml
index 6cd0447..711414d 100644
--- a/miniprogram/pages/shape/index.wxml
+++ b/miniprogram/pages/shape/index.wxml
@@ -26,9 +26,15 @@
wx:key="{{index}}"
key="{{index}}"
svg="{{ item.svg }}"
- color="{{ item.color }}"
+ fillColor="{{ item.fillColor }}"
+ bind:onShapeTap="openSelectShapePopup"
bind:onDelete="onDelete"
bind:onColorTap="onColorTap" />
+