Initial commit
This commit is contained in:
parent
36f2c92c35
commit
1fdc4e17f6
16
README.md
16
README.md
@ -11,11 +11,25 @@ Never ever worry about a fancy dropdown menu. This component does it for you!
|
||||
|
||||
# Usage
|
||||
|
||||
`import Menu from 'react-animated-menus'`
|
||||
|
||||
Component usage:
|
||||
|
||||
`<Menu width={"20px"} color="rgb(123, 192, 222)" />`
|
||||
|
||||
Replace `width` optionally width `height` but don't use both at the same time.
|
||||
To keep the ratio between height and width one has to be given and the other one is calculated by the component.
|
||||
|
||||
One example with height:
|
||||
|
||||
`<Menu height={"50px"}" />`
|
||||
|
||||
`color` is optional. The defaul value is `rgb(255, 255, 255)` if it's not defined.
|
||||
|
||||
# Contact
|
||||
|
||||
**Github:** https://github.com/aleabodo
|
||||
|
||||
**Wesite:** https://alexbell.de
|
||||
**Wesite:** https://alexbell.ninja
|
||||
|
||||
**Email:** mail@alexbell.de
|
||||
|
51
package-lock.json
generated
51
package-lock.json
generated
@ -3060,6 +3060,57 @@
|
||||
"integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=",
|
||||
"dev": true
|
||||
},
|
||||
"css-loader": {
|
||||
"version": "0.28.11",
|
||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-0.28.11.tgz",
|
||||
"integrity": "sha512-wovHgjAx8ZIMGSL8pTys7edA1ClmzxHeY6n/d97gg5odgsxEgKjULPR0viqyC+FWMCL9sfqoC/QCUBo62tLvPg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"babel-code-frame": "6.26.0",
|
||||
"css-selector-tokenizer": "0.7.0",
|
||||
"cssnano": "3.10.0",
|
||||
"icss-utils": "2.1.0",
|
||||
"loader-utils": "1.1.0",
|
||||
"lodash.camelcase": "4.3.0",
|
||||
"object-assign": "4.1.1",
|
||||
"postcss": "5.2.18",
|
||||
"postcss-modules-extract-imports": "1.2.0",
|
||||
"postcss-modules-local-by-default": "1.2.0",
|
||||
"postcss-modules-scope": "1.1.0",
|
||||
"postcss-modules-values": "1.3.0",
|
||||
"postcss-value-parser": "3.3.0",
|
||||
"source-list-map": "2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"has-flag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz",
|
||||
"integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "5.2.18",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz",
|
||||
"integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "1.1.3",
|
||||
"js-base64": "2.4.5",
|
||||
"source-map": "0.5.7",
|
||||
"supports-color": "3.2.3"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz",
|
||||
"integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"css-select": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
|
@ -20,6 +20,7 @@
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-preset-react": "^6.16.0",
|
||||
"babel-preset-stage-0": "^6.24.1",
|
||||
"css-loader": "^0.28.11",
|
||||
"path": "^0.12.7",
|
||||
"prop-types": "^15.6.0",
|
||||
"react": "^16.0.0",
|
||||
|
232
src/components/Menu.js
Normal file
232
src/components/Menu.js
Normal file
@ -0,0 +1,232 @@
|
||||
import React, { Component } from 'react';
|
||||
import anime from 'animejs'
|
||||
|
||||
/*
|
||||
* css
|
||||
*/
|
||||
import '../styles/Menu.css'
|
||||
|
||||
|
||||
class App extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
/*
|
||||
* Expected props:
|
||||
* - width: Int in percentage
|
||||
* - OR height: Int in percentage
|
||||
* - color: String
|
||||
*/
|
||||
|
||||
this.state = {
|
||||
id: this.getId(),
|
||||
open: false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
//Event listener for click
|
||||
document.addEventListener("click", (event) => {
|
||||
const id = this.state.id;
|
||||
const open = this.state.open;
|
||||
|
||||
if(event.target.closest('#'+id) && !open) {
|
||||
this.setState({
|
||||
open: true
|
||||
});
|
||||
}
|
||||
|
||||
if(!event.target.closest('#'+id) && open) {
|
||||
this.setState({
|
||||
open: false
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
componentDidUpdate() {
|
||||
const id = this.state.id;
|
||||
|
||||
//Targets that will be triggered
|
||||
var targetDots = document.querySelectorAll('#'+id+' .Menu_dot');
|
||||
var targetElement = document.querySelectorAll('#'+id+' .Menu_element');
|
||||
var targetElements = document.querySelector('#'+id+' .Menu_elements');
|
||||
var targetMenu = document.querySelector('#'+id+'.Menu');
|
||||
|
||||
|
||||
|
||||
if(this.state.open) {
|
||||
var animation = anime.timeline();
|
||||
|
||||
//Display elements
|
||||
targetElements.style.display = "block";
|
||||
|
||||
//Remove hover effect
|
||||
targetMenu.classList.remove("Menu_closed");
|
||||
|
||||
animation
|
||||
.add({
|
||||
targets: targetDots,
|
||||
scaleX: 9,
|
||||
scaleY: 10,
|
||||
borderRadius: 0,
|
||||
duration: 1300,
|
||||
translateY: "40%",
|
||||
backgroundColor: "rgb(255, 255, 255)",
|
||||
easing: 'easeOutExpo'
|
||||
})
|
||||
.add({
|
||||
targets: targetElement,
|
||||
scaleX: [2,1],
|
||||
opacity: 1,
|
||||
duration: function(targetElements, i, l) {
|
||||
return 500 + (i * 200);
|
||||
},
|
||||
easing: 'easeInOutQuart',
|
||||
offset: '-=1100'
|
||||
});
|
||||
} else {
|
||||
animation = anime.timeline();
|
||||
const color = this.getColor();
|
||||
|
||||
//Remove hover effect
|
||||
targetMenu.classList.add("Menu_closed");
|
||||
|
||||
animation
|
||||
.add({
|
||||
targets: targetElement,
|
||||
scaleX: [1,2],
|
||||
opacity: 0,
|
||||
duration: function(targetElements, i, l) {
|
||||
return 500 + (i * 200);
|
||||
},
|
||||
easing: 'easeInOutQuart'
|
||||
})
|
||||
.add({
|
||||
targets: targetDots,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
borderRadius: "100%",
|
||||
duration: 1300,
|
||||
translateY: 0,
|
||||
backgroundColor: color,
|
||||
easing: 'easeOutExpo',
|
||||
offset: '-=500'
|
||||
});
|
||||
|
||||
//Remove menu after animation finished
|
||||
animation.complete = function() {
|
||||
targetElements.style.display = "none";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getId() {
|
||||
var random = "";
|
||||
var possible = "abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
for (var i = 0; i < 5; i++)
|
||||
random += possible.charAt(Math.floor(Math.random() * possible.length));
|
||||
|
||||
while(true) {
|
||||
if(!document.getElementById(random)) {
|
||||
return random;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getDimensions() {
|
||||
//Input values
|
||||
const inputWidth = this.props.width;
|
||||
const inputHeight = this.props.height;
|
||||
|
||||
if(!(inputWidth ||inputHeight)) {
|
||||
console.log("Please define a height OR width!");
|
||||
}
|
||||
console.log(inputWidth)
|
||||
//Units and values seperated
|
||||
if(inputWidth !== undefined) {
|
||||
//Width
|
||||
const unitWidth = inputWidth.replace(/[\d]+/g,"");
|
||||
const valueWidth = parseFloat(inputWidth);
|
||||
//Height
|
||||
const unitHeight = unitWidth;
|
||||
const valueHeight = valueWidth * 2.5;
|
||||
|
||||
return {
|
||||
width: String(valueWidth) + unitWidth,
|
||||
height: String(valueHeight) + unitHeight
|
||||
}
|
||||
}
|
||||
|
||||
//Height
|
||||
const unitHeight = inputHeight.replace(/[\d]+/g,"");
|
||||
const valueHeight = parseFloat(inputHeight);
|
||||
//Width
|
||||
const unitWidth = unitHeight;
|
||||
const valueWidth = valueHeight / 2.5;
|
||||
|
||||
return {
|
||||
width: String(valueWidth) + unitWidth,
|
||||
height: String(valueHeight) + unitHeight
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getColor() {
|
||||
return this.props.color ? this.props.color : "rgb(255, 255, 255)";
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const style = {
|
||||
width: this.getDimensions().width,
|
||||
height: this.getDimensions().height
|
||||
};
|
||||
|
||||
console.log(style.height);
|
||||
const styleDot = {
|
||||
backgroundColor: this.getColor()
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={style} id={this.state.id} className="Menu Menu_closed">
|
||||
<div className="Menu_dots">
|
||||
<div className="Menu_dotBox">
|
||||
<div style={styleDot} className="Menu_dot">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className="Menu_dotBox">
|
||||
<div style={styleDot} className="Menu_dot">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div className="Menu_dotBox">
|
||||
<div style={styleDot} className="Menu_dot">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="Menu_elements">
|
||||
<div className="Menu_button Menu_element">
|
||||
Button
|
||||
</div>
|
||||
<div className="Menu_button Menu_element">
|
||||
Button
|
||||
</div>
|
||||
<div className="Menu_button Menu_element">
|
||||
Button
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default App;
|
21
src/index.js
21
src/index.js
@ -1,24 +1,5 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
|
||||
class Menu extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
/*
|
||||
* Expected props:
|
||||
* /
|
||||
*/
|
||||
this.currentImageIs_A = true;
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
Hello
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
import Menu from './components/Menu';
|
||||
|
||||
export default Menu;
|
||||
|
78
src/styles/Menu.css
Normal file
78
src/styles/Menu.css
Normal file
@ -0,0 +1,78 @@
|
||||
.Menu {
|
||||
position: relative;
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
transition: opacity 0.5s;
|
||||
border-radius: 20%;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.Menu_closed:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.Menu_dots {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.Menu_dotBox {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 33.33%;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.Menu_dot {
|
||||
position: absolute;
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
border-radius: 100%;
|
||||
top: 15%;
|
||||
left: 15%;
|
||||
transition: opacity 0.4s;
|
||||
}
|
||||
|
||||
.Menu:hover .Menu_dot {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.Menu_elements {
|
||||
position: absolute;
|
||||
top: -6.5%;
|
||||
left: -265%;
|
||||
width: 644%;
|
||||
height: 306%;
|
||||
background-color: transparent;
|
||||
display: none;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.Menu_element {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 33.33%;
|
||||
font-size: 0.8em;
|
||||
text-align: center;
|
||||
padding-top: 15%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.Menu_button {
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
transition: background-color 0.5s, padding 0.5s;
|
||||
opacity: 0;
|
||||
}
|
||||
.Menu_button:hover {
|
||||
background-color: rgb(227, 227, 227);
|
||||
padding-left: 5%;
|
||||
}
|
||||
.Menu_button:active {
|
||||
transition: background-color 0.1s;
|
||||
background-color: rgb(207, 207, 207);
|
||||
padding-left: 5%;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user