I'm using the following code to move a ball around the screen when my mobile phone is rotated:
HTML
<html>
<head>
<meta charset="utf-8">
<title>Gyro_Ball</title>
<link rel="stylesheet" href="css/style.css">
<script src="js/main.js"></script>
</head>
<body onload="init()">
<div id="ball"></div>
</body>
</html>
SCRIPT
if ( !window.requestAnimationFrame ) {
window.requestAnimationFrame = ( function() {
return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) {
window.setTimeout( callback, 1000 / 60 );
};
} )();
}
var ball;
var w;
var h;
function init()
{
ball = document.getElementById("ball");
w = window.innerWidth;
h = window.innerHeight;
ball.style.left = (w/2)-50+"px";
ball.style.top = (h/2)-50+"px";
ball.velocity = {x:0,y:0}
ball.position = {x:0,y:0}
if (window.DeviceOrientationEvent) {
window.addEventListener("deviceorientation", function(event)
{
ball.velocity.y = Math.round(event.beta);
ball.velocity.x = Math.round(event.gamma);
}
)
};
update();
}
function update()
{
ball.position.x += ball.velocity.x;
ball.position.y += ball.velocity.y;
if(ball.position.x > (w-100) && ball.velocity.x > 0)
{
ball.position.x = w-100;
}
if(ball.position.x < 0 && ball.velocity.x < 0)
{
ball.position.x = 0;
}
if(ball.position.y > (h-100) && ball.velocity.y > 0)
{
ball.position.y = h-100;
}
if(ball.position.y < 0 && ball.velocity.y < 0)
{
ball.position.y = 0;
}
ball.style.top = ball.position.y + "px"
ball.style.left = ball.position.x + "px"
requestAnimationFrame(update);//KEEP ANIMATING
}
CSS
body {
padding:0;
margin:0;
background-color: #32c9d6;
}
#ball
{
-webkit-transition: all;
transition: all;
position:absolute;
width:100px;
height:100px;
border-radius: 50%;
background: white;
}
It works great! BUT I need to slow the ball down when I rotate my mobile....any ideas?
HERE IS A DEMO (Use Your mobile to view it):
http://inkfood.github.io/Gyro_Ball2/
JSFIDDLE (Use Your mobile to view it):
https://jsfiddle.net/qq74w6a3/6/
I just need to slow that ball down when tilting left to right so it doesn't zoom across so fast...there must be a delay or acceleration or FPS I can use to slow it down?
I tried getting this to work on mobile, but I couldn't. But I did add a mouse event which uses the mouse delta to slow the ball.
I calculate how far the mouse is away from the ball center and then use that percentage to adjust the velocity. I think you could use this to find how far the ball center is from the oriented side. i.e. the bottom.
Run the embedded script and move your mouse around. The ball should slow as it gets closer to the mouse position.
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = (function() {
return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000 / 60);
};
})();
}
var ball;
var dbg;
var w;
var h;
var my = 0;
var mx = 0;
function update() {
ball.position.x += ball.velocity.x;
ball.position.y += ball.velocity.y;
if (ball.position.x > (w - 100) && ball.velocity.x > 0) {
ball.position.x = w - 100;
}
if (ball.position.x < 0 && ball.velocity.x < 0) {
ball.position.x = 0;
}
if (ball.position.y > (h - 100) && ball.velocity.y > 0) {
ball.position.y = h - 100;
}
if (ball.position.y < 0 && ball.velocity.y < 0) {
ball.position.y = 0;
}
ball.style.top = ball.position.y + "px";
ball.style.left = ball.position.x + "px";
requestAnimationFrame(update); //KEEP ANIMATING
}
function init() {
ball = document.getElementById("ball");
dbg = document.getElementById("debug");
w = window.innerWidth;
h = window.innerHeight;
ball.style.left = (w / 2) - 50 + "px";
ball.style.top = (h / 2) - 50 + "px";
ball.velocity = {
x: 0,
y: 0
};
ball.position = {
x: 0,
y: 0
};
if (window.DeviceOrientationEvent) {
window.addEventListener("deviceorientation", function(event) {
ball.velocity.y = Math.round(event.beta);
ball.velocity.x = Math.round(event.gamma);
});
} else {
window.addEventListener("mousemove", function(event) {
my = event.clientY;
mx = event.clientX;
});
window.setInterval(function() {
var wy = window.outerHeight;
var wx = window.outerWidth;
var bcy = ball.position.y + 50; //ball center Y
var bcx = ball.position.x + 50; // ball center X
var dy = Math.round(((my - bcy) * 100 / wy) * 10000) / 10000;
var dx = Math.round(((mx - bcx) * 100 / wx) * 10000) / 10000;
ball.velocity.y = dy;
ball.velocity.x = dx;
dbg.innerHTML = 'deltaY:' + dy + ' deltaX:' + dx;
}, 100);
}
update();
}
init();
#ball {
-webkit-transition: all;
transition: all;
position: absolute;
width: 100px;
height: 100px;
border-radius: 50%;
background: red;
}
#debug {
position: absolute;
top: 5px;
left: 5px;
display: inline-block;
width: auto;
height: auto;
padding: 5px 10px;
z-index: 2;
color: rgb(255, 255, 255);
background: rgba(0, 0, 0, 0.75);
font-family: monospace;
font-size: 11px;
}
<div id="ball"></div>
<div id="debug">x:0 y:0</div>
Related
I have made a simple rocket with controls and I want it to stop when it hits the ground but for whatever reason the only number that I can use to test it against is 0. I have tried context.canvas.height - this.size.height because that is what I want it to be, but when I use that in the if statement the code does not work as desired. The goal is to be able to stop all of the rocket's movement when it hits the ground.
Here is my JavaScript code
(function () {
// the canvas constants
const canvas = document.getElementById('game');
const context = canvas.getContext('2d');
// setting the canvas size
context.canvas.width = window.innerWidth;
context.canvas.height = window.innerHeight;
// the game constants
const ROCKET_SIZE = { width: 20, height: 30 };
const ROCKET_POSITION = { x: 200, y: 200 };
const GRAVITY = 2;
const THRUST = 5;
const AFTERBURNER_THRUST = 20;
const INERTIAL_DAMPING = 0.98;
// the rocket ship class
class RocketShip {
constructor(size, position) {
this.color = 'white';
this.size = size;
this.position = position;
this.angle = 0;
this.engineOn = false;
this.afterburner = false;
this.inertialDampeners = false;
this.rotatingLeft = false;
this.rotatingRight = false;
this.velocity = {
x: 0,
y: 0,
};
}
draw() {
// the center of the rocket
const triangleCenterX = this.position.x + 0.5 * this.size.width;
const triangleCenterY = this.position.y + 0.5 * this.size.height;
context.save();
context.translate(triangleCenterX, triangleCenterY);
context.rotate(this.angle);
context.lineWidth = 1;
context.beginPath();
// drawing the delta rocket
context.moveTo(0, -this.size.height / 2);
context.lineTo(-this.size.width / 2, this.size.height / 2);
context.lineTo(this.size.width / 2, this.size.height / 2);
context.closePath();
context.strokeStyle = this.color;
context.stroke();
// drawing the engine if it is active
if (this.engineOn) {
const fireYPos = this.size.height / 2 + 5;
const fireXPos = this.size.width * 0.25;
context.beginPath();
context.moveTo(-fireXPos, fireYPos);
context.lineTo(fireXPos, fireYPos);
context.lineTo(0, fireYPos + Math.random() * 50);
context.lineTo(-fireXPos, fireYPos);
context.closePath();
context.fillStyle = 'orange';
context.fill();
}
// drawing the afterburner if it is active
if (this.afterburner) {
const fireYPos = this.size.height / 2 + 5;
const fireXPos = this.size.width * 0.25;
context.beginPath();
context.moveTo(-fireXPos, fireYPos);
context.lineTo(fireXPos, fireYPos);
context.lineTo(0, fireYPos + Math.random() * 100);
context.lineTo(-fireXPos, fireYPos);
context.closePath();
context.fillStyle = 'red';
context.fill();
}
context.restore();
}
moveRocket() {
// convert angle from degrees to radians
const degToRad = Math.PI / 180;
// changing the position of the rocket
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
// moving the rocket to the other side of the screen
if (this.position.x > context.canvas.width) {
this.position.x = 0;
}
if (this.position.x < 0) {
this.position.x = context.canvas.width;
}
if (this.position.y > context.canvas.height) {
this.position.y = 0;
}
if (this.position.y < 0) {
this.position.y = context.canvas.height;
}
// stopping the rocket if it hits the ground
if (this.position.y === context.canvas.height - this.size.height) {
this.velocity.y = -GRAVITY / 100;
this.velocity.x = 0;
}
// turning the rocket
if (this.rotatingLeft) {
this.angle -= degToRad;
}
if (this.rotatingRight) {
this.angle += degToRad;
}
// accelerating the rocket if the thrust is on
if (this.engineOn) {
this.velocity.x += (THRUST / 100) * Math.sin(this.angle);
this.velocity.y -= (THRUST / 100) * Math.cos(this.angle);
}
// accelerating the rocket if the afterburner is on
if (this.afterburner) {
this.velocity.x += (AFTERBURNER_THRUST / 100) * Math.sin(this.angle);
this.velocity.y -= (AFTERBURNER_THRUST / 100) * Math.cos(this.angle);
}
// decelerating the rocket if the inertial dampeners are on
if (this.inertialDampeners) {
this.velocity.x *= INERTIAL_DAMPING;
this.velocity.y *= INERTIAL_DAMPING;
}
// updating the rocket's velocity due to gravity
this.velocity.y += GRAVITY / 100;
}
}
const rocket = new RocketShip(ROCKET_SIZE, ROCKET_POSITION);
// handling the keyboard events
function handleKeyInput(event) {
const { keyCode, type } = event;
const isKeyDown = type === 'keydown';
if (keyCode === 37) {
rocket.rotatingLeft = isKeyDown;
}
if (keyCode === 39) {
rocket.rotatingRight = isKeyDown;
}
if (keyCode === 38) {
rocket.engineOn = isKeyDown;
}
if (keyCode === 32) {
rocket.afterburner = isKeyDown;
}
if (keyCode === 40) {
rocket.inertialDampeners = isKeyDown;
}
}
// resizing the screen
function onResize() {
context.canvas.width = window.innerWidth;
context.canvas.height = window.innerHeight;
}
function draw() {
// drawing space
context.fillStyle = '#111';
context.fillRect(0, 0, canvas.width, canvas.height);
rocket.moveRocket();
// drawing the rocket
rocket.draw();
// repeating the draw function
requestAnimationFrame(draw);
}
// adding event listeners to the webpage
document.addEventListener('keydown', handleKeyInput);
document.addEventListener('keyup', handleKeyInput);
document.addEventListener('resize', onResize);
// starting the game
draw();
})();
My HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Rocket</title>
<link rel=stylesheet href="styles/rocket2.css" >
</head>
<body id="body">
<canvas id="game"></canvas>
<script src="pscripts/rocket/rocket.js"></script>
<button class="info-btn">
Hello World
</button>
</body>
</html>
My CSS:
#body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #111;
}
#game {
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.info-btn {
opacity: 1;
position: absolute;
top: 2vh;
right: 2vw;
color: white;
background-color: dimgrey;
font-family: "Agency FB";
font-size: 2vh;
cursor: pointer;
}
.info-btn:hover {
background-color: #4f4f4f;
color: #c7c7c7;
}
.info {
background-color: #4f4f4f;
padding: 2%;
width: 98%;
height: 98%;
}
The code that I have been trying to use to stop the rocket when it reaches context.canvas.height - this.size.height is:
if (this.position.y === context.canvas.height - this.size.height) {
this.velocity.y = -GRAVITY / 100;
this.velocity.x = 0;
}
I am trying to check if the y position of the rocket is equal to the canvas height - the height of the rocket and if so I set the y velocity to the opposite of gravity over 100 so that it has no movement and I set the x velocity to 0.
Thank you to anyone who reads this and tries to help me.
Because you are using === your code will only work when they are equal which is almost never going to happen in an animation. The object could pass the given point between frames. You should use >=
if (this.position.y >= context.canvas.height - this.size.height) {
this.velocity.y = -GRAVITY / 100;
this.velocity.x = 0;
}
This question title is relatively self explanatory. I'd like the canvas to be in the background of the page while the page's content starts where it normally would. I tried making a DIV for each with their own Z-index but this didn't do anything.
I need to figure out a way to send the canvas back, I've made the body background colour red so there only needs to be two layers (snow and content) rather than the three (background included).
I just need it so that the content displays on top as it would with any normal page, the snow should be a background element that goes along with the scrolling of the page.
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
window.requestAnimationFrame = requestAnimationFrame;
})();
var flakes = [],
canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
flakeCount = 400,
mX = -100,
mY = -100
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function snow() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < flakeCount; i++) {
var flake = flakes[i],
x = mX,
y = mY,
minDist = 150,
x2 = flake.x,
y2 = flake.y;
var dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)),
dx = x2 - x,
dy = y2 - y;
if (dist < minDist) {
var force = minDist / (dist * dist),
xcomp = (x - x2) / dist,
ycomp = (y - y2) / dist,
deltaV = force / 2;
flake.velX -= deltaV * xcomp;
flake.velY -= deltaV * ycomp;
} else {
flake.velX *= .98;
if (flake.velY <= flake.speed) {
flake.velY = flake.speed
}
flake.velX += Math.cos(flake.step += .05) * flake.stepSize;
}
ctx.fillStyle = "rgba(255,255,255," + flake.opacity + ")";
flake.y += flake.velY;
flake.x += flake.velX;
if (flake.y >= canvas.height || flake.y <= 0) {
reset(flake);
}
if (flake.x >= canvas.width || flake.x <= 0) {
reset(flake);
}
ctx.beginPath();
ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
ctx.fill();
}
requestAnimationFrame(snow);
};
function reset(flake) {
flake.x = Math.floor(Math.random() * canvas.width);
flake.y = 0;
flake.size = (Math.random() * 3) + 2;
flake.speed = (Math.random() * 1) + 0.5;
flake.velY = flake.speed;
flake.velX = 0;
flake.opacity = (Math.random() * 0.5) + 0.3;
}
function init() {
for (var i = 0; i < flakeCount; i++) {
var x = Math.floor(Math.random() * canvas.width),
y = Math.floor(Math.random() * canvas.height),
size = (Math.random() * 3) + 2,
speed = (Math.random() * 1) + 0.5,
opacity = (Math.random() * 0.5) + 0.3;
flakes.push({
speed: speed,
velY: speed,
velX: 0,
x: x,
y: y,
size: size,
stepSize: (Math.random()) / 30,
step: 0,
opacity: opacity
});
}
snow();
};
canvas.addEventListener("mousemove", function(e) {
mX = e.clientX,
mY = e.clientY
});
window.addEventListener("resize",function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
})
init();
body, html{
margin:0;
padding:0;
overflow-x: hidden;
user-select: none;
-moz-appearance: none;
-webkit-appearance: none;
background-color: #E71D36;
}
.page {
min-width: 100%;
max-width: 100%;
z-index: -1;
}
.contentwrap {
min-width: 100%;
max-width: 100%;
z-index: 1;
}
.content {
min-width: 50%;
max-width: 50%;
margin-left: auto;
margin-right: auto;
text-align: center;
z-index: 1;
}
#media only screen and (max-width: 500px) {
.content {
min-width: 90%;
max-width: 90%;
margin-left: auto;
margin-right: auto;
text-align: center;
z-index: 1;
}
}
.canvas-holder {
z-index: 0;
}
.canvas {
z-index: -1;
}
<div class="page">
<div class-"canvas-holder">
<canvas id="canvas">
</canvas>
</div>
<div class="content">
<h1>Content is below the canvas</h1>
</div>
</div>
Any tips would be appreciated.
Use position: absolute for the canvas and content. I've made some other changes to .content css to center the text (and added class="canvas" to the canvas html). I also removed z-index as it's not needed if you use absolute positioning.
You asked in a comment:
Any ideas how to make the canvas the height of the page, not just the
window. That'd be appreciated too
One option is to use position: fixed which will keep the canvas position fixed as the page scrolls.
Please see updated snippet.
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
window.requestAnimationFrame = requestAnimationFrame;
})();
var flakes = [],
canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
flakeCount = 400,
mX = -100,
mY = -100
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function snow() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < flakeCount; i++) {
var flake = flakes[i],
x = mX,
y = mY,
minDist = 150,
x2 = flake.x,
y2 = flake.y;
var dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)),
dx = x2 - x,
dy = y2 - y;
if (dist < minDist) {
var force = minDist / (dist * dist),
xcomp = (x - x2) / dist,
ycomp = (y - y2) / dist,
deltaV = force / 2;
flake.velX -= deltaV * xcomp;
flake.velY -= deltaV * ycomp;
} else {
flake.velX *= .98;
if (flake.velY <= flake.speed) {
flake.velY = flake.speed
}
flake.velX += Math.cos(flake.step += .05) * flake.stepSize;
}
ctx.fillStyle = "rgba(255,255,255," + flake.opacity + ")";
flake.y += flake.velY;
flake.x += flake.velX;
if (flake.y >= canvas.height || flake.y <= 0) {
reset(flake);
}
if (flake.x >= canvas.width || flake.x <= 0) {
reset(flake);
}
ctx.beginPath();
ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
ctx.fill();
}
requestAnimationFrame(snow);
};
function reset(flake) {
flake.x = Math.floor(Math.random() * canvas.width);
flake.y = 0;
flake.size = (Math.random() * 3) + 2;
flake.speed = (Math.random() * 1) + 0.5;
flake.velY = flake.speed;
flake.velX = 0;
flake.opacity = (Math.random() * 0.5) + 0.3;
}
function init() {
for (var i = 0; i < flakeCount; i++) {
var x = Math.floor(Math.random() * canvas.width),
y = Math.floor(Math.random() * canvas.height),
size = (Math.random() * 3) + 2,
speed = (Math.random() * 1) + 0.5,
opacity = (Math.random() * 0.5) + 0.3;
flakes.push({
speed: speed,
velY: speed,
velX: 0,
x: x,
y: y,
size: size,
stepSize: (Math.random()) / 30,
step: 0,
opacity: opacity
});
}
snow();
};
canvas.addEventListener("mousemove", function(e) {
mX = e.clientX,
mY = e.clientY
});
window.addEventListener("resize",function(){
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
})
init();
body, html{
margin:0;
padding:0;
overflow-x: hidden;
user-select: none;
-moz-appearance: none;
-webkit-appearance: none;
background-color: #E71D36;
}
.page {
min-width: 100%;
max-width: 100%;
}
.contentwrap {
min-width: 100%;
max-width: 100%;
}
.content {
min-width: 100%;
max-width: 100%;
margin-left: auto;
margin-right: auto;
text-align: center;
position: absolute;
left: 0;
right: 0;
}
#media only screen and (max-width: 500px) {
.content {
min-width: 90%;
max-width: 90%;
margin-left: auto;
margin-right: auto;
text-align: center;
}
}
.canvas-holder {
}
.canvas {
position: fixed;
}
<div class="page">
<div class="canvas-holder">
<canvas id="canvas" class="canvas">
</canvas>
</div>
<div class="content">
<h1>Content is below the canvas</h1>
<p style="height: 900px;"></p>
</div>
</div>
I've put together a simple jQuery script to create a radial gradient that follows the mouse with a delay, but since it's in a mousemove function, when the mouse stops moving the gradient doesn't catch up. Is there a simple way to make the gradient catch up with the mouse when the mouse stops without writing a function that's constantly running?
var xPos = 0;
var yPos = 0;
var dX = 0;
var dY = 0;
var repeater;
$(document).mousemove(function(event) {
windowWidth = $(window).width();
windowHeight = $(window).height();
mouseXpercentage = Math.round(event.pageX / windowWidth * 100);
mouseYpercentage = Math.round(event.pageY / windowHeight * 100);
dX = mouseXpercentage - xPos;
dY = mouseYpercentage - yPos;
xPos += (dX / 50);
yPos += (dY / 50);
$('.rgradient').css('background', 'radial-gradient(at ' + xPos + '% ' + yPos + '%, #e6e6e6, #1e1e1e)');
});
.rgradient {
position: fixed;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background: #1e1e1e;
background: radial-gradient( at center, #e6e6e6 #1e1e1e);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rgradient"></div>
You can use requestAnimationFrame(), as it only runs once for each frame:
var xPos = 0;
var yPos = 0;
var dX = 0;
var dY = 0;
var mouseRaf = null;
var gradMoveRaf = null;
$(document).mousemove(function(event) {
if (!mouseRaf) {
mouseRaf = requestAnimationFrame(function() {
windowWidth = $(window).width();
windowHeight = $(window).height();
mouseXpercentage = Math.round(event.pageX / windowWidth * 100);
mouseYpercentage = Math.round(event.pageY / windowHeight * 100);
dX = mouseXpercentage - xPos;
dY = mouseYpercentage - yPos;
mouseRaf = null;
});
}
if (!gradMoveRaf) {
gradMoveRaf = requestAnimationFrame(gradMove);
}
});
function gradMove() {
xPos += (dX / 50);
yPos += (dY / 50);
$('.rgradient').css('background', 'radial-gradient(at ' + xPos + '% ' + yPos + '%, #e6e6e6, #1e1e1e)');
var absX = Math.abs(mouseXpercentage - xPos);
var absY = Math.abs(mouseYpercentage - yPos);
if (absX < 1 && absY < 1) {
gradMoveRaf = null;
console.log("stop");
} else {
gradMoveRaf = requestAnimationFrame(gradMove);
console.log("repeat");
}
}
.rgradient {
position: fixed;
top: 0px;
left: 0px;
height: 100%;
width: 100%;
background: #1e1e1e;
background: radial-gradient(at center, #e6e6e6 #1e1e1e);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rgradient"></div>
I make an object which has drag and resize. But I want this object dimension and position changes saved on the same where I left. Whenever I open the or reload the page I want the object position and resizing saved wherever I left last time.
How can I do this?
HTML Code is
<div id="pane">
<div id="title">Resize, Drag or Snap Me!</div>
</div>
<div id="ghostpane"></div>
CSS Code is
body {
overflow: hidden;
}
#pane {
position: absolute;
width: 45%;
height: 45%;
top: 20%;
left: 20%;
margin: 0;
padding: 0;
z-index: 99;
border: 2px solid purple;
background: #fefefe;
}
#title {
font-family: monospace;
background: purple;
color: white;
font-size: 24px;
height: 30px;
text-align: center;
}
#ghostpane {
background: #999;
opacity: 0.2;
width: 45%;
height: 45%;
top: 20%;
left: 20%;
position: absolute;
margin: 0;
padding: 0;
z-index: 98;
-webkit-transition: all 0.25s ease-in-out;
-moz-transition: all 0.25s ease-in-out;
-ms-transition: all 0.25s ease-in-out;
-o-transition: all 0.25s ease-in-out;
transition: all 0.25s ease-in-out;
}
JS Code is
"use strict";
// Minimum resizable area
var minWidth = 60;
var minHeight = 40;
// Thresholds
var FULLSCREEN_MARGINS = -10;
var MARGINS = 4;
// End of what's configurable.
var clicked = null;
var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;
var rightScreenEdge, bottomScreenEdge;
var preSnapped;
var b, x, y;
var redraw = false;
var pane = document.getElementById('pane');
var ghostpane = document.getElementById('ghostpane');
function setBounds(element, x, y, w, h) {
element.style.left = x + 'px';
element.style.top = y + 'px';
element.style.width = w + 'px';
element.style.height = h + 'px';
}
function hintHide() {
setBounds(ghostpane, b.left, b.top, b.width, b.height);
ghostpane.style.opacity = 0;
// var b = ghostpane.getBoundingClientRect();
// ghostpane.style.top = b.top + b.height / 2;
// ghostpane.style.left = b.left + b.width / 2;
// ghostpane.style.width = 0;
// ghostpane.style.height = 0;
}
// Mouse events
pane.addEventListener('mousedown', onMouseDown);
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
// Touch events
pane.addEventListener('touchstart', onTouchDown);
document.addEventListener('touchmove', onTouchMove);
document.addEventListener('touchend', onTouchEnd);
function onTouchDown(e) {
onDown(e.touches[0]);
e.preventDefault();
}
function onTouchMove(e) {
onMove(e.touches[0]);
}
function onTouchEnd(e) {
if (e.touches.length ==0) onUp(e.changedTouches[0]);
}
function onMouseDown(e) {
onDown(e);
e.preventDefault();
}
function onDown(e) {
calc(e);
var isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;
clicked = {
x: x,
y: y,
cx: e.clientX,
cy: e.clientY,
w: b.width,
h: b.height,
isResizing: isResizing,
isMoving: !isResizing && canMove(),
onTopEdge: onTopEdge,
onLeftEdge: onLeftEdge,
onRightEdge: onRightEdge,
onBottomEdge: onBottomEdge
};
}
function canMove() {
return x > 0 && x < b.width && y > 0 && y < b.height
&& y < 30;
}
function calc(e) {
b = pane.getBoundingClientRect();
x = e.clientX - b.left;
y = e.clientY - b.top;
onTopEdge = y < MARGINS;
onLeftEdge = x < MARGINS;
onRightEdge = x >= b.width - MARGINS;
onBottomEdge = y >= b.height - MARGINS;
rightScreenEdge = window.innerWidth - MARGINS;
bottomScreenEdge = window.innerHeight - MARGINS;
}
var e;
function onMove(ee) {
calc(ee);
e = ee;
redraw = true;
}
function animate() {
requestAnimationFrame(animate);
if (!redraw) return;
redraw = false;
if (clicked && clicked.isResizing) {
if (clicked.onRightEdge) pane.style.width = Math.max(x, minWidth) + 'px';
if (clicked.onBottomEdge) pane.style.height = Math.max(y, minHeight) + 'px';
if (clicked.onLeftEdge) {
var currentWidth = Math.max(clicked.cx - e.clientX + clicked.w, minWidth);
if (currentWidth > minWidth) {
pane.style.width = currentWidth + 'px';
pane.style.left = e.clientX + 'px';
}
}
if (clicked.onTopEdge) {
var currentHeight = Math.max(clicked.cy - e.clientY + clicked.h, minHeight);
if (currentHeight > minHeight) {
pane.style.height = currentHeight + 'px';
pane.style.top = e.clientY + 'px';
}
}
hintHide();
return;
}
if (clicked && clicked.isMoving) {
if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
// hintFull();
setBounds(ghostpane, 0, 0, window.innerWidth, window.innerHeight);
ghostpane.style.opacity = 0.2;
} else if (b.top < MARGINS) {
// hintTop();
setBounds(ghostpane, 0, 0, window.innerWidth, window.innerHeight / 2);
ghostpane.style.opacity = 0.2;
} else if (b.left < MARGINS) {
// hintLeft();
setBounds(ghostpane, 0, 0, window.innerWidth / 2, window.innerHeight);
ghostpane.style.opacity = 0.2;
} else if (b.right > rightScreenEdge) {
// hintRight();
setBounds(ghostpane, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
ghostpane.style.opacity = 0.2;
} else if (b.bottom > bottomScreenEdge) {
// hintBottom();
setBounds(ghostpane, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
ghostpane.style.opacity = 0.2;
} else {
hintHide();
}
if (preSnapped) {
setBounds(pane,
e.clientX - preSnapped.width / 2,
e.clientY - Math.min(clicked.y, preSnapped.height),
preSnapped.width,
preSnapped.height
);
return;
}
// moving
pane.style.top = (e.clientY - clicked.y) + 'px';
pane.style.left = (e.clientX - clicked.x) + 'px';
return;
}
// This code executes when the mouse moves without clicking
// style cursor
if (onRightEdge && onBottomEdge || onLeftEdge && onTopEdge) {
pane.style.cursor = 'nwse-resize';
} else if (onRightEdge && onTopEdge || onBottomEdge && onLeftEdge) {
pane.style.cursor = 'nesw-resize';
} else if (onRightEdge || onLeftEdge) {
pane.style.cursor = 'ew-resize';
} else if (onBottomEdge || onTopEdge) {
pane.style.cursor = 'ns-resize';
} else if (canMove()) {
pane.style.cursor = 'move';
} else {
pane.style.cursor = 'default';
}
}
animate();
function onUp(e) {
calc(e);
if (clicked && clicked.isMoving) {
// Snap
var snapped = {
width: b.width,
height: b.height
};
if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
// hintFull();
setBounds(pane, 0, 0, window.innerWidth, window.innerHeight);
preSnapped = snapped;
} else if (b.top < MARGINS) {
// hintTop();
setBounds(pane, 0, 0, window.innerWidth, window.innerHeight / 2);
preSnapped = snapped;
} else if (b.left < MARGINS) {
// hintLeft();
setBounds(pane, 0, 0, window.innerWidth / 2, window.innerHeight);
preSnapped = snapped;
} else if (b.right > rightScreenEdge) {
// hintRight();
setBounds(pane, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
preSnapped = snapped;
} else if (b.bottom > bottomScreenEdge) {
// hintBottom();
setBounds(pane, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
preSnapped = snapped;
} else {
preSnapped = null;
}
hintHide();
}
clicked = null;
}
Demo Testing link
Use sessionStorage or localStorage
I'm doing this assignment where I have to use pure javascript to make a div appear from the side of the screen without having the browser expand. This is what I have so far:
function moveImg() {
var div = document.getElementsByTagName('div')[0];
var pos = 500;
var id = setInterval(Move, 500);
function Move() {
if (pos <= 0) {
clearInterval(id);
} else {
pos++;
div.style.right = pos + 'px';
div.style.top = pos + 'px';
}
}
}
moveImg()
div {
width: 50px;
height: 50px;
background: tomato;
}
<div></div>
I'd use transform generally.
I've done some maths too, I've commented to code but feel free to ask if there's anything you need help understanding.
function moveImg() {
var div = document.getElementsByTagName('div')[0];
var posX = document.body.clientWidth - div.offsetWidth; // start position for X
var posY = document.body.clientHeight - div.offsetHeight; // start position for Y
var tarX = posX / 2; // end position for X
var tarY = posY / 2; // end position for Y
var time = 5; // how many seconds should the animation take
var fps = 60; // frames per second, heigher is smoother but requires more power
var stepX = ((posX - tarX) / (time * fps)); // how far X should move each frame
var stepY = ((posY - tarY) / (time * fps)); // how far Y should move each frame
var id = setInterval(Move, (1000 / fps));
div.style.transform = "translate(" + posX + "px, " + posY + "px)";
div.style.opacity = "1";
function Move() {
if (posX <= tarX && posY <= tarY) {
clearInterval(id);
} else {
posX -= stepX;
posY -= stepY;
div.style.transform = "translate(" + posX + "px, " + posY + "px)";
}
}
}
moveImg();
body {
margin: 0;
width: 100vw;
height: 100vh;
}
div {
display: inline-block;
color: white;
padding: 15px 30px;
background: tomato;
opacity: 0;
}
<div>Example!</div>
Like what was said in the comments, you don't say in what direction you want your div to move, nor from which position it should start.
I've set the starting position of top:100, left:100 and reducing the top and left values by 1px each second:
function moveImg() {
var div = document.getElementsByTagName('div')[0];
var pos = 100;
var id = setInterval(Move, 500);
function Move() {
if (pos <= 0) {
clearInterval(id);
} else {
pos--;
div.style.left = pos + 'px';
div.style.top = pos + 'px';
}
}
}
moveImg()
div {
width: 50px;
height: 50px;
background: tomato;
position: relative;
top: 100px;
left: 100px;
}
<div></div>