英文:
How to animate overflowing text to scroll to the end of the text when hovering and animate back to original position when mouse leaves?
问题
我正在尝试在悬停在具有溢出文本的容器上时实现滚动文本的动画效果。目前,当鼠标悬停在容器上时,动画会滚动到文本的末尾,但当鼠标离开时,文本突然返回到原始位置。我希望在鼠标离开时也能实现回到原始位置的动画效果。
import { useEffect, useRef, useState } from 'react';
import classes from './test.module.css';
const Test = () => {
const textRef = useRef(null);
const containerRef = useRef(null);
const [isHovered, setIsHovered] = useState(false);
const [isOverflowing, setIsOverflowing] = useState(false);
const onMouseEnter = () => {
setIsHovered(true);
};
const onMouseLeave = () => {
setIsHovered(false);
};
useEffect(() => {
const textWidth = textRef.current.offsetWidth;
const containerWidth = containerRef.current.offsetWidth;
if (textWidth > containerWidth) {
setIsOverflowing(true);
}
}, []);
return (
<div>
<div
ref={containerRef}
className={classes.animated}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
>
<h3
className={isHovered && isOverflowing ? classes.textAnimated : classes.text}
ref={textRef}
>
This is some very very very long text
</h3>
</div>
</div>
);
};
export default Test;
.animated {
margin: 200px;
position: relative;
white-space: nowrap;
max-width: 300px;
width: 100%;
overflow: hidden;
background: #0c0c0c;
display: inline-block;
position: relative;
border: 1px solid white;
}
.textAnimated {
color: #fff;
animation: textScroll 3s linear forwards;
display: inline-block;
position: relative;
}
.text {
color: #fff;
display: inline-block;
position: relative;
}
@keyframes textScroll {
0% {
transform: translateX(0);
left: 0;
}
10% {
transform: translateX(0);
left: 0;
}
90% {
transform: translateX(calc(-100%));
left: 100%;
}
100% {
transform: translateX(calc(-100%));
left: 100%;
}
}
英文:
I am trying to animate scrolling text when hovering over a container that has overflowing text. Right now I have the animation scrolling to the end of the text when hovering over the container, but when the mouse leaves, the text just suddenly goes back to original position. I want it to also animate back to original position when the mouse leaves.
import {useEffect, useRef, useState} from 'react';
import classes from './test.module.css';
const Test = () => {
const textRef = useRef(null);
const containerRef = useRef(null);
const [isHovered, setIsHovered] = useState(false);
const [isOverflowing, setIsOverflowing] = useState(false);
const onMouseEnter = () => {
setIsHovered(true);
};
const onMouseLeave = () => {
setIsHovered(false);
};
useEffect(() => {
const textWidth = textRef.current.offsetWidth;
const containerWidth = containerRef.current.offsetWidth;
if (textWidth > containerWidth) {
setIsOverflowing(true);
}
}, []);
return (
<div>
<div ref={containerRef} className={classes.animated} onMouseEnter={onMouseEnter} onMouseLeave={onMouseLeave}>
<h3 className={isHovered && isOverflowing ? classes.textAnimated : classes.text} ref={textRef}>
This is some very very very long text
</h3>
</div>
</div>
);
};
export default Test;
.animated {
margin: 200px;
position: relative;
white-space: nowrap;
max-width: 300px;
width: 100%;
overflow: hidden;
background: #0c0c0c;
display: inline-block;
position: relative;
border: 1px solid white;
}
.textAnimated {
color: #fff;
animation: textScroll 3s linear forwards;
display: inline-block;
position: relative;
}
.text {
color: #fff;
display: inline-block;
position: relative;
}
@keyframes textScroll {
0% {
transform: translateX(0);
left: 0;
}
10% {
transform: translateX(0);
left: 0;
}
90% {
transform: translateX(calc(-100%));
left: 100%;
}
100% {
transform: translateX(calc(-100%));
left: 100%;
}
}
答案1
得分: 0
请考虑使用 transition
而不是 animation
。在悬停时,transition
对于在两个状态之间进行视觉插值非常有用,正如此处的情况一样:
<!-- begin snippet: js hide: false console: false babel: true -->
<!-- language: lang-js -->
const { useEffect, useRef, useState } = React;
const Test = () => {
const textRef = useRef(null);
const containerRef = useRef(null);
const [isOverflowing, setIsOverflowing] = useState(false);
useEffect(() => {
const textWidth = textRef.current.offsetWidth;
const containerWidth = containerRef.current.offsetWidth;
if (textWidth > containerWidth) {
setIsOverflowing(true);
}
}, []);
return (
<div>
<div ref={containerRef} className="animated">
<h3 className={isOverflowing ? 'textAnimated' : 'text'} ref={textRef}>
This is some very very very long text
</h3>
</div>
</div>
);
};
ReactDOM.createRoot(document.getElementById('app')).render(<Test/>);
<!-- language: lang-css -->
.animated {
margin: 200px;
position: relative;
white-space: nowrap;
max-width: 100px;
width: 100%;
overflow: hidden;
background: #0c0c0c;
display: inline-block;
position: relative;
border: 1px solid white;
}
.textAnimated {
color: #fff;
display: inline-block;
position: relative;
left: 0;
transition: transform 3s linear, left 3s linear;
}
.animated:hover .textAnimated {
transform: translateX(-100%);
left: 100%;
}
.text {
color: #fff;
display: inline-block;
position: relative;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app"></div>
<!-- end snippet -->
注意:以上代码片段中包含了HTML、JavaScript和CSS部分。如果需要进一步的翻译,请提供具体的文本或指令。
英文:
Consider using transition
rather than animation
. transition
is useful for visual interpolation between two states, as would be the case here on hover:
<!-- begin snippet: js hide: false console: false babel: true -->
<!-- language: lang-js -->
const {useEffect, useRef, useState} = React;
const Test = () => {
const textRef = useRef(null);
const containerRef = useRef(null);
const [isOverflowing, setIsOverflowing] = useState(false);
useEffect(() => {
const textWidth = textRef.current.offsetWidth;
const containerWidth = containerRef.current.offsetWidth;
if (textWidth > containerWidth) {
setIsOverflowing(true);
}
}, []);
return (
<div>
<div ref={containerRef} className="animated">
<h3 className={isOverflowing ? 'textAnimated' : 'text'} ref={textRef}>
This is some very very very long text
</h3>
</div>
</div>
);
};
ReactDOM.createRoot(document.getElementById('app')).render(<Test/>);
<!-- language: lang-css -->
.animated {
margin: 200px;
position: relative;
white-space: nowrap;
max-width: 100px;
width: 100%;
overflow: hidden;
background: #0c0c0c;
display: inline-block;
position: relative;
border: 1px solid white;
}
.textAnimated {
color: #fff;
display: inline-block;
position: relative;
left: 0;
transition: transform 3s linear, left 3s linear;
}
.animated:hover .textAnimated {
transform: translateX(-100%);
left: 100%;
}
.text {
color: #fff;
display: inline-block;
position: relative;
}
<!-- language: lang-html -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app"></div>
<!-- end snippet -->
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论