I'm making a React Native Karaoke app and I need to do an animation in which a letter is colored from left to right.
Is it possible to apply color to, say, half of a letter?
Aside from my comment, Here is how this type of styling is done. Instead of on hover, you would just animate the width with javascript.
p{
color: black;
position: relative;
display: inline-block;
margin: 0;
font-size: 50px;
}
p:before{
content: attr(data-c);
position: absolute;
width: 0;
overflow:hidden;
top: 0;
left: 0;
color:red;
transition: width 1s;
}
p:hover:before{
width: 100%;
}
<p data-c="Hello">Hello</p>
I tried this you may further apply more animation to it:
import React, { Component } from 'react';
import {
Text,
View,
Animated
} from 'react-native';
export default class AnimatedText extends Component{
componentWillMount() {
this.animatedValue = new Animated.Value(0);
}
componentDidMount() {
Animated.timing(this.animatedValue, {
toValue: 200,
duration: 2500
}).start();
}
render() {
const interpolateColor = this.animatedValue.interpolate({
inputRange: [0, 200],
outputRange: ['rgb(255,255,255)', 'rgb(255, 0, 0)'],
extrapolate: "clamp"
})
const animatedStyle = {
color: interpolateColor,
}
return (
<View style={{flex: 1,justifyContent: 'center',alignItems: 'center',padding:10,backgroundColor:'black'}}>
<Animated.Text style={animatedStyle}>
May be one day so don't turn on the lights I'll give you what you like Give you what you like
</Animated.Text>
</View>
);
}
}
Your solution in expo works if you set a height restriction: https://snack.expo.io/Bko7oYvr7
Related
I am new into Grafana. I created a custom plugin on which I have a Button. The project compiles without issues, and the button appears on the panel, but no click event is handled
Please find below the source code
import React from ‘react’;
import { PanelProps } from ‘#grafana/data’;
import { SimpleOptions } from ‘types’;
import { css, cx } from ‘#emotion/css’;
import { Button, useStyles2, useTheme2 } from ‘#grafana/ui’;
interface Props extends PanelProps {}
const getStyles = () => {
return {
wrapper: css font-family: Open Sans; position: relative; ,
svg: css position: absolute; top: 0; left: 0; ,
textBox: css position: absolute; bottom: 0; left: 0; padding: 10px; ,
hover:css background-color: rgba(255, 0, 0, 1); ,
active:css background-color: rgba(255, 255, 0, 1); ,
};
};
export const SimplePanel: React.FC = ({ options, data, width, height }) => {
const theme = useTheme2();
const styles = useStyles2(getStyles);
return (
<div
className={cx(
styles.wrapper,
css width: ${width}px; height: ${height}px;
)}
>
<svg
className={styles.svg}
width={width}
height={height}
xmlns=“SVG namespace”
xmlnsXlink=“XLink namespace”
viewBox={-${width / 2} -${height / 2} ${width} ${height}}
>
<circle style={{ fill: theme.colors.primary.main }} r={100} />
<div className={styles.textBox}>
{options.showSeriesCount && <div>Number of series: {data.series.length}</div>}
<div>Text option value: {options.text}</div>
</div>
<Button onClick={()=>console.log("test")}>TestButton</Button>
</div>
);
};
I also changed in the defaults.ini the disable_sanitize_html = true but the problem didn’t get solved.
Please can you advice what to do next.
I set the disable_sanitize_html=true but didn't work.
i started a simple project with react.in my project i have a paragraph and when mouse hover on paragraph (mouse enter event) a square appears under the paragraph and when hover out from paragraph(mouse leave event) that square disapear.but this occure so fast so i want changing this smoothly and i want use opacity and change that from 0 to 1 and reverse when my events occure.but I do not know what to do to change the opacity with animation in react.
this is my appjs
import './index.css';
import React, {useState} from "react";
function App() {
const [isShowSquare, setIsShowSquare] = useState(false);
const showSquare = () => {
setIsShowSquare(true);
}
const hideSquare = () => {
setIsShowSquare(false);
}
return (
<div>
<p onMouseEnter={showSquare} onMouseLeave={hideSquare} style={{display:'inline-block'}}>Hover Me</p>
{isShowSquare ?
<div className='square'>
</div>
: null
}
</div>
);
}
export default App;
and this is my index.css
*{
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.square{
width: 50px;
height: 50px;
background-color: #61dafb;
}
I would be very grateful if anyone could help me
Here is a method without using useState though.
I don't know if this part is important, but have a look at my
sandbox
First of all you need a css class to define the opacity the method and how much time it will take. Also, your first square class should have opacity: 0, meaning non visible.
When mouse is over text, then you add the extra class to the element.
const showSquare = () => {
div.current.classList.add("square-full");
};
const hideSquare = () => {
div.current.classList.remove("square-full");
};
.square.square-full {
opacity: 0.5;
transition: opacity 1s ease-out;
}
.square {
width: 50px;
height: 50px;
background-color: #61dafb;
opacity: 0;
}
Updated answer: No need for ref
Just use the following code
export default function App() {
const [ isShown, setShown ] = useState(false)
return (
<div>
<p
onMouseEnter={() => setShown(true)}
onMouseLeave={() => setShown(false)}
style={{ display: "inline-block" }}
class="paragraph"
>
Hover Me
</p>
<div className={`square ${isShown ? 'square-full' : ''}`}></div>
</div>
);
}
along with the extra class i mentioned before
Appearing is easy, and for disappearing I found a solution like this;
import { useState } from "react";
import "./styles.css";
export default function App() {
const [visible, setVisible] = useState(false)
const [disappear, setDisappear] = useState(false)
return (
<div className="App">
<p onMouseLeave={()=> {
setDisappear(true)
setTimeout(()=>{setVisible(false)
setDisappear(false)}
, 1000)
}} onMouseEnter={()=> setVisible(true)}>Hide/Show square </p>
{visible && <div className="square"
style={{
width: 100,
height: 100,
animation: disappear ? "disappear 1s ease" : "appear 1s ease"
}}> </div> }
</div>
);
}
For the animations in css ;
//style.css
.square {
background-color: red;
animation: appear 1s ease;
}
#keyframes appear {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes disappear {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
So what happens here is that we have a keyframe on our css for the opacity initially. So this works fine, tricky part is disappearing. When we set the visible state to false React immideately removes our element, so we have setTimeOut to stop React for 1 second. In that 1 second we apply our animations, it runs smoothly on me. Go ahead and try.
I am trying to change background color of Navbar to white on scrolling, but my code changes the state only in the console.
How to solve it?
Here is React and CSS code
import React, { useState, useEffect } from 'react';
import '../index';
export default function Header() {
const [headerColor, setHeaderColor] = useState('.header container');
const listenScrollEvent = () => {
window.scrollY > 250 ? setHeaderColor('#29323c') : setHeaderColor('transparent');
};
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
window.addEventListener('scroll', listenScrollEvent);
});
console.log(headerColor);
return (
<section id="header" style={{ color: headerColor }}>
<div className="header container" style={{ color: headerColor }}>
/* Header section */
#header {
position: fixed;
z-index: 1000;
left: 0;
top: 0;
width: 100vw;
height: auto;
}
#header .header {
min-height: 8vh;
background-color: rgba(31, 30, 30, 0.24);
transition: 0.3s ease background-color;
}
#header .nav-bar {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 100%;
max-width: 1300px;
padding: 0 10px;
}
I would rephrase your question to: "How does state work in React?"
You seem to be using a component named "Header".
import React, { useState, useEffect } from 'react';
import '../index';
export default function Header() {
const headerColor = useState({ headerColor : 'transparant' });
const listenScrollEvent = () => {
window.scrollY > 250 ? setHeaderColor('#29323c') : setHeaderColor('transparent');
};
//well lets create a func for setHeaderColor
setHeaderColor(color){
this.setState({
headerColor: color
});
}
// Similar to componentDidMount and componentDidUpdate:
useEffect(() => {
window.addEventListener('scroll', listenScrollEvent);
});
console.log(headerColor);
return (
<section id="header" style={{ background-color: headerColor }}>
<div className="header container" style={{ background-color: headerColor }}>
"Hooks are a new feature in React v16.7.0-alpha useState is the “Hook”. useState() set the default value of the any variable and manage in function component(PureComponent functions). ex : const [count, setCount] = useState(0); set the default value of count 0. and u can use setCount to increment or decrement the value. onClick={() => setCount(count + 1)} increment the count value.DOC
"
Base answer on:
https://stackoverflow.com/a/53166036/4095631
Please also look at:
"Updating an object with setState in React"
Updating an object with setState in React
and the official documents about state and hooks:
https://reactjs.org/docs/hooks-overview.html
I would like to add some transition styling to my side navigation on my app. I am able to do this using normal classes however in this tutorial they use css modules and i am unsure how to do this using css modules.
I would like my nav to glide in and out, at the moment it jumps statically when the onClick function fires - toggleSideDrawer.
I have used this logic but I am not sure if it is doing anything:
className={props.toggleSideDrawer ? classes.SideDrawerOpen : classes.SideDrawer
Essentially i want that when the user clicks the toggle, the transform property switches from translateX(-100%) to translateX(0) but this is not happening.
Side nav code:
import React from "react";
import Logo from "../../Logo/Logo";
import NavigationItems from "../NavigationItems/NavigationItems";
import Backdrop from "../../UI/Backdrop/Backdrop";
import Aux from "../../../hoc/Aux";
import classes from "./SideDrawer.css";
const SideDrawer = props => {
return (
<Aux classname={classes.SideDrawer}>
<Backdrop
showBackdrop={props.showSideDrawer}
clicked={props.toggleSideDrawer}
/>
{props.showSideDrawer && (
<div
onClick={props.toggleSideDrawer}
className={
props.toggleSideDrawer ? classes.SideDrawerOpen : classes.SideDrawer
}
>
<div className={classes.Logo}>
<Logo />
</div>
<nav>
<NavigationItems />
</nav>
</div>
)}
</Aux>
);
};
export default SideDrawer;
Where the code is used in my Layout component:
import React, { useState } from "react";
import Aux from "../Aux";
import classes from "./Layout.css";
import Toolbar from "../../components/Navigation/Toolbar/Toolbar";
import SideDrawer from "../../components/Navigation/SideDrawer/SideDrawer";
const layout = props => {
const [showSideDrawer, setShowSideDrawer] = useState(false);
return (
<Aux>
<SideDrawer
showSideDrawer={showSideDrawer}
toggleSideDrawer={() => {
setShowSideDrawer(!showSideDrawer);
}}
/>
<Toolbar
onMenuClick={() => {
setShowSideDrawer(!showSideDrawer);
}}
/>
<main className={classes.mainContent}> {props.children} </main>
</Aux>
);
};
export default layout;
CSS:
.SideDrawer {
position: fixed;
width: 280px;
max-width: 70%;
height: 100%;
left: 0;
top: 0;
z-index: 200;
background-color: white;
padding: 32px 16px;
box-sizing: border-box;
transform: translateX(-100%);
}
#media (min-width: 500px) {
.SideDrawer {
display: none;
}
}
.Logo {
height: 11%;
text-align: center;
}
.SideDrawerOpen {
position: fixed;
width: 280px;
max-width: 70%;
height: 100%;
left: 0;
top: 0;
z-index: 200;
padding: 32px 16px;
box-sizing: border-box;
background-color: red;
transform: translateX(0);
transition: transform 0.3s ease-out;
}
The thing is that you need the element will has the transition rule all the time.
My suggestion is to set a static class which which will hold all the styles and addd another one only for overriding transform to make it move.
Something like that (it uses scss but it's easy to do it with css)
.SideDrawer {
position: fixed;
width: 280px;
max-width: 70%;
height: 100%;
left: 0;
top: 0;
z-index: 200;
background-color: white;
padding: 32px 16px;
box-sizing: border-box;
transition: transform .3s ease;
transform: translateX(-100%);
&.show {
transform: translateX(0);
}
}
export const App = () => {
const [showSideDrawer, setShowSideDrawer] = useState(false);
const sidebarClasses = classname([
styles.SideDrawer,
{
[styles.show]: showSideDrawer
}
]);
const ToggleSidebar = () => {
return (
<button onClick={() => setShowSideDrawer(!showSideDrawer)}>
Toggle Sidebar
</button>
);
};
return (
<Fragment>
<h1>App</h1>
<div className={sidebarClasses}>
<div>Sidebar content</div>
<ToggleSidebar />
</div>
<ToggleSidebar />
</Fragment>
);
};
https://codesandbox.io/s/xenodochial-framework-04sbe?file=/src/App.jsx
#MoshFeu helped me fix this.
The problem is that you render the drawer only when showSideDrawer so before it becomes true, the sidebar is not in the DOM yet so the transition is not affecting it.
The solution is to keep it in the DOM all the time but toggle . Open class to change the style.
There are libraries that knows to make the transition works even for elements that are not in the DOM but it's a bit more complicated.
code fix for SideDrawer.js without the conditional within the return
class SideDrawer extends Component {
render() {
let sideDrawerClass = [classes.SideDrawer];
// SideDrawer will now be an array with the side drawer classes and the open class
if (this.props.showSideDrawer) {
sideDrawerClass.push(classes.Open);
}
return (
<Aux classname={classes.SideDrawer}>
<Backdrop
showBackdrop={this.props.showSideDrawer}
clicked={this.props.toggleSideDrawer}
/>
<div
className={sideDrawerClass.join(" ")}
onClick={this.props.toggleSideDrawer}
>
<div className={classes.Logo}>
<Logo />
</div>
<nav>
<NavigationItems />
</nav>
</div>
</Aux>
);
}
}
export default SideDrawer;
Trying to build a nifty animation for launching dialogs but running into a snag with ReactCSSTransitionsGroup. The goal is to ensure that the dialog looks like its zooming out of the button that launched it. Below is a sample that shows the working demo.
The math looks good, the css looks good, the component looks good. The unexpected behavior exhibited is the following
Click on the first button (either one). Works perfectly.
Click on the second button, the enter animation does not play.
Doesn't matter how many buttons you add, only the first works as expected. All additional buttons won't show the enter animation properly.
The leave animation works for all buttons.
Trying to figure out if there's something wrong with the code, unintended usage of ReactCSSTransitionsGroup or a bug with it.
Fiddle is here
Thanks!
let ReactCSSTransitionGroup = React.addons.CSSTransitionGroup;
let StyleSheet = aphrodite.StyleSheet;
let css = aphrodite.css
const Button = (props) => {
return <div className="button" onClick={(e) => props.onClick(e)}>Click me</div>;
}
let emptyStyleSheet = StyleSheet.create({
enter: {},
enterActive: {},
leave: {},
leaveActive: {}
});
class UnicornDialog extends React.Component {
constructor(props) {
super(props);
this.state = {sheet: emptyStyleSheet};
}
componentWillReceiveProps(nextProps, nextContext){
if (!nextProps.show) {
return;
}
let viewportRect = document.body.getBoundingClientRect();
let sourceRect = nextProps.startRect;
let viewportCenterX = viewportRect.left + (viewportRect.width / 2);
let viewportCenterY = viewportRect.top + (viewportRect.height / 2);
let sourceCenterX = sourceRect.left + (sourceRect.width / 2);
let sourceCenterY = sourceRect.top + (sourceRect.height / 2);
let dx = sourceCenterX - viewportCenterX;
let dy = sourceCenterY - viewportCenterY;
let sheet = StyleSheet.create({
enter: {
opacity: 0,
transform: `translate(${dx}px, ${dy}px) scale(0.01)`
},
enterActive: {
opacity: 1,
transform: "translate(0, 0) scale(1)", transition: "transform 750ms cubic-bezier(0, 0, 0.2, 1), opacity 750ms cubic-bezier(0, 0, 0.2, 1)"
},
leave: {
opacity: 1,
transform: "translate(0, 0) scale(1)"
},
leaveActive: {
opacity: 0,
transform: `translate(${dx}px, ${dy}px) scale(0.01)`,
transition: "transform 750ms cubic-bezier(0, 0, 0.2, 1), opacity 750ms cubic-bezier(0, 0, 0.2, 1)"
}
})
this.setState(sheet);
}
render() {
let child = <div key={"dialog"}
className="dialog"
onClick={this.props.onClick}>click anywhere to dismiss</div>;
if (!this.props.show) {
child = null;
}
return <ReactCSSTransitionGroup
transitionName={{
enter: css(this.state.enter),
enterActive: css(this.state.enterActive),
leave: css(this.state.leave),
leaveActive: css(this.state.leaveActive)
}}
transitionEnterTimeout={750}
transitionLeaveTimeout={750}>
{child}
</ReactCSSTransitionGroup>
}
}
class Parent extends React.Component {
constructor(props) {
super(props);
this.state = { startRect: null, show: false };
}
showDialog(e) {
let startRect = e.target.getBoundingClientRect();
let show = true;
this.setState({ startRect, show });
}
hideDialog() {
this.setState({ startRect: null, show: false });
}
render() {
return (
<div>
<Button onClick={this.showDialog.bind(this)} />
<Button onClick={this.showDialog.bind(this)} />
<UnicornDialog {...this.state} onClick={this.hideDialog.bind(this)} />
</div>
);
}
}
ReactDOM.render(< Parent />, document.getElementById('container'));
body {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
}
.button {
position: absolute;
height: 32px;
line-height: 32px;
width: 128px;
text-align: center;
border: 1px solid rgba(64, 64, 64, 0.1);
background-color: #e74c3c;
color: white;
cursor: pointer;
}
.button:first-child {
top: 64px;
left: 64px;
}
.button:nth-child(2) {
top: 264px;
left: 264px;
}
.dialog {
box-sizing: border-box;
padding: 150px;
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 100;
background-color: #34495e;
color: #ecf0f1;
cursor: pointer;
font-size: 2rem;
}
<script src="https://npmcdn.com/react#15.4.0/dist/react-with-addons.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/aphrodite#1.1.0/dist/aphrodite.umd.js"></script>
<div id="container">
<!-- This element's contents will be replaced with your component. -->
</div>
Figured this one out - its a bug in the styles. ReactCSSTransitionGroup will apply both enter and enterActive. When applying those, effectively the enter style is applied but not the active.