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.
Please check your email for instructions to activate your account.
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 https://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='https://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!