It's free and you have access to premium codes!
Welcome back! Please login to your account.
Don't worry, we'll send you a message to help you to recover your acount.
Written by 13 May 2020
Have you ever noticed that the menus can be slide down by a rope like real screens in the cinema? It is very interesting to put such menus in your website, isn't it?
<!-- this script is provided by www.javascriptfreecode.com coded by: Kerixa Inc. -->
<style>
html{
height: 100%;
}
body{
font-family: Arial;
margin: 0px;
height: 100%;
--color: #2196F3;
--bgColor: #424242;
color: var(--color);
background-color: var(--bgColor);
}
*{
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
-moz-user-select: none; /* Old versions of Firefox */
-ms-user-select: none; /* Internet Explorer/Edge */
user-select: none;
}
#nav{
position: fixed;
transform: translateY(-70vh);
overflow: visible;
}
canvas{
display: none;
}
#nav > #content{
box-sizing: border-box;
margin: 0px;
padding: 20vh 10px 10vh 10px;
height: 70vh;
box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22);
background-color: #616161;
}
#nav > #content > h1{
color: #eee;
margin: 0px;
text-align: center;
}
#nav > #content > div{
margin: 30px auto;
display: flex;
justify-content: center;
align-items: center;
}
#nav > #content a{
margin: 10px;
font-size: 20px;
}
#nav > #rope{
width: 100vw;
height: 100vh;
display: block;
}
#nav > #rope > circle{
fill: var(--bgColor);
stroke: var(--color);
cursor: pointer;
-webkit-tap-highlight-color: transparent;
}
#nav > #rope > path{
stroke: var(--color);
}
#page{
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
color: var(--textColor);
}
#page > h1{
font-size: 50px;
}
</style>
<div id="nav">
<div id="content">
<h1>Menu & Navigation</h1>
<div>
<a data-color="#2196F3" style="color: #2196F3" href="">Blue Page</a>
<a data-color="#F44336" style="color: #F44336" href="">Red Page</a>
<a data-color="#8BC34A" style="color: #8BC34A" href="">Green Page</a>
<a data-color="#FF9800" style="color: #FF9800" href="">Orange Page</a>
</div>
</div>
<svg id="rope" xmlns="http://www.w3.org/2000/svg">
<path fill="transparent" stroke-width="10px" stroke-linejoin="round" />
<circle stroke-width="10px" r="20" id="handle"></circle>
</svg>
</div>
<div id="page">
<h1>Pull</h1>
</div>
<script src='https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.14.2/matter.min.js'></script>
<script id="rendered-js">
class PhysicsEngine {
constructor() {
this.navclosedPos = -30;
this.navHeight = 50;
this.canvasWidth = 500;
this.canvasHeight = 600;
this.initWorld();
}
initWorld() {
const engine = Matter.Engine.create();
const render = Matter.Render.create({
element: document.body,
engine: engine });
let bodies = this.createBodies();
let constraints = this.createConstraints();
Matter.World.add(engine.world, [...bodies, ...constraints]);
Matter.Engine.run(engine);
Matter.Render.run(render);
}
createBodies() {
this.nav = Matter.Bodies.rectangle(this.canvasWidth / 2, this.navclosedPos, this.canvasWidth, this.navHeight, { isSensor: true, inertia: Infinity, mass: 0.1 });
this.rope = this.createRope();
this.handle = this.rope.bodies[this.rope.bodies.length - 1];
return [this.nav, this.rope];
}
createRope() {
const ropeParts = Matter.Body.nextGroup(true);
const rope = Matter.Composites.stack(this.canvasWidth / 2, this.navclosedPos, 8, 1, -30, 0, (x, y) => {
return Matter.Bodies.circle(x, y, 15, {
collisionFilter: { group: ropeParts } });
});
Matter.Composites.chain(rope, 0, 0.2, 0, -0.2, { stiffness: 1, damping: 0.6, length: 3 });
return rope;
}
createConstraints() {
this.fixMenuToTop = Matter.Constraint.create({
bodyA: this.nav,
pointA: { x: 0, y: this.navHeight / 2 },
pointB: { x: this.canvasWidth / 2, y: this.navclosedPos },
stiffness: 0.5,
damping: 0.1,
length: 0 });
this.fixMenuToBottom = Matter.Constraint.create({
bodyA: this.nav,
pointA: { x: 0, y: this.navHeight / 2 },
pointB: { x: this.canvasWidth / 2, y: 0 },
stiffness: 0.01,
damping: 0.1,
length: 0 });
const fixRopeToMenu = Matter.Constraint.create({
bodyA: this.nav,
pointA: { x: 0, y: this.navHeight - 20 },
bodyB: this.rope.bodies[0],
stiffness: 1,
length: 0 });
this.fixMouseToHandle = Matter.Constraint.create({
bodyA: this.handle,
pointB: { x: 0, y: 0 },
stiffness: 0.000000000000001,
length: 0 });
return [this.fixMenuToTop, this.fixMenuToBottom, fixRopeToMenu, this.fixMouseToHandle];
}
grabHandle(x, y) {
this.moveHandle(x, y);
this.fixMouseToHandle.stiffness = 1;
}
moveHandle(x, y) {
this.fixMouseToHandle.pointB.x = x;
this.fixMouseToHandle.pointB.y = y;
}
releaseHandle() {
this.fixMouseToHandle.stiffness = 0.000000000000001;
}}
class Nav {
constructor() {
this.physicsEngine = new PhysicsEngine();
this.canvasWidth = this.physicsEngine.canvasWidth;
this.canvasHeight = this.physicsEngine.canvasHeight;
this.navElm = document.getElementById('content');
this.ropeContainer = document.getElementById('rope');
this.ropeElm = this.ropeContainer.querySelector('path');
this.handleElm = document.getElementById('handle');
this.pullText = document.querySelector('#page > h1');
for (let link of Array.from(document.querySelectorAll('a'))) {
link.addEventListener('click', e => {
e.preventDefault();
this.navigateTo(link.getAttribute('data-color'));
});
}
this.handleElm.addEventListener('mousedown', this.grab.bind(this));
document.body.addEventListener('mousemove', this.move.bind(this));
document.body.addEventListener('mouseup', this.release.bind(this));
this.handleElm.addEventListener('touchstart', this.grab.bind(this));
document.body.addEventListener('touchmove', this.move.bind(this), { passive: false });
document.body.addEventListener('touchend', this.release.bind(this));
this.grabbed = false;
this.isOpen = false;
this.shouldOpen = false;
this.inTransition = false;
this.onResize();
window.addEventListener('resize', this.onResize.bind(this));
this.render();
}
onResize() {
this.width = window.innerWidth;
this.height = window.innerHeight;
this.ropeContainer.setAttribute('viewport', `0 0 ${this.width} ${this.height}`);
this.navOpenPos = this.height / 10 * 6;
this.physicsEngine.fixMenuToBottom.pointB.y = this.getCanvasY(this.navOpenPos);
}
grab(e) {
let x = e.clientX || e.touches[0].clientX;
let y = e.clientY || e.touches[0].clientY;
this.grabbed = true;
this.physicsEngine.grabHandle(this.getCanvasX(x), this.getCanvasY(y));
this.inTransition = false;
console.log(this.grabbed);
}
move(e) {
e.preventDefault();
let x = e.clientX || e.touches[0].clientX;
let y = e.clientY || e.touches[0].clientY;
let navPos = this.getScreenY(this.physicsEngine.nav.position.y + this.physicsEngine.navHeight / 2);
if (navPos >= 40 && !this.isOpen && !this.inTransition) {
this.release();
this.open();
} else
if ((navPos >= this.navOpenPos + 25 || navPos <= this.navOpenPos - 10) && this.isOpen && !this.inTransition) {
this.release();
this.close();
} else
if (this.grabbed)
this.physicsEngine.moveHandle(this.getCanvasX(x), this.getCanvasY(y));
}
release() {
if (this.grabbed) {
this.physicsEngine.releaseHandle();
this.grabbed = false;
}
}
open() {
this.shouldOpen = true;
this.inTransition = true;
}
close() {
this.shouldOpen = false;
this.inTransition = true;
}
render() {
window.requestAnimationFrame(this.render.bind(this));
if (this.shouldOpen && !this.isOpen) {
if (this.physicsEngine.fixMenuToTop.stiffness >= 0.01) {
this.physicsEngine.fixMenuToTop.stiffness -= 0.02;
this.physicsEngine.fixMenuToBottom.stiffness += 0.02;
} else
this.isOpen = true;
}
if (!this.shouldOpen && this.isOpen) {
if (this.physicsEngine.fixMenuToTop.stiffness <= 0.5) {
this.physicsEngine.fixMenuToTop.stiffness += 0.03;
this.physicsEngine.fixMenuToBottom.stiffness -= 0.03;
} else
this.isOpen = false;
}
let path = `M ${this.width / 2} ${this.getScreenY(this.physicsEngine.nav.position.y)}`;
for (let body of this.physicsEngine.rope.bodies) {
path += `L ${this.getScreenX(body.position.x)} ${this.getScreenY(body.position.y)}`;
}
let lastBody = this.physicsEngine.rope.bodies[this.physicsEngine.rope.bodies.length - 1];
this.handleElm.setAttribute('cx', this.getScreenX(lastBody.position.x));
this.handleElm.setAttribute('cy', this.getScreenY(lastBody.position.y));
this.ropeElm.setAttribute('d', path);
//console.log(this.physicsEngine.nav.position.y);
this.navElm.style.transform = `translate(${0}px, ${this.getScreenY(this.physicsEngine.nav.position.y + this.physicsEngine.navHeight / 2)}px)`;
}
getScreenX(canvasX) {
return canvasX / this.canvasWidth * this.width;
}
getScreenY(canvasY) {
return canvasY / this.canvasHeight * this.height;
}
getCanvasX(screenX) {
return screenX / this.width * this.canvasWidth;
}
getCanvasY(screenY) {
return screenY / this.height * this.canvasHeight;
}
navigateTo(page) {
document.body.style.setProperty('--color', page);
this.close();
}}
const nav = new Nav();
//# sourceURL=pen.js
</script><a target='_blank' href='www.javascriptfreecode.com' style='font-size: 8pt; text-decoration: none'>JavaScript Best Codes</a>
Comments
Here you can leave us commments. Let us know what you think about this code tutorial!