Instantly share code, notes, and snippets.
-
Star
(0)
0
You must be signed in to star a gist -
Fork
(0)
0
You must be signed in to fork a gist
-
Save LynnAU/2fb22c94b3b5dbc29f0c0549cf83c81a to your computer and use it in GitHub Desktop.
A react version of https://codepen.io/andyNroses/pen/AXwPkb . The style is slightly different to the codepen but the values can be moved over, it's basically the same code in a slightly different format and structure
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.menu { | |
width: 40px; | |
height: 40px; | |
} | |
.center { | |
position: absolute; | |
margin: auto; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
} | |
.item { | |
position: absolute; | |
left: 0px; | |
top: 0px; | |
width: 50px; | |
height: 50px; | |
background-color: white; | |
-moz-border-radius: 50%; | |
-webkit-border-radius: 50%; | |
border-radius: 50%; | |
cursor: pointer; | |
vertical-align: middle; | |
text-align: center; | |
line-height: 50px; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react'; | |
import anime from 'animejs'; | |
import $ from 'jquery'; | |
import 'jquery-ui-dist/jquery-ui'; | |
import 'jquery-ui-dist/jquery-ui.css'; | |
import './Nav.css'; | |
window.timeOut = undefined; | |
export default class Nav extends Component { | |
Add(item) { | |
let menu = this; | |
if(!this.first) { | |
this.first = this.last = item; | |
this.first.$element.on('mouseup', () => { | |
if(menu.first.isMoving) menu.first.isMoving = false; | |
else menu.Click(); | |
}); | |
item.$element.draggable( | |
{ | |
start: () => { | |
menu.Close(); | |
item.isMoving = true; | |
} | |
}, | |
{ | |
drag: () => { | |
if(item.next) item.next.UpdatePosition(); | |
} | |
}, | |
{ | |
stop: () => { | |
item.isMoving = false; | |
item.MoveTo(item); | |
} | |
} | |
); | |
} else { | |
this.last.next = item; | |
item.prev = this.last; | |
this.last = item; | |
} | |
return item; | |
} | |
Open() { | |
this.status = 'open'; | |
let current = this.first.next, | |
head = this.first, | |
temp = this.first.next, | |
numOfNodes = 0, | |
radius = 110, | |
angle = 0; | |
while(temp !== null) { numOfNodes++; temp = temp.next; } | |
let step = (2 * Math.PI) / numOfNodes; | |
radius = 20 * numOfNodes; | |
while(current !== null) { | |
anime({ | |
targets: current.$element[0], | |
left: parseInt(head.$element.css('left'), 10) + Math.round(radius * Math.cos(angle)), | |
top: parseInt(head.$element.css('top'), 10) + Math.round(radius * Math.sin(angle)), | |
duration: 500 | |
}); | |
current = current.next; | |
angle += step; | |
} | |
} | |
Close() { | |
this.status = 'closed'; | |
let current = this.first.next, | |
head = this.first; | |
while(current !== null) { | |
anime({ | |
targets: current.$element[0], | |
left: head.$element.css('left'), | |
top: head.$element.css('top'), | |
duration: 500 | |
}); | |
current = current.next; | |
} | |
} | |
Click() { | |
if(this.status === 'closed') this.Open(); | |
else this.Close(); | |
} | |
constructor(opts) { | |
super(opts); | |
this.state = { | |
size: 0, | |
tabs: [] | |
}; | |
this.$element = this.first = this.last = null; | |
this.status = 'closed'; | |
this.Add = this.Add.bind(this); | |
this.Open = this.Open.bind(this); | |
this.Close = this.Close.bind(this); | |
this.Click = this.Click.bind(this); | |
} | |
componentDidMount() { | |
let tabs = []; | |
this.props.tabs.forEach((tab, index) => tabs.push(<Item key={tab.id} {...tab} order={index} numOfTabs={this.props.tabs.length} RegisterNewItem={this.Add} />)); | |
this.setState({ | |
tabs: [ ...this.state.tabs, tabs ] | |
}); | |
$('[data-toggle="tooltip"]').tooltip(); | |
console.log(this); | |
} | |
render() { | |
return ( | |
<div className="menu center"> | |
<div id={this.props.element} ref={ele => this.$element = $(ele)}> | |
{ this.state.tabs } | |
</div> | |
</div> | |
); | |
} | |
} | |
class Item extends Component { | |
componentDidMount() { | |
this.props.RegisterNewItem(this); | |
let element = this; | |
this.$element.on('mousemove', () => { | |
clearTimeout(window.timeOut); | |
window.timeOut = setTimeout(() => element.next && element.isMoving ? element.next.MoveTo(element) : null, 10); | |
}); | |
if(this.props.onMount) this.props.onMount(); | |
} | |
MoveTo(item) { | |
anime({ | |
targets: this.$element[0], | |
left: item.$element.css('left'), | |
top: item.$element.css('top'), | |
duration: 700, | |
elasticity: 500 | |
}); | |
if(this.next) this.next.MoveTo(item); | |
} | |
UpdatePosition() { | |
anime({ | |
targets: this.$element[0], | |
left: this.prev.$element.css('left'), | |
top: this.prev.$element.css('top'), | |
duration: 200 | |
}); | |
if(this.next) this.next.UpdatePosition(); | |
} | |
constructor(opts) { | |
super(opts); | |
this.prev = this.next = null; | |
this.isMoving = false; | |
} | |
render() { | |
return ( | |
<div className="item" style={{backgroundColor:this.props.bgColour,zIndex:(this.props.numOfTabs - this.props.order)}} data-toggle="tooltip" data-placement="left" title={this.props.tooltip} onClick={this.props.onClick} ref={ele => { this.$element = $(ele); }}> | |
<i className={this.props.icon} style={{color:this.props.colour}} /> | |
{ this.props.innerHTML } | |
</div> | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment