显示动态圆 Children
Display a Circle with Dynamic Children
我正在创建一个使用圆形作为布局的动态阵列显示。数组的每个元素将占据圆内 space 的相同部分。如果数组中有 3 个元素,则需要在 3 个相等的 space 秒内填满 100% 的圆。我已经让它工作到显示 4 个相同大小的元素的程度。我需要帮助找出一个公式来根据数组的大小调整正方形的大小。
我的方法是单独创建每个元素。我需要控制圆圈内的每个 child,同时将 child 内的文本居中。我也乐于接受新想法,我觉得代码有点乱。如果您有更清洁的方法,请分享!
下面是我的代码:
import React, { useState, forwardRef } from "react";
import {dataFlow} from './database'
const PieDisplay = forwardRef(({ showWindow }, ref) => {
const [display, setDisplay] = useState(dataFlow.map((item) => item));
const getPieStyle = (index) => {
let pieButtonStyle = {
transform: "",
};
const rotX = (360 / display.length) * index; //set the angle for each element of the pie
pieButtonStyle.transform = `rotate(${rotX}deg) skewY(0deg)`;
return pieButtonStyle;
};
const getPieTextStyle = (index) => {
let pieButtonStyle = {
transform: "",
};
const rotX = 360 / display.length / 2; //set the angle for each element's text of the pie
pieButtonStyle.transform = `rotate(${rotX}deg) skewY(0deg)`;
return pieButtonStyle;
};
let i = 0;
let j = 0;
return (
<div className="background">
<div className="pie-parent">
{display.map((elem) => (
<div
className="pie-button"
style={getPieStyle(i += 1)}
key={elem.name}
onClick={
elem.items ? () => updateDisplay(elem.name) : () => showWindow()
}
ref={ref}
>
<pre
className="pie-button--text"
style={getPieTextStyle(j += 1)}
>
{elem.name}
</pre>
</div>
))}
</div>
</div>
);
});
export default PieDisplay;
CSS:
.background {
position: relative;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: var(--white);
font-size: 48px;
width: 320px;
height: 320px;
padding: 20px;
border-radius: 50rem;
box-shadow: 0px 0px 30px 10px rgba(255, 255, 255, 0.2) inset, 0px 0px 30px 10px rgba(255, 255, 255, 0.2);
}
.pie-parent {
position: absolute;
box-shadow: 0px 0px 30px 10px rgba(255, 255, 255, 0.2) inset, 0px 0px 30px 10px rgba(255, 255, 255, 0.2);
padding: 0;
margin: 1em auto;
width: 225%;
height: 225%;
border-radius: 50%;
overflow: hidden;
}
.pie-button {
overflow: hidden;
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 50%;
transform-origin: 0% 100%;
z-index: 2;
}
.pie-button--text {
position: absolute;
left: -100%;
width: 200%;
height: 200%;
text-align: center;
padding-top: 50px;
}
.pie-button:hover {
background-color: grey;
cursor: pointer;
}
.pie-button:nth-child(1) {
background-color: red;
}
.pie-button:nth-child(2) {
background-color: blue;
}
.pie-button:nth-child(3) {
background-color: yellow;
}
.pie-button:nth-child(4) {
background-color: green;
}
测试数据:
export const dataFlow = [
{
name: 'Contact',
},
{
name: 'About',
},
{
name: 'Projects',
items: [
{
name: "Test1",
},
{
name: 'Test2',
},
{
name: 'Test3',
},
{
name: 'Test4',
},
{
name: 'Test5'
},
]
},
{
name: "Professional\nExperience",
items: [
{
name: 'Test1',
},
{
name: 'Test2',
},
{
name: 'Test3',
}
]
},
];
我能够根据数组的长度应用 skewY 和旋转值的正确组合来解决我的问题。基本上,skewY 值会根据要显示的元素数量发生巨大变化。下面是我想出的table:
N Elements
SkewY
12
-60
11
-55
10
-50
9
-45
8
-40
7
-35
6
-30
5
-15
4
-0
3
30
3 = 30,比例 1.2 ~ 文本 -30,比例 0.8
对于 3 个元素,我需要应用比例 属性 来填补缺失的 space。父元素增加了大小,文本需要减少相同的数量,以便文本保持居中。
需要记住的一点是,为元素设置的 skewY 需要与文本相反。如果给元素 skewY 30deg,文本需要有 skewY -30deg。为了使文本在元素中间居中,我使用了旋转 属性。此外,文本需要先有 skewY,然后是旋转 属性。父元素首先有旋转,然后是 skewY 属性.
我无法显示 2 个元素,因为这需要在 90 度上有 skewY,然后元素消失。我想应该有一种显示它们的方法,但我还没有弄清楚。
下面是最终代码:
import React, { useState, forwardRef } from "react";
import {dataFlow} from './database'
const PieDisplay = forwardRef(({ showWindow }, ref) => {
const [display, setDisplay] = useState(dataFlow.map((item) => item));
const getPieStyle = (index) => {
let pieButtonStyle = {
transform: "",
};
const rotX = (360 / display.length) * index; //get the rotation for each element
if (display.length === 3) pieButtonStyle.transform = `rotate(${rotX}deg) skewY(30deg) scale(1.2)`;
else if (display.length === 4) pieButtonStyle.transform = `rotate(${rotX}deg) skewY(0deg)`;
else if (display.length === 5) pieButtonStyle.transform = `rotate(${rotX}deg) skewY(-15deg)`;
else if (display.length > 5) {
const skewY = (5 * display.length) * -1 //set the skewY in intervals of 5 for 6+ elements
pieButtonStyle.transform = `rotate(${rotX}deg) skewY(${skewY}deg)`;}
return pieButtonStyle;
};
const getPieTextStyle = () => {
let pieButtonStyle = {
transform: "",
};
if (display.length === 3) pieButtonStyle.transform = `skewY(-30deg) rotate(55deg) scale(0.8)`;
else if (display.length === 4) pieButtonStyle.transform = `skewY(0deg) rotate(45deg)`;
else if (display.length === 5) pieButtonStyle.transform = `skewY(15deg) rotate(35deg)`;
else if (display.length > 5) {
const skewY = (5 * display.length)
const rotX = 30 / (skewY / 30); //get the proper rotation based on skewY
pieButtonStyle.transform = `skewY(${skewY}deg) rotate(${rotX}deg)`;
}
return pieButtonStyle;
};
let i = 0;
return (
<ul className="pie-parent">
{display.map((elem) => (
<li
className="pie-button"
style={getPieStyle(i += 1)}
key={elem.name}
onClick={
elem.items ? () => updateDisplay(elem.name) : () => showWindow()
}
ref={ref}
>
<pre className="pie-button--text" style={getPieTextStyle()}>
{elem.name}
</pre>
</li>
))}
</ul>
);
});
export default PieDisplay;
我正在创建一个使用圆形作为布局的动态阵列显示。数组的每个元素将占据圆内 space 的相同部分。如果数组中有 3 个元素,则需要在 3 个相等的 space 秒内填满 100% 的圆。我已经让它工作到显示 4 个相同大小的元素的程度。我需要帮助找出一个公式来根据数组的大小调整正方形的大小。
我的方法是单独创建每个元素。我需要控制圆圈内的每个 child,同时将 child 内的文本居中。我也乐于接受新想法,我觉得代码有点乱。如果您有更清洁的方法,请分享!
下面是我的代码:
import React, { useState, forwardRef } from "react";
import {dataFlow} from './database'
const PieDisplay = forwardRef(({ showWindow }, ref) => {
const [display, setDisplay] = useState(dataFlow.map((item) => item));
const getPieStyle = (index) => {
let pieButtonStyle = {
transform: "",
};
const rotX = (360 / display.length) * index; //set the angle for each element of the pie
pieButtonStyle.transform = `rotate(${rotX}deg) skewY(0deg)`;
return pieButtonStyle;
};
const getPieTextStyle = (index) => {
let pieButtonStyle = {
transform: "",
};
const rotX = 360 / display.length / 2; //set the angle for each element's text of the pie
pieButtonStyle.transform = `rotate(${rotX}deg) skewY(0deg)`;
return pieButtonStyle;
};
let i = 0;
let j = 0;
return (
<div className="background">
<div className="pie-parent">
{display.map((elem) => (
<div
className="pie-button"
style={getPieStyle(i += 1)}
key={elem.name}
onClick={
elem.items ? () => updateDisplay(elem.name) : () => showWindow()
}
ref={ref}
>
<pre
className="pie-button--text"
style={getPieTextStyle(j += 1)}
>
{elem.name}
</pre>
</div>
))}
</div>
</div>
);
});
export default PieDisplay;
CSS:
.background {
position: relative;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
color: var(--white);
font-size: 48px;
width: 320px;
height: 320px;
padding: 20px;
border-radius: 50rem;
box-shadow: 0px 0px 30px 10px rgba(255, 255, 255, 0.2) inset, 0px 0px 30px 10px rgba(255, 255, 255, 0.2);
}
.pie-parent {
position: absolute;
box-shadow: 0px 0px 30px 10px rgba(255, 255, 255, 0.2) inset, 0px 0px 30px 10px rgba(255, 255, 255, 0.2);
padding: 0;
margin: 1em auto;
width: 225%;
height: 225%;
border-radius: 50%;
overflow: hidden;
}
.pie-button {
overflow: hidden;
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 50%;
transform-origin: 0% 100%;
z-index: 2;
}
.pie-button--text {
position: absolute;
left: -100%;
width: 200%;
height: 200%;
text-align: center;
padding-top: 50px;
}
.pie-button:hover {
background-color: grey;
cursor: pointer;
}
.pie-button:nth-child(1) {
background-color: red;
}
.pie-button:nth-child(2) {
background-color: blue;
}
.pie-button:nth-child(3) {
background-color: yellow;
}
.pie-button:nth-child(4) {
background-color: green;
}
测试数据:
export const dataFlow = [
{
name: 'Contact',
},
{
name: 'About',
},
{
name: 'Projects',
items: [
{
name: "Test1",
},
{
name: 'Test2',
},
{
name: 'Test3',
},
{
name: 'Test4',
},
{
name: 'Test5'
},
]
},
{
name: "Professional\nExperience",
items: [
{
name: 'Test1',
},
{
name: 'Test2',
},
{
name: 'Test3',
}
]
},
];
我能够根据数组的长度应用 skewY 和旋转值的正确组合来解决我的问题。基本上,skewY 值会根据要显示的元素数量发生巨大变化。下面是我想出的table:
N Elements | SkewY |
---|---|
12 | -60 |
11 | -55 |
10 | -50 |
9 | -45 |
8 | -40 |
7 | -35 |
6 | -30 |
5 | -15 |
4 | -0 |
3 | 30 |
3 = 30,比例 1.2 ~ 文本 -30,比例 0.8
对于 3 个元素,我需要应用比例 属性 来填补缺失的 space。父元素增加了大小,文本需要减少相同的数量,以便文本保持居中。
需要记住的一点是,为元素设置的 skewY 需要与文本相反。如果给元素 skewY 30deg,文本需要有 skewY -30deg。为了使文本在元素中间居中,我使用了旋转 属性。此外,文本需要先有 skewY,然后是旋转 属性。父元素首先有旋转,然后是 skewY 属性.
我无法显示 2 个元素,因为这需要在 90 度上有 skewY,然后元素消失。我想应该有一种显示它们的方法,但我还没有弄清楚。
下面是最终代码:
import React, { useState, forwardRef } from "react";
import {dataFlow} from './database'
const PieDisplay = forwardRef(({ showWindow }, ref) => {
const [display, setDisplay] = useState(dataFlow.map((item) => item));
const getPieStyle = (index) => {
let pieButtonStyle = {
transform: "",
};
const rotX = (360 / display.length) * index; //get the rotation for each element
if (display.length === 3) pieButtonStyle.transform = `rotate(${rotX}deg) skewY(30deg) scale(1.2)`;
else if (display.length === 4) pieButtonStyle.transform = `rotate(${rotX}deg) skewY(0deg)`;
else if (display.length === 5) pieButtonStyle.transform = `rotate(${rotX}deg) skewY(-15deg)`;
else if (display.length > 5) {
const skewY = (5 * display.length) * -1 //set the skewY in intervals of 5 for 6+ elements
pieButtonStyle.transform = `rotate(${rotX}deg) skewY(${skewY}deg)`;}
return pieButtonStyle;
};
const getPieTextStyle = () => {
let pieButtonStyle = {
transform: "",
};
if (display.length === 3) pieButtonStyle.transform = `skewY(-30deg) rotate(55deg) scale(0.8)`;
else if (display.length === 4) pieButtonStyle.transform = `skewY(0deg) rotate(45deg)`;
else if (display.length === 5) pieButtonStyle.transform = `skewY(15deg) rotate(35deg)`;
else if (display.length > 5) {
const skewY = (5 * display.length)
const rotX = 30 / (skewY / 30); //get the proper rotation based on skewY
pieButtonStyle.transform = `skewY(${skewY}deg) rotate(${rotX}deg)`;
}
return pieButtonStyle;
};
let i = 0;
return (
<ul className="pie-parent">
{display.map((elem) => (
<li
className="pie-button"
style={getPieStyle(i += 1)}
key={elem.name}
onClick={
elem.items ? () => updateDisplay(elem.name) : () => showWindow()
}
ref={ref}
>
<pre className="pie-button--text" style={getPieTextStyle()}>
{elem.name}
</pre>
</li>
))}
</ul>
);
});
export default PieDisplay;