From 2f50fcf0fbb7eff3c3cc72ffbd1316692da2d7c7 Mon Sep 17 00:00:00 2001 From: qinhaoyan Date: Thu, 19 Dec 2024 15:41:54 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96shape=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=9C=86=E8=A7=92=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-CN/components/shape.md | 19 +- packages/amis-ui/scss/components/_shape.scss | 2 +- packages/amis-ui/src/components/Shape.tsx | 231 ++++--------------- packages/amis-ui/src/utils/vectorComputed.ts | 98 ++++++++ 4 files changed, 157 insertions(+), 193 deletions(-) create mode 100644 packages/amis-ui/src/utils/vectorComputed.ts diff --git a/docs/zh-CN/components/shape.md b/docs/zh-CN/components/shape.md index 4537c99c6f6..3cba9e74ae1 100644 --- a/docs/zh-CN/components/shape.md +++ b/docs/zh-CN/components/shape.md @@ -85,7 +85,7 @@ icon: type: 'shape', className: 'm-2', shapeType: 'square', - radius: 4 + radius: -4 }, { type: 'shape', @@ -165,7 +165,6 @@ icon: {"name": "矩形-类型1", "shapeType": "rectangle-1"}, {"name": "矩形-类型2", "shapeType": "rectangle-2"}, {"name": "矩形-类型3", "shapeType": "rectangle-3"}, - {"name": "矩形-类型4", "shapeType": "rectangle-4"}, {"name": "心形", "shapeType": "heart"}, {"name": "正五边形", "shapeType": "pentagon"}, {"name": "正六边形", "shapeType": "hexagon"}, @@ -207,11 +206,11 @@ icon: ## 属性表 -| 属性名 | 类型 | 默认值 | 说明 | -| --------- | ------------ | --------- | ------------------- | -| type | `string` | `'shape'` | 指定为图形渲染器 | -| shapeType | `IShapeType` | `'-'` | 图形类型 | -| className | `string` | | 自定义 CSS 样式类名 | -| width | `number` | `200` | 图形宽度 | -| height | `number` | `200` | 图形大小 | -| radius | `number` | `0` | 圆角大小(1-10) | +| 属性名 | 类型 | 默认值 | 说明 | +| --------- | ------------ | --------- | --------------------- | +| type | `string` | `'shape'` | 指定为图形渲染器 | +| shapeType | `IShapeType` | `'-'` | 图形类型 | +| className | `string` | | 自定义 CSS 样式类名 | +| width | `number` | `200` | 图形宽度 | +| height | `number` | `200` | 图形大小 | +| radius | `number` | `0` | 圆角大小,负数表示内弧 | diff --git a/packages/amis-ui/scss/components/_shape.scss b/packages/amis-ui/scss/components/_shape.scss index 99b8210fe3c..14c4223e25d 100644 --- a/packages/amis-ui/scss/components/_shape.scss +++ b/packages/amis-ui/scss/components/_shape.scss @@ -1,5 +1,5 @@ /** - * @file _shape.scss + * @file _shape.scss * * @author allenve(yupeng12@baidu.com) * @created: 2024/12/12 diff --git a/packages/amis-ui/src/components/Shape.tsx b/packages/amis-ui/src/components/Shape.tsx index 27ab0701d73..32a68610390 100644 --- a/packages/amis-ui/src/components/Shape.tsx +++ b/packages/amis-ui/src/components/Shape.tsx @@ -7,6 +7,7 @@ import React from 'react'; import {themeable, ThemeProps} from 'amis-core'; +import {radiusStartEndPoint} from '../utils/vectorComputed'; export type IShapeType = | 'square' @@ -22,8 +23,7 @@ export type IShapeType = | 'parallelogram' // 平行四边形 | 'rectangle-1' // 矩形类型1 | 'rectangle-2' // 矩形类型2 - | 'rectangle-3' // 矩形类型1 - | 'rectangle-4' // 矩形类型2 + | 'rectangle-3' // 矩形类型3 | 'pentagon' // 五边形 | 'hexagon' // 六边形 | 'octagon' // 八边形 @@ -62,8 +62,7 @@ class SvgPathGenerator { if (!genFun) { return []; } - const radiusValue = Math.floor(Math.max(0, Math.min(10, radius))) || 0; - return genFun(radiusValue * 10); + return genFun(radius * 10); } toRadians(degrees: number) { @@ -88,7 +87,6 @@ class SvgPathGenerator { 'rectangle-1': this.getRectangleType1Path.bind(this), 'rectangle-2': this.getRectangleType2Path.bind(this), 'rectangle-3': this.getRectangleType3Path.bind(this), - 'rectangle-4': this.getRectangleType4Path.bind(this), 'pentagon': this.getPentagon.bind(this), 'hexagon': this.getHexagon.bind(this), 'octagon': this.getOctagonPath.bind(this), @@ -103,49 +101,33 @@ class SvgPathGenerator { return ShapeConfig[type]; } - /** - * 传入起点、终点和距离,返回直线上距离起点距离为distanc - * - * @param {[number, number]} [startX, startY] - * @param {[number, number]} [endX, endY] - * @param {number} distance - * @returns - * @memberof SvgPathGenerator - */ - radiusPoint( - [startX, startY]: [number, number], - [endX, endY]: [number, number], - distance: number - ) { - // 计算终点与起点的直线距离 - const dx = endX - startX; - const dy = endY - startY; - const totalDistance = Math.sqrt(dx * dx + dy * dy); - - // 如果距离大于总距离的一半,则取一半 - if (distance > totalDistance / 2) { - distance = totalDistance / 2; - } - - // 计算比例 - const ratio = distance / totalDistance; - - // 计算新点 - const x = startX + dx * ratio; - const y = startY + dy * ratio; - - return [x, y]; - } - radiusPath( radius: number, [endX1, endY1]: [number, number], [startX, startY]: [number, number], [endX2, endY2]: [number, number] ) { - const [x1, y1] = this.radiusPoint([startX, startY], [endX1, endY1], radius); - const [x2, y2] = this.radiusPoint([startX, startY], [endX2, endY2], radius); - return [`${x1},${y1}`, `${startX},${startY} ${x2},${y2}`]; + let flag = true; + if (radius < 0) { + radius = radius * -1; + // 圆角向内 + flag = false; + } + const { + start, + end, + radius: mxRadius, + sweepFlag + } = radiusStartEndPoint( + [startX, startY, endX1, endY1], + [startX, startY, endX2, endY2], + radius + ); + return [ + `${start[0]},${start[1]}`, + `${mxRadius} ${mxRadius} ${0} ${0} ${flag ? sweepFlag : sweepFlag ^ 1} + ${end[0]},${end[1]}` + ]; } /** @@ -164,18 +146,17 @@ class SvgPathGenerator { const [startX, startY] = points[i]; const [endX1, endY1] = nextItem; const [endX2, endY2] = preItem; - const [start, Q] = this.radiusPath( + if (!radius) { + newPath.push(`${i === 0 ? 'M' : 'L'}${startX},${startY}`); + continue; + } + const [start, A] = this.radiusPath( radius, [endX2, endY2], [startX, startY], [endX1, endY1] ); - - if (i === 0) { - newPath.push(`M${start}`, `Q${Q}`); - } else { - newPath.push(`L${start}`, `Q${Q}`); - } + newPath.push(`${i === 0 ? 'M' : 'L'}${start}`, `A${A}`); } newPath.push('Z'); @@ -191,57 +172,36 @@ class SvgPathGenerator { [S, S], [0, S] ]; - const ponits2: Array<[number, number]> = [ - [S, S], - [S, 0], - [0, 0], - [0, S] - ]; const path1 = this.addRoundCornersToPath(ponits1, radius); - - const path2 = this.addRoundCornersToPath(ponits2, radius); - // 用两个path重叠 避免曲线的间隙 - return [path1, path2]; + return [path1]; } // 等边三角形 getTrianglePath(radius: number) { const S = this.size; const height = Math.sin(this.toRadians(60)) * S; - const x = ((2 - Math.sqrt(3)) / 4) * S - (Math.sqrt(3) / 8) * radius; + const x = ((2 - Math.sqrt(3)) / 4) * S - (Math.sqrt(3) / 8) * (radius || 0); const points1: Array<[number, number]> = [ [0, height + x], [S / 2, x], [S, height + x] ]; - const points2: Array<[number, number]> = [ - [S / 2, x], - [S, height + x], - [0, height + x] - ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 直角三角形 getRightTrianglePath(radius: number) { const points1: Array<[number, number]> = [ [0, 0], - [0, 200], - [200, 200] - ]; - const points2: Array<[number, number]> = [ [200, 200], - [0, 200], - [0, 0] + [0, 200] ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 矩形 @@ -253,15 +213,8 @@ class SvgPathGenerator { [S, (S / 4) * 3], [0, (S / 4) * 3] ]; - const points2: Array<[number, number]> = [ - [S, (S / 4) * 3], - [S, S / 4], - [0, S / 4], - [0, (S / 4) * 3] - ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 凸弧矩形 @@ -277,15 +230,8 @@ class SvgPathGenerator { L ${w} ${h + x} Z `; - const path2 = ` - M 0 ${radius + x} - Q ${w / 2} ${x} ${w} ${radius + x} - L ${w} ${h + x} - L 0 ${h + x} - Z - `; - return [path1, path2]; + return [path1]; } // 凹弧矩形 @@ -301,15 +247,8 @@ class SvgPathGenerator { L ${w} ${h + x} Z `; - const path2 = ` - M 0 ${x} - Q ${w / 2} ${radius + x} ${w} ${x} - L ${w} ${h + x} - L 0 ${h + x} - Z - `; - return [path1, path2]; + return [path1]; } // 双凸弧矩形 @@ -323,15 +262,7 @@ class SvgPathGenerator { Q ${S / 2} ${(S / 4) * 3 + dx} 0 ${(S / 4) * 3} Z `; - const path2 = ` - M ${S} ${(S / 4) * 3} - L ${S} ${S / 4} - Q ${S / 2} ${S / 4 - dx} 0 ${S / 4} - L 0 ${(S / 4) * 3} - Q ${S / 2} ${(S / 4) * 3 + dx} ${S} ${(S / 4) * 3} - Z - `; - return [path1, path2]; + return [path1]; } // 双凹弧矩形 getDConcaveArcRectangle(radius: number) { @@ -344,15 +275,7 @@ class SvgPathGenerator { Q ${S / 2} ${(S / 4) * 3 - dx} 0 ${(S / 4) * 3} Z `; - const path2 = ` - M ${S} ${(S / 4) * 3} - L ${S} ${S / 4} - Q ${S / 2} ${S / 4 + dx} 0 ${S / 4} - L 0 ${(S / 4) * 3} - Q ${S / 2} ${(S / 4) * 3 - dx} ${S} ${(S / 4) * 3} - Z - `; - return [path1, path2]; + return [path1]; } // 桶形矩形 @@ -367,14 +290,7 @@ class SvgPathGenerator { Q ${S / 2} ${(S / 4) * 3 + R - dx} 0 ${(S / 4) * 3 - dx} Z `; - const path2 = ` - M 0 ${S / 4 - dx} - Q ${S / 2} ${S / 4 + R - dx} ${S} ${S / 4 - dx} - L ${S} ${(S / 4) * 3 - dx} - Q ${S / 2} ${(S / 4) * 3 + R - dx} 0 ${(S / 4) * 3 - dx} - Z - `; - return [path1, path2]; + return [path1]; } // 菱形 @@ -385,16 +301,9 @@ class SvgPathGenerator { [100, 200], [0, 100] ]; - const ponits2: Array<[number, number]> = [ - [200, 100], - [100, 0], - [0, 100], - [100, 200] - ]; const path1 = this.addRoundCornersToPath(ponits1, radius); - const path2 = this.addRoundCornersToPath(ponits2, radius); - return [path1, path2]; + return [path1]; } // 平行四边形 @@ -405,16 +314,9 @@ class SvgPathGenerator { [150, 200], [0, 200] ]; - const points2: Array<[number, number]> = [ - [150, 200], - [200, 0], - [50, 0], - [0, 200] - ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 矩形-类型1 @@ -441,24 +343,7 @@ class SvgPathGenerator { } // 矩形-类型2 - getRectangleType2Path() { - const path = [ - 'M20,0', - 'L180,0', - 'Q180,20 200,20', - 'L200,180', - 'Q180,180 180,200', - 'L20,200', - 'Q20,180 0,180', - 'L0,20', - 'Q20,20 20,0', - 'Z' - ]; - return [path]; - } - - // 矩形-类型3 - getRectangleType3Path(radius: number) { + getRectangleType2Path(radius: number) { const S = this.size; const dx = 35; const points: Array<[number, number]> = [ @@ -473,8 +358,8 @@ class SvgPathGenerator { return [path]; } - // 矩形-类型4 - getRectangleType4Path(radius: number) { + // 矩形-类型3 + getRectangleType3Path(radius: number) { const S = this.size; const dx = 35; const points: Array<[number, number]> = [ @@ -541,17 +426,9 @@ class SvgPathGenerator { [0, a + dx], [b, dx] ]; - const points2: Array<[number, number]> = [ - [x1, a + x2 + dx], - [S - x1, a + x2 + dx], - [S, a + dx], - [b, dx], - [0, a + dx] - ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 六边形 @@ -564,18 +441,9 @@ class SvgPathGenerator { [13.8974596, 149.711325], [13.8974596, 50.2886751] ]; - const points2: Array<[number, number]> = [ - [100, 199.42265], - [186.10254, 149.711325], - [186.10254, 50.2886751], - [100, 0.577350269], - [13.8974596, 50.2886751], - [13.8974596, 149.711325] - ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 正八边形 @@ -603,8 +471,7 @@ class SvgPathGenerator { [x, S] ]; const path1 = this.addRoundCornersToPath(points1, radius); - const path2 = this.addRoundCornersToPath(points2, radius); - return [path1, path2]; + return [path1]; } // 六角星 diff --git a/packages/amis-ui/src/utils/vectorComputed.ts b/packages/amis-ui/src/utils/vectorComputed.ts new file mode 100644 index 00000000000..0c2ccce536a --- /dev/null +++ b/packages/amis-ui/src/utils/vectorComputed.ts @@ -0,0 +1,98 @@ +// 计算向量的模长 +export function vectorLength(v: number[]): number { + return Math.sqrt(v.reduce((sum, cur) => sum + cur ** 2, 0)); +} + +// 计算向量的点积 +export function dotProduct(v1: number[], v2: number[]): number { + return v1.reduce((sum, cur, index) => sum + cur * v2[index], 0); +} + +// 计算向量的夹角 +export function vectorAngle(v1: number[], v2: number[]): number { + return Math.acos(dotProduct(v1, v2) / (vectorLength(v1) * vectorLength(v2))); +} + +// 通过直角边和夹角计算另一直角边长度 +export function computeSideLength(side: number, angle: number): number { + return side / Math.tan(angle); +} + +/** + * 传入起点、终点和距离,返回直线上距离起点距离为distance + * + * @param {[number, number]} [startX, startY] + * @param {[number, number]} [endX, endY] + * @param {number} distance + * @returns + * @memberof SvgPathGenerator + */ +export function radiusPoint( + [startX, startY]: number[], + [endX, endY]: number[], + distance: number +) { + // 计算终点与起点的直线距离 + const dx = endX - startX; + const dy = endY - startY; + const totalDistance = Math.sqrt(dx * dx + dy * dy); + + // 如果距离大于总距离的一半,则取一半 + if (distance > totalDistance / 2) { + distance = totalDistance / 2; + } + + // 计算比例 + const ratio = distance / totalDistance; + + // 计算新点 + const x = startX + dx * ratio; + const y = startY + dy * ratio; + + return [x, y]; +} + +// 传入2个向量和圆角半径,返回圆角弧线的起始点坐标 +export function radiusStartEndPoint( + v1: number[], + v2: number[], + radius: number +) { + // 计算向量夹角 + const angle = vectorAngle( + [v1[2] - v1[0], v1[3] - v1[1]], + [v2[2] - v1[0], v2[3] - v1[1]] + ); + + // 计算3点是顺时针还是逆时针 + const sweepFlag = + (v1[2] - v1[0]) * (v2[3] - v1[1]) - (v1[3] - v1[1]) * (v2[2] - v1[0]) < 0 + ? 1 + : 0; + + // 计算短边一半的长度 + const maxLength = Math.min( + vectorLength([v1[2] - v1[0], v1[3] - v1[1]]) / 2, + vectorLength([v2[2] - v1[0], v2[3] - v1[1]]) / 2 + ); + + // 计算radius的最大值 + const maxRadius = Math.min(radius, maxLength * Math.tan(angle / 2)); + + // 直角边的长度 + const distance = computeSideLength(maxRadius, angle / 2); + + const [startX, startY] = radiusPoint( + [v1[0], v1[1]], + [v1[2], v1[3]], + distance + ); + const [endX, endY] = radiusPoint([v2[0], v2[1]], [v2[2], v2[3]], distance); + + return { + start: [startX, startY], + end: [endX, endY], + radius: maxRadius, + sweepFlag + }; +} From fec273ee52bff7c35d4d25e61bc4cd1a14d25981 Mon Sep 17 00:00:00 2001 From: qinhaoyan Date: Thu, 19 Dec 2024 19:37:13 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-CN/components/shape.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/zh-CN/components/shape.md b/docs/zh-CN/components/shape.md index 3cba9e74ae1..1511a148fd6 100644 --- a/docs/zh-CN/components/shape.md +++ b/docs/zh-CN/components/shape.md @@ -132,12 +132,11 @@ icon: shapeType: 'custom', color: "#037bff", paths: [ - "M 27.5,-0.5 C 29.5,-0.5 31.5,-0.5 33.5,-0.5C 36.7684,0.854923 37.1017,2.68826 34.5,5C 27.8333,9 21.1667,13 14.5,17C 16.0444,18.1871 17.7111,18.5205 19.5,18C 27.2036,13.8164 34.8703,9.64975 42.5,5.5C 48.8656,8.36388 54.8656,11.8639 60.5,16C 61.7112,16.8928 61.7112,17.7261 60.5,18.5C 50.6679,24.4991 40.5012,29.8324 30,34.5C 27.3736,34.4441 25.5403,33.2774 24.5,31C 31.4655,25.845 38.7989,21.1784 46.5,17C 45.3349,15.9164 44.0016,15.0831 42.5,14.5C 35.3291,18.9197 27.9958,23.0864 20.5,27C 18.8333,27.6667 17.1667,27.6667 15.5,27C 12.6907,25.2589 9.69069,24.0922 6.5,23.5C 6.33003,24.8221 6.66337,25.9887 7.5,27C 15.0829,31.3742 22.5829,35.8742 30,40.5C 40.1623,35.0865 50.1623,29.4198 60,23.5C 60.3333,23.8333 60.6667,24.1667 61,24.5C 61.6667,31.5 61.6667,38.5 61,45.5C 52.3566,51.5651 43.5232,57.2318 34.5,62.5C 31.8333,62.5 29.1667,62.5 26.5,62.5C 17.7048,56.5972 8.70483,50.9305 -0.5,45.5C -0.5,42.8333 -0.5,40.1667 -0.5,37.5C 9.82265,42.8149 20.156,48.1483 30.5,53.5C 37.9543,49.9391 45.2876,46.1058 52.5,42C 54.2446,40.308 54.5779,38.4747 53.5,36.5C 45.908,41.2139 38.0747,45.5472 30,49.5C 19.4253,44.0703 9.25867,38.0703 -0.5,31.5C -0.5,26.5 -0.5,21.5 -0.5,16.5C 8.85567,10.7985 18.189,5.13186 27.5,-0.5 Z", - "M 159.5,3.5 C 165.768,3.09235 167.768,5.75901 165.5,11.5C 158.228,12.9758 156.228,10.3091 159.5,3.5 Z", - "M 80.5,14.5 C 85.881,14.5735 90.881,15.9068 95.5,18.5C 98.816,26.6338 99.316,34.9671 97,43.5C 94.3893,47.6316 90.556,49.6316 85.5,49.5C 73.8113,48.9956 69.978,43.3289 74,32.5C 78.8546,28.8907 84.3546,27.224 90.5,27.5C 90.1774,23.8441 88.1774,21.8441 84.5,21.5C 80.7571,21.8577 77.4238,23.191 74.5,25.5C 73.359,23.5787 73.1923,21.5787 74,19.5C 75.9651,17.4497 78.1318,15.783 80.5,14.5 Z M 86.5,33.5 C 91.6306,33.606 92.7973,35.9394 90,40.5C 87.0622,42.8691 83.8956,43.0358 80.5,41C 79.4464,39.6124 79.2797,38.1124 80,36.5C 82.166,35.2685 84.3326,34.2685 86.5,33.5 Z", - "M 113.5,14.5 C 119.291,13.4888 124.124,15.1555 128,19.5C 133.652,15.2568 139.819,14.4235 146.5,17C 148.041,18.5793 149.208,20.4127 150,22.5C 150.832,31.1507 151.332,39.8174 151.5,48.5C 149.208,48.7564 147.041,48.4231 145,47.5C 143.781,40.5789 143.114,33.5789 143,26.5C 139.814,20.2831 136.147,19.9497 132,25.5C 131.5,33.1594 131.334,40.8261 131.5,48.5C 129.409,48.6816 127.409,48.3482 125.5,47.5C 124.337,40.2078 123.504,32.8745 123,25.5C 118.27,20.025 114.603,20.6917 112,27.5C 111.5,34.4921 111.334,41.4921 111.5,48.5C 108.921,48.9167 106.754,48.25 105,46.5C 104.333,39.1667 104.333,31.8333 105,24.5C 106.261,19.7452 109.095,16.4118 113.5,14.5 Z", - "M 199.5,35.5 C 199.5,37.5 199.5,39.5 199.5,41.5C 196.891,47.0648 192.391,49.7314 186,49.5C 179.379,49.3775 175.879,46.0442 175.5,39.5C 178.949,40.6386 182.449,41.6386 186,42.5C 188.97,42.7659 191.137,41.5992 192.5,39C 191.833,37.6667 190.833,36.6667 189.5,36C 185.218,34.7245 181.051,33.2245 177,31.5C 173.387,20.9296 177.221,15.263 188.5,14.5C 191.963,15.1536 195.13,16.487 198,18.5C 198.495,20.4727 198.662,22.4727 198.5,24.5C 195.496,23.2221 192.329,22.2221 189,21.5C 186.095,21.5591 183.928,22.7258 182.5,25C 186.479,27.5587 190.812,29.5587 195.5,31C 197.07,32.3968 198.404,33.8968 199.5,35.5 Z", - "M 158.5,15.5 C 161.044,15.1043 163.211,15.771 165,17.5C 165.112,25.5921 165.946,33.5921 167.5,41.5C 169.661,42.0351 171.661,42.8684 173.5,44C 169.982,50.6733 165.482,51.1733 160,45.5C 158.705,35.545 158.205,25.545 158.5,15.5 Z" + "M28.7312529,0.451996665 L1.92575684,15.8327405 C0.641918945,16.9201671 0,17.8552977 0,18.6381323 C0,19.4209669 0,23.7793686 0,31.7133374 L30.1233295,49.1882469 L54.74597,35.1754816 L54.74597,42.2129373 L31.0027368,56.1570351 C30.3803008,56.644996 29.8461111,56.644996 29.4001678,56.1570351 C28.9542245,55.6690741 19.1541686,49.8258134 0,38.6272531 L0,45.7376111 L28.7312529,62.5701394 C29.9104176,63.1432869 31.0961916,63.1432869 32.2885747,62.5701394 C33.4809578,61.9969918 43.0514329,56.3861491 61,45.7376111 L61,24.3532598 C43.0365968,34.8706536 33.4661217,40.4338687 32.2885747,41.0429051 C30.5222542,41.9564597 30.0828355,41.8389106 28.7312529,41.0429051 C27.8301979,40.5122348 20.3630035,36.1320948 6.32966971,27.9024851 L6.32966971,21.8340463 L16.8640877,27.2811313 C18.1811929,27.7179433 19.2031727,27.7179433 19.9300272,27.2811313 C20.6568816,26.8443193 28.2327888,22.3902338 42.6577487,13.9188748 L47.8268453,17.033462 C48.2333133,17.6822864 48.064461,18.2171765 47.3202883,18.6381323 C46.5761157,19.0590881 39.0914758,23.234167 24.8663686,31.1633689 L30.1233295,35.1754816 L61,17.9315096 L43.3323939,6.26763183 L18.1933006,20.3607536 L13.3840291,17.033462 L36.6348401,3.39932681 L32.7397763,0.451996665 C31.8901421,0.150665555 31.2386503,0 30.7853012,0 C30.331952,0 29.6472692,0.150665555 28.7312529,0.451996665 Z", + "M85.4606259,16 C91.6887073,16 98,19.9446168 98,24.4357411 L98,40.7476187 C96.2218371,46.2492062 93.4906486,49 89.8064346,49 C86.1222206,49 83.1967025,48.9610235 81.0298802,48.8830705 C79.1204375,48.1724054 77.850878,47.5467586 77.2212016,47.0061299 C75.1137392,45.1967008 74.0196778,43.6199029 73.6733281,42.7807824 C73.2701673,41.8040225 71.9205412,38.0832352 74.7691152,33.7965154 C76.4122418,31.3238313 79.7102167,29.6814742 82.6168695,29.3805022 L92.0014918,29.3805022 L92.0014918,24.4357411 C90.1259032,22.5455883 87.9456146,21.600512 85.4606259,21.600512 L84.7605642,21.6006889 C81.8851835,21.6087957 80.8791028,21.7977752 74.4275673,25.5002778 L74.4275673,20.825158 C77.6308853,17.608386 81.3085715,16 85.4606259,16 Z M92.1136435,33.8360358 L84.9688911,33.8360358 C80.9383044,34.662764 78.9230111,36.3792944 78.9230111,38.985627 C78.9230111,41.5919597 80.2819885,43.3084901 82.9999432,44.1352182 L87.9615254,44.1352182 C90.0138334,44.1352182 91.3978727,42.8170486 92.1136435,40.1807095 L92.1136435,33.8360358 Z", + "M106,45.9058326 L106.12203,26.0591328 C107.998819,19.3539517 112.44853,16.0013611 119.471163,16.0013611 C123.091874,15.9443424 126.348706,17.6787713 129.241661,21.2046476 C131.146086,17.7357899 134.533925,16.0013611 139.405178,16.0013611 C142.929724,16.0013611 147.449054,17.71895 149.676343,21.7722423 C150.188086,22.7035287 150.629305,24.1324922 151,26.0591328 L150.880889,48 L148.277496,48 C146.491015,47.376753 145.444467,46.3780151 145.137852,45.0037864 C145.137852,44.4024223 145.137852,38.5872358 145.137852,27.5582269 C144.726084,23.8837882 142.815193,21.9551266 139.405178,21.7722423 C134.290157,21.4979157 131.885977,24.5600387 131.885977,26.0591328 C131.885977,27.0585289 131.885977,34.3721513 131.885977,48 L127.514392,48 C126.066497,47.117215 125.34255,46.1184772 125.34255,45.0037864 C125.34255,43.8890957 125.34255,37.7903229 125.34255,26.707468 C124.168415,23.4173175 121.973924,21.7722423 118.759078,21.7722423 C113.936808,21.7722423 112.018661,24.9975268 112.018661,26.707468 C112.018661,27.8474288 112.018661,34.9449395 112.018661,48 L108.414781,48 C107.890079,47.9047657 107.35644,47.6282578 106.813864,47.1704763 C106.271288,46.7126949 106,46.291147 106,45.9058326 Z", + "M160.140201,16.7159953 L160.140201,42.1967437 C160.100175,42.583777 160.383858,43.4742319 160.991248,44.8681084 C161.950865,47.0702956 165.286128,49 168.094575,49 C171.736366,49 173.350406,47.1468859 172.936694,43.4406577 L168.094575,43.4406577 C166.412106,43.1933185 165.570871,42.1819868 165.570871,40.4066624 C165.570871,38.6313381 165.570871,31.8283876 165.570871,19.997811 C164.879352,18.0634863 163.857786,16.9695478 162.506173,16.7159953 C161.15456,16.4624429 160.365903,16.4624429 160.140201,16.7159953 Z M162.757704,12.6808435 C164.833027,12.6808435 166.515408,10.9614281 166.515408,8.84042173 C166.515408,6.71941538 164.833027,5 162.757704,5 C160.682381,5 159,6.71941538 159,8.84042173 C159,10.9614281 160.682381,12.6808435 162.757704,12.6808435 Z", + "M177.00791,25.6466313 C176.697727,34.2604795 185.59716,34.4875652 188.32068,34.8600665 C191.0442,35.2325677 193.783492,36.1062875 193.783492,39.4670446 C193.783492,42.8278017 191.560993,43.4871964 189.446164,43.4871964 C187.331335,43.4871964 187.047369,43.6717882 184.447219,43.4871964 C182.713785,43.3641352 180.442017,42.1357631 177.631913,39.8020801 L177.631913,44.8030644 C179.513873,47.6010215 182.71894,49 187.247112,49 C194.03937,49 200,45.5737365 200,38.8852924 C200,32.1968484 193.250147,29.9615425 185.661293,28.8150427 C182.33376,27.9726002 182.963706,26.4071448 182.963706,24.4700092 C182.963706,22.5328736 186.910243,21.4851146 189.928058,21.4851146 C192.945874,21.4851146 198.713517,23.9817612 198.713517,24.7718362 C198.713517,25.2985529 198.713517,23.5269195 198.713517,19.4569362 C197.801499,18.3656594 196.499944,17.4867226 194.808852,16.8201258 C192.272215,15.8202307 190.383829,16.0153824 187.522469,16.0153824 C182.366988,16.0153824 177.197843,20.3721739 177.00791,25.6466313 Z" ] } ] @@ -211,6 +210,7 @@ icon: | type | `string` | `'shape'` | 指定为图形渲染器 | | shapeType | `IShapeType` | `'-'` | 图形类型 | | className | `string` | | 自定义 CSS 样式类名 | +| color | `string` | | 填充颜色 | | width | `number` | `200` | 图形宽度 | | height | `number` | `200` | 图形大小 | | radius | `number` | `0` | 圆角大小,负数表示内弧 | From 2647bc0bceca9a44136a5c3aba39e9a7c83498b0 Mon Sep 17 00:00:00 2001 From: qinhaoyan Date: Thu, 19 Dec 2024 20:53:27 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E4=B8=89=E8=A7=92=E5=BD=A2=E5=B1=85?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/amis-ui/src/components/Shape.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/amis-ui/src/components/Shape.tsx b/packages/amis-ui/src/components/Shape.tsx index 32a68610390..aa4bec3989f 100644 --- a/packages/amis-ui/src/components/Shape.tsx +++ b/packages/amis-ui/src/components/Shape.tsx @@ -180,12 +180,14 @@ class SvgPathGenerator { getTrianglePath(radius: number) { const S = this.size; const height = Math.sin(this.toRadians(60)) * S; - const x = ((2 - Math.sqrt(3)) / 4) * S - (Math.sqrt(3) / 8) * (radius || 0); + const maxRadius = Math.min(radius, Math.tan(this.toRadians(30)) * (S / 2)); + // sin30度,所以斜边是R的2倍,斜边减去R就是高度移动的距离 + const dy = (S - height - maxRadius) / 2; const points1: Array<[number, number]> = [ - [0, height + x], - [S / 2, x], - [S, height + x] + [0, height + dy], + [S / 2, dy], + [S, height + dy] ]; const path1 = this.addRoundCornersToPath(points1, radius); From ed5b0c7a88e4f6f7cf4e3f6f2744e9c84226bd9a Mon Sep 17 00:00:00 2001 From: qinhaoyan Date: Fri, 20 Dec 2024 11:09:54 +0800 Subject: [PATCH 4/4] bugfix --- packages/amis-theme-editor-helper/rollup.config.js | 5 +++++ packages/amis-ui/src/components/Shape.tsx | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/amis-theme-editor-helper/rollup.config.js b/packages/amis-theme-editor-helper/rollup.config.js index 802bd280e7b..3433d25e8c2 100644 --- a/packages/amis-theme-editor-helper/rollup.config.js +++ b/packages/amis-theme-editor-helper/rollup.config.js @@ -48,6 +48,11 @@ const pkgs = []; } }); +const index = pkgs.indexOf('style-inject'); +if (~index) { + pkgs.splice(index, 1); +} + const external = id => pkgs.some(pkg => id.startsWith(pkg) || ~id.indexOf(`node_modules/${pkg}`)); const input = ['./src/index.ts']; diff --git a/packages/amis-ui/src/components/Shape.tsx b/packages/amis-ui/src/components/Shape.tsx index aa4bec3989f..b20b4a45004 100644 --- a/packages/amis-ui/src/components/Shape.tsx +++ b/packages/amis-ui/src/components/Shape.tsx @@ -180,7 +180,8 @@ class SvgPathGenerator { getTrianglePath(radius: number) { const S = this.size; const height = Math.sin(this.toRadians(60)) * S; - const maxRadius = Math.min(radius, Math.tan(this.toRadians(30)) * (S / 2)); + // 内切圆为最大圆角,其半径是高度的1/3 + const maxRadius = Math.min(radius, height / 3) || 0; // sin30度,所以斜边是R的2倍,斜边减去R就是高度移动的距离 const dy = (S - height - maxRadius) / 2;