所以基本上我已经创建了打字效果,但我只能得到数组中的第一个字符串才能工作。我想使用输入效果在新行中写出所有数组。我已在下面列出了JSX和CSS文件。 我还应该指出,这只是一个大项目的一部分,所以试图运行这个JSX和css不会工作
import React from 'react';
import "./Content.css";
const content =()=>{
const message =["WELCOME TO MY WORLD","THIS IS MY WEBSITE","I AM AT YOUR SERVICE"];
let i =0 ;
for(i=0; i<message.length;i++){
return(
<div className='background'>
<h1 className="typewriter">
{message[i]}
</h1>
</div>
)
}
}
export default content;
&#13;
background{
display: flex;
justify-content: center;
flex-wrap: wrap;
}
canvas{width: 60;
}
.typewriter {
text-align: center;
overflow: hidden;
border-right: .15em solid black;
color: white;
font-family: Courier New;
top:30%;
font-size: 40px;
white-space: nowrap;
letter-spacing: .30em;
animation:
typing 3.5s steps(30, end),
blink-caret .75s step-end infinite;
}
/* The typing effect */
@keyframes typing {
from { width:20% }
to { width: 50% }
}
@keyframes blink-caret {
from, to { border-color: transparent }
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
&#13;
答案 0 :(得分:2)
可以使其成为这样的类组件:
setMethod("plot",
signature(x = "stanfitExtended",
y = "missing" # <--------------What's New !!
),
definition = function(x){
foo(x)
}
)
class Typer extends React.Component {
static defaultProps = {
heading: '',
dataText: []
}
constructor(props) {
super(props);
this.state = {
text: '',
isDeleting: false,
loopNum: 0,
typingSpeed: 150
}
}
componentDidMount() {
this.handleType();
}
handleType = () => {
const { dataText } = this.props;
const { isDeleting, loopNum, text, typingSpeed } = this.state;
const i = loopNum % dataText.length;
const fullText = dataText[i];
this.setState({
text: isDeleting ? fullText.substring(0, text.length - 1) : fullText.substring(0, text.length + 1),
typingSpeed: isDeleting ? 30 : 150
});
if (!isDeleting && text === fullText) {
setTimeout(() => this.setState({ isDeleting: true }), 500);
} else if (isDeleting && text === '') {
this.setState({
isDeleting: false,
loopNum: loopNum + 1
});
}
setTimeout(this.handleType, typingSpeed);
};
render() {
return (
<h1>{ this.props.heading }
<span>{ this.state.text }</span>
<span id="cursor"/>
</h1>
);
}
}
ReactDOM.render(
<Typer
heading={'Things I want to type:'}
dataText={["WELCOME TO MY WORLD","THIS IS MY WEBSITE","I AM AT YOUR SERVICE"]}
/>,
document.getElementById('app')
);
@import url('https://fonts.googleapis.com/css?family=VT323');
body {
font-family: 'VT323', monospace;
background-color: #003B00;
padding: 1em 2em;
}
h1 {
color: #00FF41;
}
#cursor {
border-left: .1em solid #00FF41;
animation: blink .7s steps(1) infinite;
}
@keyframes blink {
50% {
border-color: transparent;
}
}
链接到笔:https://codepen.io/AliKlein/pen/aPyKjy JSFiddle:https://jsfiddle.net/am9qke3v/
答案 1 :(得分:1)
在循环的第一次迭代中,您将从函数返回单个项目。这是不正确的。您需要返回一个JSX对象数组:
const content =()=>{
const message =["WELCOME TO MY WORLD","THIS IS MY WEBSITE","I AM AT YOUR SERVICE"];
let i =0 ;
let jsxArray = [];
for(i=0; i<message.length;i++){
jsxArray.push(
<div className='background'>
<h1 className="typewriter">
{message[i]}
</h1>
</div>
);
}
return jsxArray;
}
答案 2 :(得分:1)
这是我在Typescript&React中使用功能组件和挂钩的代码:
import React, { useState, useEffect } from 'react'
const Typer = ({ title = '', dataText }: TyperProps) => {
const [text, setText] = useState('')
const [isDeleting, setIsDeleting] = useState(false)
const [speed, setSpeed] = useState(150)
const [loop, setLoop] = useState(0)
const i: number = loop % dataText.length
const fullText: string = dataText[i]
const handleTyping = () => {
setText(
isDeleting
? fullText.substring(0, text.length - 1)
: fullText.substring(0, text.length + 1)
)
setSpeed(isDeleting ? 30 : 150)
if (!isDeleting && text === fullText) {
setTimeout(() => setIsDeleting(true), 500)
} else if (isDeleting && text === '') {
setIsDeleting(false)
setLoop(loop + 1)
}
}
useEffect(() => {
const timer = setTimeout(() => {
handleTyping()
}, speed)
return () => clearTimeout(timer)
})
return <h1>{title} {text}</h1>
}
interface TyperProps {
dataText: string[]
title?: string
}
export default Typer
interface TyperProps
部分与prop-types
类似。如果不需要,您可以摆脱它。
答案 3 :(得分:1)
如果您想使用钩子来完成此操作,则可以执行以下操作:
(非常感谢@AliKlein for the inspiration)
const { render } = ReactDOM;
const { useState, useEffect } = React;
const CONSTANTS = {
DELETING_SPEED: 30,
TYPING_SPEED: 150,
}
function TypeWriter({ messages, heading }) {
const [state, setState] = useState({
text: "",
message: "",
isDeleting: false,
loopNum: 0,
typingSpeed: CONSTANTS.TYPING_SPEED,
});
useEffect(() => {
let timer = "";
const handleType = () => {
setState(cs => ({
...cs, // cs means currentState
text: getCurrentText(cs),
typingSpeed: getTypingSpeed(cs)
}));
timer = setTimeout(handleType, state.typingSpeed);
};
handleType();
return () => clearTimeout(timer);
}, [state.isDeleting]);
useEffect(() => {
if (!state.isDeleting && state.text === state.message) {
setTimeout(() => {
setState(cs => ({
...cs,
isDeleting: true
}))
}, 500);
} else if (state.isDeleting && state.text === "") {
setState(cs => ({
...cs, // cs means currentState
isDeleting: false,
loopNum: cs.loopNum + 1,
message: getMessage(cs, messages)
}));
}
}, [state.text, state.message, state.isDeleting, messages]);
function getCurrentText(currentState) {
return currentState.isDeleting
? currentState.message.substring(0, currentState.text.length - 1)
: currentState.message.substring(0, currentState.text.length + 1);
}
function getMessage(currentState, data) {
return data[Number(currentState.loopNum) % Number(data.length)];
}
function getTypingSpeed(currentState) {
return currentState.isDeleting
? CONSTANTS.TYPING_SPEED
: CONSTANTS.DELETING_SPEED;
}
return (
<h1>
{heading}
<span>{state.text}</span>
<span id="cursor" />
</h1>
);
}
let msgs = ["WELCOME TO MY WORLD","THIS IS MY WEBSITE","I AM AT YOUR SERVICE"];
render(<TypeWriter heading={"Things I want to type:"} messages={msgs} />, document.body);
@import url('https://fonts.googleapis.com/css?family=VT323');
body {
font-family: 'VT323', monospace;
background-color: #003B00;
padding: 1em 2em;
}
h1 {
color: #00FF41;
}
#cursor {
border-left: .1em solid #00FF41;
animation: blink .7s steps(1) infinite;
}
@keyframes blink {
50% {
border-color: transparent;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.9.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.9.0/umd/react-dom.production.min.js"></script>
答案 4 :(得分:1)
react-mk(是的,我是作者,不,您不需要安装它)主要使用useEffect挂钩(由组件生命周期触发,以避免呈现问题)和自定义useKeyboard挂钩来处理此问题。
此外,我认为逼真的打字动画应支持字符和句子的打字之间的逼真的延迟。在下面的示例中,请参见句子DelayPerCharRange和keyPressDelayRange。
// Keyboard.js
import { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import getTimer from './getTimer';
import useKeyboard from './useKeyboard';
import { defaultKeyPressDelay } from './constants';
const initialState = [];
export const type = (...actions) => [...actions];
export default function Keyboard({ children, sentenceDelayPerCharRange, keyPressDelayRange }) {
const [text, setText, clearText] = useKeyboard();
const [remainingActions, setRemainingActions] = useState(initialState);
useEffect(
/* istanbul ignore next */
() => {
if (remainingActions.length === initialState.length) {
setRemainingActions(
typeof children === 'function' ? children({ type }) : [children.toString()],
);
}
},
[children],
);
useEffect(() => {
if (remainingActions.length > initialState.length) {
const [newAction, ...newRemainingActions] = remainingActions;
const doAction =
/* istanbul ignore next */
action =>
setText(action, keyPressDelayRange).then(
/* istanbul ignore next */
() => setRemainingActions(newRemainingActions),
);
const doClear =
/* istanbul ignore next */
action => clearText(action).then(doAction);
getTimer(newAction, sentenceDelayPerCharRange).then(doClear);
}
}, [remainingActions]);
return text;
}
Keyboard.propTypes = {
children: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.func]).isRequired,
keyPressDelayRange: PropTypes.arrayOf(PropTypes.number),
sentenceDelayPerCharRange: PropTypes.arrayOf(PropTypes.number),
};
Keyboard.defaultProps = {
keyPressDelayRange: defaultKeyPressDelay,
sentenceDelayPerCharRange: defaultKeyPressDelay.map(delay => delay * 1.25),
};
还有一些辅助功能,例如getTimer / s和getDelay。
// useKeyboard.js
import { useState, useRef, useEffect } from 'react';
import getTimers from './getTimers';
import getTimer from './getTimer';
const initialState = '';
export const backspace = (chars, setChars) =>
setChars(chars.length > 1 ? chars.slice(0, chars.length - 1) : initialState);
export const type = (chars, nextChar, setChars) => setChars(`${chars}${nextChar}`);
export default function useKeyboard() {
const [chars, setChars] = useState(initialState);
const [remainingChars, setRemainingChars] = useState(initialState);
const [resolver, setResolver] = useState(undefined);
const [delayRange, setDelayRange] = useState(undefined);
const charsRef = useRef(chars);
charsRef.current = chars;
useEffect(() => {
/* istanbul ignore next */
if (remainingChars.length > initialState.length) {
const [nextChar, ...newRemainingChars] = remainingChars;
const doType = () => type(chars, nextChar, setChars);
const doSetRemainingChars = () => setRemainingChars(newRemainingChars);
getTimer(nextChar, delayRange)
.then(doType)
.then(doSetRemainingChars);
} else if (typeof resolver === 'function') {
resolver();
setResolver(undefined);
setRemainingChars(initialState);
}
}, [remainingChars]);
const setText = (text, keyPressDelayRange) =>
new Promise(resolve => {
setResolver(() => resolve);
setDelayRange(keyPressDelayRange);
setChars(initialState);
/* istanbul ignore else */
if (typeof text === 'string') {
setRemainingChars(text);
} else {
resolve();
}
});
const clearText = action =>
new Promise(resolve =>
/* istanbul ignore next */
!chars
? resolve(action)
: getTimers(charsRef.current.split(''), () => {
/* istanbul ignore next */
backspace(charsRef.current, setChars);
/* istanbul ignore next */
return charsRef.current.length === 0 && resolve(action);
}),
);
const text = chars;
return [text, setText, clearText];
}
我喜欢这种实现方式,因为尽管它重量轻,但仍保持其声明性。更不用说它实际上依赖于组件的生活方式,而不是仅依赖于setInterval / setTimeout(如果您曾经使用过打字动画库,偶尔会弄乱文本,那可能是罪魁祸首)。
答案 5 :(得分:1)
这是我的打字功能组件:
const { useState, useRef, useEffect } = React // inline import
// import { useState, useRef, useEffect } from 'react' // normal import
const Typing = ({ text, onFinish, delay = 100 }) => {
const to = useRef()
const [charIndex, setCharIndex] = useState(1)
useEffect(() => {
if(charIndex < text.length) {
to.current = setTimeout(() => setCharIndex(charIndex + 1), delay)
} else {
onFinish()
}
return () => clearTimeout(to.current) // cleanup on unmount
}, [charIndex])
return text.substr(0, charIndex)
}
ReactDOM.render(
<Typing text="Hello world!" onFinish={() => console.log('done')} />
, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 6 :(得分:0)
检查此包裹 https://www.npmjs.com/package/reactjs-typing-effect
npm install-保存reactjs-typing-effect
或
添加纱线reactjs-typing-effect
答案 7 :(得分:0)
检查此新组件 https://www.npmjs.com/package/reactjs-typing-effect
添加纱线reactjs-typing-effect
import ReactJsTyping from 'reactjs-typing-effect';
const list=['Reactjs Typing','custom speed']
render(){
<div style={{ fontSize: 20, color: '#2196F3'}}>
<ReactJsTyping StringList={list} speed={500}/>
</div>
}