在我的网络应用程序中有一个汉堡包制作部分。用户从一个只有顶部小圆面包和底部小圆面包的汉堡包开始。用户可以从各种“浇头”中进行选择以添加到汉堡包中,然后显示更改。我有顶部面包、底部面包、生菜、肉饼、奶酪等的 SVG 文件,我希望在运行时动态地将它们组合(堆叠)在一起。我目前能够动态堆叠它们,但我希望某些 SVG 文件与其他文件重叠。
我会告诉你我的意思
在上面你可以看到汉堡包开始时什么都没有。 反应 DOM 看起来像
<img src = {topBunSVG}> </img>
<img src = {buttonBunSVG}> </img>
让我们点击番茄来添加它。
现在您可以看到番茄现在位于两个面包之间。 DOM 现在看起来像这样
<img src = {topBunSVG}> </img>
<img src = {tomatoSVG}> </img>
<img src = {buttonBunSVG}> </img>
添加馅饼也是一样
DOM 现在看起来像这样
<img src = {topBunSVG}> </img>
<img src = {pattySVG}> </img>
<img src = {tomatoSVG}> </img>
<img src = {buttonBunSVG}> </img>
让我们尝试更复杂的东西,比如加些奶酪
你可以看到奶酪与其他成分重叠
DOM 现在看起来像这样
<img src = {topBunSVG}> </img>
<img src = {cheeseSVG}> </img>
<img src = {pattySVG}> </img>
<img src = {tomatoSVG}> </img>
<img src = {buttonBunSVG}> </img>
然而,React 实际上是这样显示的:
这不是我想要的。
如何让它们正确堆叠?
此外,当我将窗口变小时,它看起来像这样: Responsive component resized
这是组件的相关代码:
import React, { useEffect, useReducer, useState } from "react";
import "./makeHamburger.scss";
import bottomBun from "../../assets/foodParts/hamburger/bottombun.svg"
import cheese from "../../assets/foodParts/hamburger/cheese.svg"
import lettuce from "../../assets/foodParts/hamburger/lettuce.svg"
import patty from "../../assets/foodParts/hamburger/patty.svg"
import tomato from "../../assets/foodParts/hamburger/tomato.svg"
import topBun from "../../assets/foodParts/hamburger/topbun.svg"
const parts = {
topBun: {
view: topBun,
price: 1.5,
macros: {
carbs: 1,
protein: 0,
fiber: 0,
fat: 0,
},
},
bottomBun: {
view: bottomBun,
price: 1.5,
macros: {
carbs: 1,
protein: 0,
fiber: 0,
fat: 0,
},
},
patty: {
view: patty,
price: 5,
macros: {
carbs: 0,
protein: 1,
fiber: 0,
fat: 0,
},
},
cheese: {
view: cheese,
price: 1,
macros: {
carbs: 0,
protein: 0,
fiber: 0,
fat: 1,
},
},
lettuce: {
view: lettuce,
price: 2,
macros: {
carbs: 0,
protein: 0,
fiber: 1,
fat: 0,
},
},
tomato: {
view: tomato,
price: 2,
macros: {
carbs: 0,
protein: 0,
fiber: 1,
fat: 0,
},
},
}
const initialState = { contents: [parts.topBun, parts.bottomBun] };
function reducer(state, action) {
let tmp = JSON.parse(JSON.stringify(state))
switch (action.type) {
case "addPatty":
tmp.contents.splice(1, 0, parts.patty)
return {
contents: tmp.contents
}
break;
case "addCheese":
tmp.contents.splice(1, 0, parts.cheese)
return {
contents: tmp.contents
}
break;
case "addLettuce":
tmp.contents.splice(1, 0, parts.lettuce)
return {
contents: tmp.contents
}
break;
case "addTomato":
tmp.contents.splice(1, 0, parts.tomato)
return {
contents: tmp.contents
}
break;
case "deletePartsById":
if ((action.payload == 0) || (action.payload == (state.contents.length - 1))) {
return state;
}
tmp.contents.splice(action.payload, 1)
return {
contents: tmp.contents
}
break;
default:
break;
}
}
const MakeHamburger = ({recieveFood}) => {
const [state, dispatch] = useReducer(reducer, initialState);
const getTotalPrice = () => {
let price = 0;
state.contents.forEach((item,index) => {
price += item.price
})
return price;
}
const getTotalCarbs = () => {
let carbs = 0;
state.contents.forEach((item,index) => {
carbs += item.macros.carbs
})
return carbs;
}
const getTotalFat = () => {
let fat = 0;
state.contents.forEach((item,index) => {
fat += item.macros.fat
})
return fat;
}
const getTotalFiber = () => {
let fiber = 0;
state.contents.forEach((item,index) => {
fiber += item.macros.fiber
})
return fiber;
}
const getTotalProtein = () => {
let protein = 0;
state.contents.forEach((item,index) => {
protein += item.macros.protein
})
return protein;
}
const getTotalMacros = () => {
return{
carbs: getTotalCarbs(),
protein: getTotalProtein(),
fiber: getTotalFiber(),
fat: getTotalFat(),
}
}
return (
<div id="food" className="container">
<h1>Let's make Max a burger</h1>
<p>Select what goes on the burger</p>
<div className="container">
<div className="row justify-content-center">
<div className="col-6">
<div className="row">
<div className="col">
<button className="transparentButton" onClick={() => { dispatch({ type: 'addCheese' }) }}>
<img className="selectPartImg" src={cheese}></img>
</button>
</div>
<div className="col">
<p>Cheese</p>
</div>
</div>
<div className="row mt-3">
<div className="col">
<button className="transparentButton" onClick={() => { dispatch({ type: 'addLettuce' }) }}>
<img className="selectPartImg" src={lettuce}></img>
</button>
</div>
<div className="col">
<p>Lettuce</p>
</div>
</div>
<div className="row mt-3">
<div className="col">
<button className="transparentButton" onClick={() => { dispatch({ type: 'addPatty' }) }}>
<img className="selectPartImg" src={patty}></img>
</button>
</div>
<div className="col"><p>Patty</p></div>
</div>
<div className="row mt-3">
<div className="col">
<button className="transparentButton" onClick={() => { dispatch({ type: 'addTomato' }) }} >
<img className="selectPartImg" src={tomato}></img>
</button>
</div>
<div className="col"><p>Tomato</p></div>
</div>
</div>
<div className="col-6 ">
{state.contents.map(function (part, i) {
return <div className="row no-gutters">
<div className="col">
<button className="transparentButton" onClick={() => { dispatch({ type: 'deletePartsById', payload: i }) }} >
<img className="partImg" src={part.view}></img>
</button>
</div>
</div>
})}
<h1>Total price: {getTotalPrice()}</h1>
<p>({getTotalCarbs() ? getTotalCarbs() + " carbs" : null}{getTotalFat() ? ", " + getTotalFat() + " fat" : null}
{getTotalFiber() ? ", " + getTotalFiber() + " fiber" : null}{getTotalProtein() ? ", " + getTotalProtein() + " protein" : null})</p>
<button onClick = {() => {recieveFood(getTotalMacros())}}>Feed this burger</button>
</div>
</div>
</div>
</div>
);
};
export default MakeHamburger;
答案 0 :(得分:0)
如果某一层的高度与图片的高度不一致,则需要指定每一层的高度。 (图像中不存在有关所需高度的信息)。
import React, { useEffect, useState } from 'react';
export const Patties = (props) => {
return (<>
{ [...props.patties].reverse().map( function(patty, index){
return <>
<path d={ 'M 0 ' + (60 - index * 20) + ' h 100 l -50 30 z' } fill={ patty.color } />
</>
})}
</>);
};
export const Hamburger = (props) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
width={ 200 }
height={ 200 }
viewBox={ [ 0, 0, 100, 100 ].join(' ') }
>
<Patties patties={[
{ color: '#fa0' },
{ color: '#0a0' },
{ color: '#c20' },
]}/>
</svg>
);
};
export const Hamburger2 = (props)=>{
const patties = [
{ url: imgUrlA },
{ url: imgUrlB },
{ url: imgUrlC },
];
return (<div style={{ position: 'relative' }}>
{ patties.reverse().map( function(patty, index){
return <img
src={ patty.url }
style={{ position: 'absolute', top: 60 - index * 20 }}
/>;
})}
</div>);
};
答案 1 :(得分:0)
感谢大家的建议答案,我设法用这个代码片段解决了这个程序:
const drawParts = () => {
let parts = [];
let positionOffSet = 0;
let z = state.contents.length;
state.contents.map(function (part, index) {
parts.push(
<div className="row no-gutters" style={{ position: 'relative', zIndex: z, top: positionOffSet }}>
<div className="col">
<button className="transparentButton" onClick={() => { dispatch({ type: 'deletePartsById', payload: index }) }} >
<img className="partImg" src={part.view}></img>
</button>
</div>
</div>
)
if(part.view == cheese){
positionOffSet -= 90;
z--;
}
if(part.view == lettuce){
positionOffSet -= 15;
z--;
}
})
return parts;
}
基本上有一个全局偏移量和 z 值变量,每次出现奶酪或生菜时都会增加。偏移量和 z 值应用于所有元素。