我已经为这个问题解决了2天,我正在尝试实现连续的垂直文本滚动,但是由于某些我不知道的原因,react返回一个数字而不是我的数组对象(在我记录了输出之后以查看我的代码出了什么问题)(在第二次迭代中)(因为该数组每隔一段时间就会不断更新)。作为记录,这最初是在Angular JS应用程序中实现的,但是我试图将其转换为与useEffect()
和useState()
反应以更新数组中的更改。
以下是我到目前为止所做的:
const Skills = () => {
let skillWrap = useRef();
let [activeSkills, setActiveSkills] = useState([]);
console.log(activeSkills);
console.log(typeof activeSkills);
let sMax = totalSkills.length - 1; // 0 -> 19
let activeStart = Math.floor(Math.random() * (sMax + 1));
let activeEnd = activeStart === 0 ? sMax : activeStart - 1;
for (let e = activeStart; e <= sMax; e++) {
setActiveSkills(activeSkills.push(totalSkills[e]));
}
if (activeStart !== 0) {
for (let s = 0; s <= activeEnd; s++) {
setActiveSkills(activeSkills.push(totalSkills[s]));
}
}
let scrollDis = 0,
scrollingDown = false,
scrollingUp = false,
scrollingDownSelf = false,
scrollingUpSelf = false,
scrollCatchInterval = 40,
scrollDirection = "up",
hasScrolledRecently = false;
const wheelEventHandler = e => {
let skillFocused = skillWrap.current.childNodes[19];
skillFocused.classList.remove("active");
function animateScroll(scrollDis, callback) {
let curLeftTop = scrollDis * 8,
curLeftFinal = scrollDis * 4;
tween(skillWrap.current, -curLeftFinal, curLeftTop, 1, callback);
}
function scrollUp() {
setTimeout(() => {
for (let su = 0; su < scrollDis; su++) {
activeEnd--;
activeStart--;
if (activeEnd < 0) activeEnd = 19;
if (activeStart < 0) activeStart = 19;
/*setActiveSkills(activeSkills.unshift(totalSkills[activeStart]));
setActiveSkills(activeSkills.pop());*/
activeSkills.unshift(totalSkills[activeStart]);
activeSkills.pop();
}
skillFocused.classList.add("active");
skillWrap.current.style.transform = "none";
scrollDis = 0;
scrollingUp = false;
scrollingUpSelf = false;
if (e.deltaZ === 0) {
setTimeout(() => {
hasScrolledRecently = false;
}, 3000);
}
}, 0);
}
function scrollDown() {
setTimeout(() => {
for (let sd = 0; sd < Math.abs(scrollDis); sd++) {
activeEnd++;
activeStart++;
if (activeEnd > 19) activeEnd = 0;
if (activeStart > 19) activeStart = 0;
/*setActiveSkills(activeSkills.push(totalSkills[activeEnd]));
setActiveSkills(activeSkills.shift());*/
activeSkills.push(totalSkills[activeEnd]);
activeSkills.shift();
}
skillFocused.classList.add("active");
skillWrap.style.transform = "none";
scrollDis = 0;
scrollingDown = false;
scrollingDownSelf = false;
if (e.deltaZ === 0) {
setTimeout(() => {
hasScrolledRecently = false;
}, 3000);
}
}, 0);
}
if (
(e.deltaY === 100 || e.deltaY === 3) &&
!scrollingUp &&
!scrollingDownSelf
) {
// (scroll down) add skill to bottom & remove skill from top
scrollDirection = "down";
scrollDis--;
scrollingDown = true;
if (e.deltaZ === 0) hasScrolledRecently = true;
let scd = scrollDis;
setTimeout(() => {
if (scrollDis === scd) {
if (scrollDis < -6) scrollDis = -6;
scrollingDownSelf = true;
animateScroll(scrollDis, scrollDown);
}
}, scrollCatchInterval);
} else if (
(e.deltaY === -100 || e.deltaY === -3) &&
!scrollingDown &&
!scrollingUpSelf
) {
// (scroll up) add skill to top & remove skill from bottom
scrollDirection = "up";
scrollDis++;
scrollingUp = true;
if (e.deltaZ === 0) hasScrolledRecently = true;
let scu = scrollDis;
setTimeout(() => {
if (scrollDis === scu) {
if (scrollDis > 5) scrollDis = 5;
scrollingUpSelf = true;
animateScroll(scrollDis, scrollUp);
}
}, scrollCatchInterval);
}
};
function tween(o, x, y, durationSecs, onComplete) {
let fps = 30,
count = 0,
stopAt = fps * durationSecs,
easef = Quad_easeInOut;
let f = function() {
count++;
if (count >= stopAt) {
tween_stop(o);
if (onComplete) onComplete();
} else {
tween_setProperty(
o,
easef(count, 0, x, stopAt),
easef(count, 0, y, stopAt)
);
}
};
clearInterval(o._tween_int);
o._tween_int = setInterval(f, (durationSecs * 1000) / fps);
}
function tween_stop(o) {
clearInterval(o._tween_int);
}
function tween_setProperty(o, x, y) {
o.style.cssText += ";transform:translate3d(" + x + "vw," + y + "vh,0);";
}
function Quad_easeInOut(t, b, c, d) {
if ((t /= d / 2) < 1) return (c / 2) * t * t * t * t + b;
return (-c / 2) * ((t -= 2) * t * t * t - 2) + b;
}
useEffect(() => {
/*console.log(activeSkills);*/
setTimeout(() => {
skillWrap.current.childNodes[19].classList.add("active");
}, 2000);
window.addEventListener("wheel", wheelEventHandler);
function constantScroll() {
// prevents scrolling while changing views
setTimeout(function() {
// emulate scrolling of the skill list
let scrollEvent = new WheelEvent("wheel", {
deltaY: scrollDirection === "up" ? -100 : 100,
deltaZ: 1 // used to differentiate between user scroll / programmatic scroll
});
if (!hasScrolledRecently) {
// 3 scroll events are dispatched to mirror scrolling of 3 skills
for (let r = 0; r < 3; r++) {
window.dispatchEvent(scrollEvent);
}
}
constantScroll();
}, 3000);
}
// wait 3 seconds before issuing first scroll
setTimeout(function() {
constantScroll();
}, 2000);
return () => {
window.removeEventListener("wheel", wheelEventHandler);
console.log("Skills Component will unmount");
};
}, [activeSkills]);
return (
<div>
<div className="view skills active active-f">
<div className="header-container skills">
<div className="header-title-wrap">
<div className="cover" />
<h1 className="header big first">My</h1>
<h1 className="header big last">Skillsset</h1>
</div>
<div className="header-info-wrap">
<div className="header-content-body skill-one">
<div className="line-left" />
<p className="header body about-one">
The core of my skill set largely surrounds the MERN{" "}
<strong>stack</strong>, to achieve both a clear and dynamic user
experience. I also have some experience with mobile integration
(Android and iOS). Strengthening my grasp of the mobile app
development space is one of my primary goals for the near
future.
</p>
</div>
</div>
</div>
<div className="skill-container active active-f">
<div className="skill-wrap">hey</div>
</div>
</div>
<div className="skill-container active-f active">
<div ref={skillWrap} className="skill-wrap">
{console.log(activeSkills)}
{activeSkills.map((skill, i) => (
<div key={i} className="skill">
{skill}
</div>
))}
</div>
</div>
</div>
);
};
下面是https://codesandbox.io/页面,查看我到目前为止所做的事情,以及我正在尝试用React实现的Angular JS实现的链接。
我的React实现(来自技能路线):https://codesandbox.io/s/shy-http-jlrle
原始Angular实施(技能路线):https://codesandbox.io/s/github/eazylaykzy/portfolio-ex
我真的很感激能帮助我使它生效。
答案 0 :(得分:0)
就像我的评论中提到的那样抽象第一部分,您可以编写自己的钩子并按原样使用
import React, { useMemo } from 'react';
// How to shuffle an array
// https://stackoverflow.com/questions/2450954/how-to-randomize-shuffle-a-javascript-array
function shuffle(array) {
const newArray = [...array];
for (let i = newArray.length - 1; i > 0; i -= 1) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
}
return newArray;
}
function useActiveSkills(skills) {
return useMemo(() => shuffle(skills), [skills]);
}
function Component() {
const activeSkills = useActiveSkills();
return (
<>
{activeSkills.map((skill) => (
<p>{skill.name}</p>
))}
</>
);
}