我一直在尝试重新创建TypeForm用于创建问题的类似 UI。
如果您在他们的编辑器中注意到,当您使用箭头时,右侧会像一页一样上下滚动。
对于我的应用程序,我希望它以相同的方式滚动,但通过单击左侧的问题来代替
它几乎可以工作,但是当第一次以相反的顺序单击问题时,动画中有一个小错误 - 它重叠 - 这就是问题所在。我正在努力使上下动画的问题永远不会相互重叠,你能帮忙吗?
目前它的工作方式是根据您是否选择“上一个”问题来更改动画的initial
,animate
和值exit
这是一个代码框的链接,因为我无法让下面的代码片段正确运行......
import React, { useState, useEffect, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion"
import uuid from 'uuid/v4';
import './styles.css';
const App = () => {
const [display, setDisplay] = useState(false);
const [questions, setQuestions] = useState([{id:uuid(), q: '', active:true}]);
const [isPrevious, setIsPrevious] = useState(false);
const [prev, setPrev] = useState(0);
const toggleMenu = () => setDisplay(!display);
const selectType = ()=> {
setDisplay(false);
setPrev(questions.findIndex(x=>x.active === true))
setQuestions(prevState => {
let updated = prevState.map(question=>{
question.active = false;
return question
})
updated.push({id:uuid(), q: '', active:true})
return updated
})
}
useEffect(()=>{
setPrev(questions.findIndex(x=>x.active === true))
},[questions])
const updateQuestions = ({id, q}) => setQuestions(prevState => prevState.map((question, index) => {
question.active = false;
if(question.id === id) {
console.log({'prev': prev, 'current': index, 'isPrev?': isPrevious})
if(prev > index) {
setIsPrevious(true)
} else {
setIsPrevious(false)
}
question.q = q
question.active = true
}
return question
}))
const removeQuestion = (id) => setQuestions(prevState => prevState.filter(question => question.id !== id))
return (
<>
<Navbar />
<main className="flex items-stretch justify-between">
<div className="w-1/2">
{questions.map(question=>
<Qshort key={question.id} removeQuestion={removeQuestion} data={question} updateQuestion={updateQuestions}/>
)}
<div className="relative mt-10 px-4">
<button onClick={toggleMenu} className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Add your first question</button>
<div className={(display ? "flex " : "hidden ") + "absolute bg-white p-3 flex-col shadow-md w-1/2 rounded-lg"}>
<button onClick={() => selectType("1")} className="my-3 mt-0 p-3 hover:bg-gray-200 rounded">Short question</button>
</div>
</div>
</div>
<div className="rightSide relative w-1/2 bg-gray-200 flex flex-col items-center justify-center">
<AnimatePresence finishBeforeExit>
{questions.length &&
<motion.div
transition={{ duration: 1, type: "tween" }}
key={questions[questions.findIndex(x=>x.active)].id}
initial={{opacity:0, bottom:isPrevious ? '100%' : '-50%'}}
animate={{opacity:1, bottom:'50%'}}
exit={{opacity:0, bottom:isPrevious ? '-20%' : '100%'}}
className="absolute flex flex-col w-64 w-2/3"
>
<p className="text-2xl pl-3 text-gray-600">{questions[questions.findIndex(x=>x.active)].q}</p>
<input
placeholder="Type your answer here...."
type="text"
className="mt-3 w-full p-3 bg-transparent border-b-4 text-2xl"
/>
</motion.div>
}
</AnimatePresence>
{questions.length &&
<button className="absolute mb-3 mr-3 bottom-0 right-0 bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-6 rounded">Next step</button>
}
</div>
</main>
</>
);
};
const Qshort = ({updateQuestion,removeQuestion,data}) => {
return (
<div className={(data.active ? 'border-green-500 ':'border-transparent')+" border relative bg-gray-300 py-8 pb-12 pl-4 mb-2"}>
<input
onFocus={(e)=>updateQuestion({id:data.id, q:e.target.value})}
onChange={(e)=>updateQuestion({id:data.id, q:e.target.value})}
type="text"
className="w-full bg-transparent"
placeholder="Type your question here..."
/>
<button onClick={()=>removeQuestion(data.id)} className="absolute bottom-0 right-0 mr-3 mb-3 text-xs text-blue-500 hover:text-blue-700">Remove</button>
</div>
);
};
const Navbar = () => {
return (
<nav className="relative flex items-center justify-between flex-wrap bg-blue-500 p-6">
<div className="flex items-center flex-shrink-0 text-white mr-6">
<span className="font-semibold text-xl tracking-tight">Aquire</span>
</div>
<div className="block lg:hidden">
<button className="flex items-center px-3 py-2 border rounded text-teal-200 border-teal-400 hover:text-white hover:border-white">
<svg
className="fill-current h-3 w-3"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<title>Menu</title>
<path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" />
</svg>
</button>
</div>
</nav>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/uuid.v4@1.0.0/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/framer-motion@0.6.6/dist/framer-motion.js"></script>
<div id="root"></div>