feat:绘制图形

This commit is contained in:
2025-09-12 16:56:00 +08:00
parent 3b4b2dcd64
commit 6acc5d676c
27 changed files with 76464 additions and 112 deletions
@@ -38,6 +38,6 @@
position: absolute;
top: -16rpx;
right: -16rpx;
color: rgba(255, 0, 0);
color: #ff0000;
}
}
@@ -77,6 +77,18 @@
width: 48rpx;
height: 48rpx;
}
&.checked-disabled {
border: 1px solid #c2c2c2;
}
.img-shape-checked-disabled {
position: absolute;
bottom: -2rpx;
right: -2rpx;
width: 48rpx;
height: 48rpx;
}
}
}
}
@@ -10,6 +10,10 @@ Component({
type: Boolean,
value: false,
},
selectedShapeList: { // 已选中的shapeList,用于初始化
type: Array,
value: [],
},
selectedShapeIndex: {
type: Number,
value: -1,
@@ -24,39 +28,72 @@ Component({
totalSelected: 0,
},
lifetimes: {
attached() {
// 处理 SVG 数据,转换为 data URL
const shapesWithDataUrl = SHAPES.map(shape => {
const completeSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">${shape.svg}</svg>`;
const svgDataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(completeSvg)}`;
return {
...shape,
svgDataUrl: svgDataUri
};
});
// attached() {
// // 处理 SVG 数据,转换为 data URL
// const shapesWithDataUrl = SHAPES.map(shape => {
// const completeSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">${shape.svg}</svg>`;
// const svgDataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(completeSvg)}`;
// return {
// ...shape,
// svgDataUrl: svgDataUri
// };
// });
// this.setData({
// shapes: shapesWithDataUrl
// });
// }
},
observers: {
// selectedShapeIndex(index: number) {
// const { shapes } = this.data;
// const newShapes = shapes.map((item, i) => ({
// ...item,
// checked: i === index
// }));
// this.setData({
// singleMode: index !== -1,
// totalSelected: index !== -1 ? 1 : 0,
// shapes: newShapes
// });
// },
'selectedShapeList, selectedShapeIndex': function (selectedShapeList: ShapeCard[], index: number) {
let newShapes = [];
let checkedIds: string[] = selectedShapeList.map(item => item.id);
if (index !== -1) { // 单选模式
let singleShapeId = selectedShapeList[index].id;
newShapes = SHAPES.map(shape => {
const completeSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">${shape.svg}</svg>`;
const svgDataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(completeSvg)}`;
return {
...shape,
svgDataUrl: svgDataUri,
checked: singleShapeId === shape.id,
checkedDisabled: singleShapeId !== shape.id && checkedIds.includes(shape.id)
}
});
} else { // 多选模式
newShapes = SHAPES.map(shape => {
const completeSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">${shape.svg}</svg>`;
const svgDataUri = `data:image/svg+xml;charset=utf-8,${encodeURIComponent(completeSvg)}`;
return {
...shape,
svgDataUrl: svgDataUri,
checked: checkedIds.includes(shape.id)
}
});
}
this.setData({
shapes: shapesWithDataUrl
shapes: newShapes,
totalSelected: newShapes.filter(item => item.checked).length,
singleMode: index !== -1,
});
}
},
observers: {
selectedShapeIndex(newVal: number) {
this.setData({
singleMode: newVal !== -1
});
},
},
// pageLifetimes: {
// show: function () {
// console.log('show singleMode', this.data.singleMode);
// },
// hide: function () {
// console.log('hide singleMode', this.data.singleMode);
// },
// resize: function (size) {
// console.log('resize', size);
// }
// },
/**
* 组件的方法列表
*/
@@ -70,6 +107,16 @@ Component({
const { singleMode, shapes } = this.data;
let newShapes = [];
const selectedShape = shapes[index];
if (selectedShape.checkedDisabled) {
wx.showToast({
title: '当前形状已选中,请勿重复选中',
icon: 'none',
duration: 1500
});
return;
}
if (singleMode) {
// 单选模式:currentShapeKey 不为空时,只能选中一个形状
newShapes = shapes.map((item, i) => ({
@@ -78,7 +125,7 @@ Component({
}));
} else {
// 多选模式:currentShapeKey 为空时,支持多选,最多可选6个
newShapes = this.data.shapes.map(item => ({ ...item }));
newShapes = shapes.map(item => ({ ...item }));
const targetIndex = index;
// 统计当前已选中的数量
@@ -7,11 +7,11 @@
选择形状{{ singleMode ? '(单选)' : '(多选)' }}
</text>
<view class="shape-options-wrapper">
<view class="shape-options">
<view class="shape-options {{ singleMode ? 'single-mode' : '' }}">
<view
wx:for="{{shapes}}"
wx:key="id"
class="shape-option {{item.checked ? 'selected' : '' }}"
class="shape-option {{item.checked ? 'selected' : '' }} {{ item.checkedDisabled ? 'checked-disabled' : '' }}"
bindtap="onSelectShape"
data-index="{{index}}"
data-shape="{{item.id}}">
@@ -25,6 +25,11 @@
class="img-shape-selected"
src="/assets/imgs/checked.png"
mode="aspectFit" />
<image
wx:if="{{item.checkedDisabled}}"
class="img-shape-checked-disabled"
src="/assets/imgs/checked-disabled.png"
mode="aspectFit" />
</view>
</view>
</view>