Collision fires only for the last DIV - javascript

I'm trying to trigger some events when one DOM element collide with another. A have a bunch of objects, how many I don't know, so I take them like querySelectorAll and then I'm trying to loop them via foreach. Everything works fine except - the even fires only for the last element. Does anyone know why?
Thank you!
Codepen — https://codepen.io/PavelLaptev/pen/ZEQPaRa
const isCollide = (a, b) => {
var x1 = a.offsetLeft;
var y1 = a.offsetTop;
var h1 = a.clientHeight;
var w1 = a.clientWidth;
var b1 = y1 + h1;
var r1 = x1 + w1;
var x2 = b.offsetLeft;
var y2 = b.offsetTop;
var h2 = b.clientHeight;
var w2 = b.clientWidth;
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
return true;
};
const interactElements = document.querySelectorAll(".object");
const cursor = document.getElementById("cursor");
console.log(interactElements);
document.addEventListener("mousemove", (e) => {
let cursorPos = {
x: e.x - 20 / 2,
y: e.y - 20 / 2,
};
cursor.style.top = `${cursorPos.y}px`;
cursor.style.left = `${cursorPos.x}px`;
interactElements.forEach((item) => {
if (isCollide(cursor, item)) {
cursor.style.background = "blue";
} else {
cursor.style.background = "red";
}
});
})
.objects {
width: 300px;
height: 300px;
background: rgba(0,0,0,0.2);
}
.object {
width: 60px;
height: 60px;
background: rgba(0,0,0,0.5);
margin: 20px;
}
#cursor {
width: 20px;
height: 20px;
background: rgba(0,0,0,1);
border-radius: 20px;
position: absolute;
}
<div id="cursor"></div>
<div class="objects">
<div class="object"></div>
<div class="object"></div>
<div class="object"></div>
</div>

Change this:
interactElements.forEach((item) => {
if (isCollide(cursor, item)) {
cursor.style.background = "blue";
} else {
cursor.style.background = "red";
}
});
to:
cursor.style.background = Array.from(interactElements).some((item) => isCollide(cursor, item)) ? 'blue' : 'red'
const isCollide = (a, b) => {
var x1 = a.offsetLeft;
var y1 = a.offsetTop;
var h1 = a.clientHeight;
var w1 = a.clientWidth;
var b1 = y1 + h1;
var r1 = x1 + w1;
var x2 = b.offsetLeft;
var y2 = b.offsetTop;
var h2 = b.clientHeight;
var w2 = b.clientWidth;
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2) return false;
return true;
};
const interactElements = document.querySelectorAll(".object");
const cursor = document.getElementById("cursor");
console.log(interactElements);
document.addEventListener("mousemove", (e) => {
let cursorPos = {
x: e.x - 20 / 2,
y: e.y - 20 / 2,
};
cursor.style.top = `${cursorPos.y}px`;
cursor.style.left = `${cursorPos.x}px`;
cursor.style.background = Array.from(interactElements).some((item) => isCollide(cursor, item)) ? 'blue' : 'red'
})
.objects {
width: 300px;
height: 300px;
background: rgba(0,0,0,0.2);
}
.object {
width: 60px;
height: 60px;
background: rgba(0,0,0,0.5);
margin: 20px;
}
#cursor {
width: 20px;
height: 20px;
background: rgba(0,0,0,1);
border-radius: 20px;
position: absolute;
}
<div id="cursor"></div>
<div class="objects">
<div class="object"></div>
<div class="object"></div>
<div class="object"></div>
</div>

Related

Get alert and get text in the bottom

i am trying to get alert from the main big circle alone. The alert should not come from the small circles.
How to get alert from the big circle alone? and Text for small circle should be in the bottom the each circle. For me its showing in the top right corner of the circles. Can anyone help me to solve this thing?
Thanks in advance
var noop = function() {
return this;
};
function UserCanceledError() {
this.name = 'UserCanceledError';
this.message = 'User canceled dialog';
}
UserCanceledError.prototype = Object.create(Error.prototype);
function Dialog() {
this.setCallbacks(noop, noop);
}
Dialog.prototype.setCallbacks = function(okCallback, cancelCallback) {
this._okCallback = okCallback;
return this;
};
Dialog.prototype.waitForUser = function() {
var _this = this;
return new Promise(function(resolve, reject) {
_this.setCallbacks(resolve, reject);
});
};
Dialog.prototype.show = noop;
Dialog.prototype.hide = noop;
function PromptDialog() {
Dialog.call(this);
this.el = document.getElementById('dialog');
this.messageEl = this.el.querySelector('.message');
this.okButton = this.el.querySelector('button.ok');
this.attachDomEvents();
}
PromptDialog.prototype = Object.create(Dialog.prototype);
PromptDialog.prototype.attachDomEvents = function() {
var _this = this;
this.okButton.addEventListener('click', function() {
_this.hide();
console.log('Ok clicked!!');
});
};
PromptDialog.prototype.show = function(message) {
this.messageEl.innerHTML = '' + message;
this.el.className = '';
return this;
};
PromptDialog.prototype.hide = function() {
this.el.className = 'hidden';
return this;
};
var prompt = new PromptDialog();
const getBall = (x, y, dx, dy, r, color) => ({x, y, dx, dy, r, color});
const drawBall = (ball, ctx) => {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2, false);
ctx.fillStyle = ball.collider ? "red" : ball.color;
ctx.fill();
ctx.closePath();
}
const updatePos = (ball, containerR) => {
ball.x += ball.dx;
ball.y += ball.dy;
const dx = ball.x - containerR;
const dy = ball.y - containerR;
if (Math.sqrt(dx * dx + dy * dy) >= containerR - ball.r) {
const v = Math.sqrt(ball.dx * ball.dx + ball.dy * ball.dy);
const angleToCollisionPoint = Math.atan2(-dy, dx);
const oldAngle = Math.atan2(-ball.dy, ball.dx);
const newAngle = 2 * angleToCollisionPoint - oldAngle;
ball.dx = -v * Math.cos(newAngle);
ball.dy = v * Math.sin(newAngle);
}
}
function makeArea(domid, radius, ballsNumber) {
const ctx = document.getElementById(domid).getContext("2d");
const containerR = radius;
const size = radius * 2
ctx.canvas.width = ctx.canvas.height = size;
ctx.globalAlpha = 1;
let balls = [];
for(var i=0 ; i<ballsNumber ; ++i) {
const r = Math.random()*radius*0.5;
const t = Math.random()*Math.PI*2;
balls.push(getBall(radius + Math.cos(t)*r, radius + Math.sin(t)*r, 0.1, 0.1, 5, "Green"));
}
return {
ctx: ctx,
radius: radius,
balls: balls
}
}
const collides = (a, b) => (Math.hypot(Math.abs(a.x - b.x), Math.abs(a.y - b.y)) < (a.r + b.r));
const areas = [
makeArea("Canvas", 150, 10, true),
makeArea("Canvas1", 80, 4, false),
makeArea("Canvas2", 80, 4, false),
makeArea("Canvas3", 80, 4, false),
makeArea("Canvas4", 80, 4, false)
];
function engine() {
//console.clear(); // Clear console test messages
mydiv.textContent =" ";
areas.forEach((area) =>{
const ctx = area.ctx;
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
area.balls.forEach((a, ai) => {
a.collider = undefined;
area.balls.forEach((b, bi) => {
if (bi === ai) return; // Don't look at self
if (collides(a, b)) a.collider = b; // Store the colliding B ball
});
if (a.collider) { // If ball has a collider:
//mydiv.textContent = ("Alert");
//beep();
prompt.show('ALERT!!!!! Not Maintaining Distance')
.waitForUser()
.then(function(name) {
output.innerHTML = '' + name;
})
.catch(function(e) {
console.log('Unknown error', e);
})
.finally(function() {
prompt.hide();
});
//console.log(`${a.color[0]} → ← ${a.collider.color[0]}`);
}
updatePos(a, area.radius);
drawBall(a, ctx);
});
});
requestAnimationFrame(engine);
}
engine();
canvas {
background: #eee;
margin: 0 auto;
border-radius: 50%;
box-shadow: 0 0 0 4px #000;
}
.row {
display: flex;
}
.Row {
display: flex;
flex-direction: row;
margin-left: 40%;
margin-top: 8%;
float: right;
}
#Canvas1, #Canvas2, #Canvas3, #Canvas4 {
background: #eee;
border-radius: 50%;
border: solid 0px #000;
margin: 2px;
}
<div class="Row">
<div>
<canvas id="Canvas"></canvas>
</div>
<div>
<div class="row">
<canvas id="Canvas1"></canvas>
<span> xyz</span>
<canvas id="Canvas2"></canvas>
<span> xyz1</span>
</div>
<div class="row">
<canvas id="Canvas3"></canvas>
<span> xyz2</span>
<canvas id="Canvas4"></canvas>
<span>xyz3</span>
</div>
</div>
</div>
<div id="mydiv"></div>
<div id="dialog" class="hidden">
<div class="message"></div>
<div>
<button class="ok">OK</button>
</div>
</div>
Regarding your second question:
The <span>s are just children of .row, like the canvas is. You could "group" them with the canvas and make their position absolute:
/* important stuff: */
.group {
position: relative;
}
.group span {
position: absolute;
left: 0;
right: 0;
bottom: 5px;
text-align: center;
}
/* only for testing: */
#canvas1 {
background: #eee;
width: 100%;
height: 100%
}
.row {
width: 200px;
height: 200px;
display: flex;
}
<div class="row">
<div class="group">
<canvas id="canvas1"></canvas>
<span>xyz</span>
</div>
</div>
About the alert from the big circle:
If you're extending your forEach on all areas with a variable for the index ...
areas.forEach((area, areaindex) => {
... you could check for index zero later:
if (a.collider && areaindex == 0)

Tried making a button, that takes you to google page

i have a html script with button and onclick function script that should take me to google.com, but it doesn't seem to work. Been stuck with this for hours. Im also new to HTML.
Tried everything. Line 336 and 353 should be the needed content. And line 136 should be the button itself. I don't understand whats wrong. Anyone ever have had this issue?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="shortcut icon" type="image/x-icon/text/javascript" href="https://static.codepen.io/assets/favicon/favicon-aec34940fbc1a6e787974dcd360f2c6b63348d4b1f4e06c77743096d55480f33.ico" />
<link rel="mask-icon" type="" href="https://static.codepen.io/assets/favicon/logo-pin-8f3771b1072e3c38bd662872f6b673a722f4b3ca2421637d5596661b4e2132cc.svg" color="#111" />
<title>SpyBanter - SpyBanter's Official WebSite</title>
<style type="text/css">
body {
overflow: hidden;
margin: 0;
}
body:before {
content: '';
background: #c4252a url(http://subtlepatterns2015.subtlepatterns.netdna-cdn.com/patterns/cheap_diagonal_fabric.png);
background-blend-mode: multiply;
mix-blend-mode: multiply;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 10;
}
canvas {
opacity: 0;
transition: 1s opacity cubic-bezier(0.55, 0, 0.1, 1);
}
canvas.ready {
opacity: 0.4;
}
.intro {
position: absolute;
padding: 20px;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
left: 50%;
top: 50%;
text-align: center;
color: #fafafa;
z-index: 10;
width: 100%;
max-width: 700px;
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
text-shadow: 0px 5px 20px black;
}
.intro h1 {
font-size: 40px;
font-weight: 300;
letter-spacing: 2px;
}
.intro p {
letter-spacing: 1px;
line-height: 24px;
}
#btnclose {
background-color: indianred;
border-color: darkred;
}
}
#btnnup:hover, #btnsisu:hover, #btncmd:hover {
background-color: #3e8e41;
}
#btnnup:active, #btnsisu:active, #btncmd:active {
background-color: #3e8e41;
box-shadow: 0 5px #666;
transform: translateY(4px);
}
#btnsisu {
left: 108px;
top: 105px;
}
#btncmd {
left: -311px;
top: -88px;
}
#content {
width: 100%;
height: auto;
min-height: 580px;
}
</style>
<script>
window.console = window.console || function(t) {};
</script>
<script>
if (document.location.search.match(/type=embed/gi)) {
window.parent.postMessage("resize", "*");
}
</script>
</head>
<body translate="no">
<canvas id="canvas" data-image="http://unsplash.it/g/450/200/?random=1"></canvas>
<div class="intro">
<h1>Interactive mosaic background</h1>
<p>Had to do this effect in a recent project and wanted to share it with you :). To change the background, edit the data-image on the canvas tag. You can also change the magnet effect intensity by changing the magnet variable</p>
<button id="btncmd">Videos</button>
</div>
<script src="https://static.codepen.io/assets/common/stopExecutionOnTimeout-de7e2ef6bfefd24b79a3f68b414b87b8db5b08439cac3f1012092b2290c719cd.js"></script>
<script type="application/javascript">
(function () {
// Variables
var Photo, addListeners, canvas, createGrid, ctx, gridItem, grids, height, img, imgInfo, imgSrc, imgs, init, magnet, mouse, populateCanvas, render, resizeCanvas, rotateAndPaintImage, updateMouse, useGrid, width;
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
width = canvas.width = window.innerWidth;
height = canvas.height = window.innerHeight;
imgSrc = canvas.dataset.image;
img = new Image();
useGrid = true;
imgInfo = {};
imgs = [];
grids = [];
magnet = 2000;
mouse = {
x: 1,
y: 0 };
init = function () {
addListeners();
img.onload = function (e) {
var numberToShow;
// Check for firefox.
imgInfo.width = e.path ? e.path[0].width : e.target.width;
imgInfo.height = e.path ? e.path[0].height : e.target.height;
numberToShow = Math.ceil(window.innerWidth / imgInfo.width) * Math.ceil(window.innerHeight / imgInfo.height);
if (useGrid) {
createGrid();
}
populateCanvas(numberToShow * 4);
canvas.classList.add('ready');
return render();
};
return img.src = imgSrc;
};
addListeners = function () {
window.addEventListener('resize', resizeCanvas);
window.addEventListener('mousemove', updateMouse);
return window.addEventListener('touchmove', updateMouse);
};
updateMouse = function (e) {
mouse.x = e.clientX;
return mouse.y = e.clientY;
};
resizeCanvas = function () {
width = canvas.width = window.innerWidth;
return height = canvas.height = window.innerHeight;
};
populateCanvas = function (nb) {
var i, p, results;
i = 0;
results = [];
while (i <= nb) {
p = new Photo();
imgs.push(p);
results.push(i++);
}
return results;
};
createGrid = function () {
var c, grid, i, imgScale, item, j, k, l, r, ref, ref1, ref2, results, x, y;
imgScale = 0.5;
grid = {
row: Math.ceil(window.innerWidth / (imgInfo.width * imgScale)),
cols: Math.ceil(window.innerHeight / (imgInfo.height * imgScale)),
rowWidth: imgInfo.width * imgScale,
colHeight: imgInfo.height * imgScale };
for (r = j = 0, ref = grid.row; 0 <= ref ? j < ref : j > ref; r = 0 <= ref ? ++j : --j) {
x = r * grid.rowWidth;
for (c = k = 0, ref1 = grid.cols; 0 <= ref1 ? k < ref1 : k > ref1; c = 0 <= ref1 ? ++k : --k) {
y = c * grid.colHeight;
item = new gridItem(x, y, grid.rowWidth, grid.colHeight);
grids.push(item);
}
}
results = [];
for (i = l = 0, ref2 = grids.length; 0 <= ref2 ? l < ref2 : l > ref2; i = 0 <= ref2 ? ++l : --l) {
results.push(grids[i].draw());
}
return results;
};
gridItem = function (x = 0, y = 0, w, h) {
this.draw = function () {
ctx.drawImage(img, x, y, w, h);
};
};
Photo = function () {
var TO_RADIANS, finalX, finalY, forceX, forceY, h, r, seed, w, x, y;
seed = Math.random() * (2.5 - 0.7) + 0.7;
w = imgInfo.width / seed;
h = imgInfo.height / seed;
x = window.innerWidth * Math.random();
finalX = x;
y = window.innerHeight * Math.random();
finalY = y;
console.log(`INIT Y :: ${finalY} || INIT X :: ${finalX}`);
r = Math.random() * (180 - -180) + -180;
forceX = 0;
forceY = 0;
TO_RADIANS = Math.PI / 180;
this.update = function () {
var distance, dx, dy, powerX, powerY, x0, x1, y0, y1;
x0 = x;
y0 = y;
x1 = mouse.x;
y1 = mouse.y;
dx = x1 - x0;
dy = y1 - y0;
distance = Math.sqrt(dx * dx + dy * dy);
powerX = x0 - dx / distance * magnet / distance;
powerY = y0 - dy / distance * magnet / distance;
forceX = (forceX + (finalX - x0) / 2) / 2.1;
forceY = (forceY + (finalY - y0) / 2) / 2.2;
x = powerX + forceX;
y = powerY + forceY;
};
this.draw = function () {
return rotateAndPaintImage(ctx, img, r * TO_RADIANS, x, y, w / 2, h / 2, w, h);
};
};
rotateAndPaintImage = function (context, image, angle, positionX, positionY, axisX, axisY, widthX, widthY) {
context.translate(positionX, positionY);
context.rotate(angle);
context.drawImage(image, -axisX, -axisY, widthX, widthY);
context.rotate(-angle);
return context.translate(-positionX, -positionY);
};
render = function () {
var x, y;
x = 0;
y = 0;
ctx.clearRect(0, 0, width, height);
while (y < grids.length) {
grids[y].draw();
y++;
}
while (x < imgs.length) {
imgs[x].update();
imgs[x].draw();
x++;
}
return requestAnimationFrame(render);
};
init();
}).call(this);
cmd = function () {
window.location.href = "https://www.google.com/";
}
function cmd() {
window.location.href = "https://www.google.com/";
}
btnclose.onclick = cmd;
btnnup.onclick = cmd;
btncmd.onclick = cmd;
//# sourceURL=coffeescript
//# sourceURL=pen.js
</script>
<script type="application/javascript">
window.onload = function() {
main.style.opacity = "1";
}
function show(){
main.style.opacity = "1";
}
function close() {
main.style.opacity = "0";
$.post('http://tt_help/close', JSON.stringify({
}));
}
function cmd() {
window.location.href = "https://www.google.com/";
}
function sisukord() {
let id = $(this).attr('content');
console.log(id)
let docs = `https://docs.google.com/document/d/e/2PACX-1vSXxzowHucTNRBwduXT-pDoGQT4blGJhOvgnzIYmpEe2DwU4mimf84RZ8orvUGpm2vPsPDdkkVAnFkq/pub?embedded=true${id}`;
$('#main iframe').attr('src', docs);
}
window.addEventListener('message', function(event) {
if (event.data.type == "open") {
main.style.opacity = "1";
}
});
btnclose.onclick = cmd;
btncmd.onclick = cmd;
btnsisu.onclick = cmd;
</script>
</body>
If you're trying to make a button that takes you to google.com, I would advise you to use an a tag, not a button tag. The tag automatically links you to your desired destination when clicked.
Example:
Example
If you want the link to look like a button, then simply look at the css options. I would advise you to look here: https://www.w3schools.com/css/css_link.asp
a {
background-image:linear-gradient(to bottom, lightblue, aquamarine);
padding:5px;
text-decoration:none;
color:black;
padding-right:50px;
padding-left:50px;
margin-top: 50px;
margin-left: 50px;
display: inline-block;
font-size:25px;
border-radius:5px;
box-shadow: 1px 1px green;
}
Example
If you are determined to use a <button> tag, then all you need to do is within that button tag add an onclick attribute. So, you would change your code to <button id="btncmd" onclick="cmd()">Videos</button>.
Example of what you want:
function cmd() {
window.location.href = "https://www.example.com/"; // I'm using example but you can use google.
}
<button id="btncmd" onclick="cmd()">Videos</button>
You did not define btncmd. Adding this line to your code solves the problem:
var btncmd = document.getElementById("btncmd");

I have a issue in my canvas. i want to change the color of particles. currently they are in black color. How i can change..?

I have a issue in my canvas. i want to change the color of particles. currently they are in black color. How i can change..?
here is my code please let me know if u have any solution.
I have a issue in my canvas. i want to change the color of particles. currently they are in black color. How i can change..?
here is my code please let me know if u have any solution. http://jsfiddle.net/gbcL0uks/
<head>
<title>
Text Particles
</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css" />
<link rel="stylesheet" href="https://cdn.bootcss.com/hover.css/2.3.1/css/hover-min.css">
<meta property="og:title" content="Text Particles" />
<meta property="og:description" content="Some cool canvas pixel manipulation" />
<meta property="og:image" content="http://william.hoza.us/images/text-small.png" />
<style>
#import url('https://fonts.googleapis.com/css?family=Bree+Serif');
body {
font-family: 'Bree Serif', serif;
}
.float {
position: absolute;
left: 20px;
}
.menu {
position: absolute;
top: 20px;
right: 20px;
cursor: pointer;
}
.fa-bars {
font-size: 24px;
border: 2px solid #333333;
padding: 12px;
transition: .4s;
}
.fa-bars:hover {
background: #333333;
color: #f7d600;
}
.overlay {
height: 100%;
width: 100%;
position: fixed;
z-index: 1;
top: 0;
left: -100%;
background-color: rgb(0, 0, 0);
background-color: rgba(0, 0, 0, 0.9);
overflow-x: hidden;
transition: 0.5s;
}
.overlay-content {
position: relative;
top: 50%;
width: 100%;
text-align: center;
margin-top: 30px;
transform: translate(0, -100%);
}
.overlay a {
padding: 8px;
text-decoration: none;
font-size: 6rem;
color: #818181;
display: inline-block;
transition: 0.3s;
margin: 0 3rem;
}
.overlay a:hover,
.overlay a:focus {
color: #f1f1f1;
}
.overlay .closebtn {
position: absolute;
top: 20px;
right: 0;
font-size: 60px;
}
#media screen and (max-height: 450px) {
.overlay a {
font-size: 20px
}
.overlay .closebtn {
font-size: 40px;
top: 15px;
right: 0;
}
}
</style>
</head>
<body style="margin:0px; background:#f7d600;">
<div class="float">
<h1>Herbialis</h1>
</div>
<!-- <div class="menu">
<i class="fa fa-bars"></i>
</div> -->
<div id="myNav" class="overlay">
×
<div class="overlay-content">
About
Products
Contact
</div>
</div>
<div class="menu">
<i class="fa fa-bars" onclick="openNav()"></i>
</div>
<canvas id="canv" onmousemove="canv_mousemove(event);" onmouseout="mx=-1;my=-1;">
you need a canvas-enabled browser, such as Google Chrome
</canvas>
<canvas id="wordCanv" width="500px" height="500px" style="border:1px solid black;display:none;">
</canvas>
<textarea id="wordsTxt" style="position:absolute;left:-100;top:-100;" onblur="init();" onkeyup="init();" onclick="init();"></textarea>
<script type="text/javascript">
var l = document.location + "";
l = l.replace(/%20/g, " ");
var index = l.indexOf('?t=');
if (index == -1) document.location = l + "?t=Hello world";
var pixels = new Array();
var canv = $('canv');
var ctx = canv.getContext('2d');
var wordCanv = $('wordCanv');
var wordCtx = wordCanv.getContext('2d');
var mx = -1;
var my = -1;
var words = "";
var txt = new Array();
var cw = 0;
var ch = 0;
var resolution = 1;
var n = 0;
var timerRunning = false;
var resHalfFloor = 0;
var resHalfCeil = 0;
function canv_mousemove(evt) {
mx = evt.clientX - canv.offsetLeft;
my = evt.clientY - canv.offsetTop;
}
function Pixel(homeX, homeY) {
this.homeX = homeX;
this.homeY = homeY;
this.x = Math.random() * cw;
this.y = Math.random() * ch;
//tmp
this.xVelocity = Math.random() * 10 - 5;
this.yVelocity = Math.random() * 10 - 5;
}
Pixel.prototype.move = function () {
var homeDX = this.homeX - this.x;
var homeDY = this.homeY - this.y;
var homeDistance = Math.sqrt(Math.pow(homeDX, 2) + Math.pow(homeDY, 2));
var homeForce = homeDistance * 0.01;
var homeAngle = Math.atan2(homeDY, homeDX);
var cursorForce = 0;
var cursorAngle = 0;
if (mx >= 0) {
var cursorDX = this.x - mx;
var cursorDY = this.y - my;
var cursorDistanceSquared = Math.pow(cursorDX, 2) + Math.pow(cursorDY, 2);
cursorForce = Math.min(10000 / cursorDistanceSquared, 10000);
cursorAngle = Math.atan2(cursorDY, cursorDX);
} else {
cursorForce = 0;
cursorAngle = 0;
}
this.xVelocity += homeForce * Math.cos(homeAngle) + cursorForce * Math.cos(cursorAngle);
this.yVelocity += homeForce * Math.sin(homeAngle) + cursorForce * Math.sin(cursorAngle);
this.xVelocity *= 0.92;
this.yVelocity *= 0.92;
this.x += this.xVelocity;
this.y += this.yVelocity;
}
function $(id) {
return document.getElementById(id);
}
function timer() {
if (!timerRunning) {
timerRunning = true;
setTimeout(timer, 33);
for (var i = 0; i < pixels.length; i++) {
pixels[i].move();
}
drawPixels();
wordsTxt.focus();
n++;
if (n % 10 == 0 && (cw != document.body.clientWidth || ch != document.body.clientHeight)) body_resize();
timerRunning = false;
} else {
setTimeout(timer, 10);
}
}
function drawPixels() {
var imageData = ctx.createImageData(cw, ch);
var actualData = imageData.data;
var index;
var goodX;
var goodY;
var realX;
var realY;
for (var i = 0; i < pixels.length; i++) {
goodX = Math.floor(pixels[i].x);
goodY = Math.floor(pixels[i].y);
for (realX = goodX - resHalfFloor; realX <= goodX + resHalfCeil && realX >= 0 && realX < cw; realX++) {
for (realY = goodY - resHalfFloor; realY <= goodY + resHalfCeil && realY >= 0 && realY < ch; realY++) {
index = (realY * imageData.width + realX) * 4;
actualData[index + 3] = 255;
}
}
}
imageData.data = actualData;
ctx.putImageData(imageData, 0, 0);
}
function readWords() {
words = $('wordsTxt').value;
txt = words.split('\n');
}
function init() {
readWords();
var fontSize = 200;
var wordWidth = 0;
do {
wordWidth = 0;
fontSize -= 5;
wordCtx.font = fontSize + "px sans-serif";
for (var i = 0; i < txt.length; i++) {
var w = wordCtx.measureText(txt[i]).width;
if (w > wordWidth) wordWidth = w;
}
} while (wordWidth > cw - 50 || fontSize * txt.length > ch - 50)
wordCtx.clearRect(0, 0, cw, ch);
wordCtx.textAlign = "center";
wordCtx.textBaseline = "middle";
for (var i = 0; i < txt.length; i++) {
wordCtx.fillText(txt[i], cw / 2, ch / 2 - fontSize * (txt.length / 2 - (i + 0.5)));
}
var index = 0;
var imageData = wordCtx.getImageData(0, 0, cw, ch);
for (var x = 0; x < imageData.width; x += resolution) //var i=0;i<imageData.data.length;i+=4)
{
for (var y = 0; y < imageData.height; y += resolution) {
i = (y * imageData.width + x) * 4;
if (imageData.data[i + 3] > 128) {
if (index >= pixels.length) {
pixels[index] = new Pixel(x, y);
} else {
pixels[index].homeX = x;
pixels[index].homeY = y;
}
index++;
}
}
}
pixels.splice(index, pixels.length - index);
}
function body_resize() {
cw = document.body.clientWidth;
ch = document.body.clientHeight;
canv.width = cw;
canv.height = ch;
wordCanv.width = cw;
wordCanv.height = ch;
init();
}
wordsTxt.focus();
wordsTxt.value = l.substring(index + 3);
resHalfFloor = Math.floor(resolution / 2);
resHalfCeil = Math.ceil(resolution / 2);
body_resize();
timer();
</script>
<script>
function openNav() {
document.getElementById("myNav").style.left = "0";
}
function closeNav() {
document.getElementById("myNav").style.left = "-100%";
}
</script>
</body>
</html>
Add 3 color components to image data. For example, for orange color:
for (realX = goodX - resHalfFloor; realX <= goodX + resHalfCeil && realX >= 0 && realX < cw; realX++) {
for (realY = goodY - resHalfFloor; realY <= goodY + resHalfCeil && realY >= 0 && realY < ch; realY++) {
index = (realY * imageData.width + realX) * 4;
actualData[index + 0] = 253; // Red component
actualData[index + 1] = 106; // Green component
actualData[index + 2] = 2; // Blue component
actualData[index + 3] = 255;
}
}

jQuery: mouse following element wont stick with cursor when scrolling

I have a small problem and I can't get it to fix.
I developed a element that is following the cursor and way it needs to function is that the border around the cursor needs to stick with the position of the cursor. But the problem I've got right now is that it won't stick when scrolling down.
You can check at the demo below what I mean.
The problem seems that it is not correctly checking the height of the page, thats why its not correctly positioning. Am I right?
const windowW = window.innerWidth;
const windowH = window.innerHeight;
const maxLength = Math.max(windowW, windowH);
const cursorWidth = 100;
const cursorR = cursorWidth >> 1;
const cursorDelay = 10;
const buttons = Array.from(document.querySelectorAll('.border-button'));
const cursor = {
el: document.querySelector('.border-cursor'),
x: windowW >> 1,
y: windowH >> 1,
scaleX: 1,
scaleY: 1,
};
const target = {
x: windowW >> 1,
y: windowH >> 1,
width: cursorWidth,
followMouse: true,
};
const norm = (val, max, min) => (val - min) / (max - min);
const toDegrees = r => r * (180 / Math.PI);
const distanceBetween = (v1, v2) => Math.sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y +- v2.y));
const loop = () => {
const destX = target.x - cursorR;
const destY = target.y - cursorR;
const newX = cursor.x + ((destX - cursor.x) / cursorDelay);
const newY = cursor.y + ((destY - cursor.y) / cursorDelay);
const angle = angleBetween(cursor.x, cursor.y, newX, newY);
if (target.followMouse) {
const distance = Math.abs(distanceBetween(target, cursor));
const scale = norm(distance, maxLength, cursorR);
cursor.scaleX = 1 + scale;
cursor.scaleY = 1 - scale;
} else {
const targetScale = target.width / cursorWidth;
cursor.scaleX += (targetScale - cursor.scaleX) / (cursorDelay / 2);
cursor.scaleY = cursor.scaleX;
}
cursor.x = newX;
cursor.y = newY;
cursor.el.style.transform = `translate(${cursor.x}px, ${cursor.y}px) rotate(${toDegrees(angle)}deg) scale(${cursor.scaleX}, ${cursor.scaleY})`;
requestAnimationFrame(loop);
};
const angleBetween = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1);
const onPointerMove = (e) => {
if (!target.followMouse) {
return;
}
const pointer = (e.touches && e.touches.length) ? e.touches[0] : e;
const { clientX: x, clientY: y } = pointer;
target.x = x;
target.y = y;
};
const onPointerOver = (e) => {
const btn = e.target;
const rect = btn.getBoundingClientRect();
target.followMouse = false;
target.x = rect.left + (rect.width >> 1);
target.y = rect.top + (rect.height >> 1);
target.width = Math.max(rect.width, rect.height) + 50;
};
const onPointerOut = () => {
target.followMouse = true;
target.width = cursorWidth;
};
document.body.addEventListener('mousemove', onPointerMove);
document.body.addEventListener('touchmove', onPointerMove);
buttons.forEach((btn) => {
btn.addEventListener('touchstart', onPointerOver);
btn.addEventListener('mouseover', onPointerOver);
btn.addEventListener('touchend', onPointerOut);
btn.addEventListener('mouseout', onPointerOut);
});
loop();
const windowW = window.innerWidth;
const windowH = window.innerHeight;
const maxLength = Math.max(windowW, windowH);
const cursorWidth = 100;
const cursorR = cursorWidth >> 1;
const cursorDelay = 10;
const buttons = Array.from(document.querySelectorAll('.border-button'));
const cursor = {
el: document.querySelector('.border-cursor'),
x: windowW >> 1,
y: windowH >> 1,
scaleX: 1,
scaleY: 1,
};
const target = {
x: windowW >> 1,
y: windowH >> 1,
width: cursorWidth,
followMouse: true,
};
const norm = (val, max, min) => (val - min) / (max - min);
const toDegrees = r => r * (180 / Math.PI);
const distanceBetween = (v1, v2) => Math.sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y +- v2.y));
const loop = () => {
const destX = target.x - cursorR;
const destY = target.y - cursorR;
const newX = cursor.x + ((destX - cursor.x) / cursorDelay);
const newY = cursor.y + ((destY - cursor.y) / cursorDelay);
const angle = angleBetween(cursor.x, cursor.y, newX, newY);
if (target.followMouse) {
const distance = Math.abs(distanceBetween(target, cursor));
const scale = norm(distance, maxLength, cursorR);
cursor.scaleX = 1 + scale;
cursor.scaleY = 1 - scale;
} else {
const targetScale = target.width / cursorWidth;
cursor.scaleX += (targetScale - cursor.scaleX) / (cursorDelay / 2);
cursor.scaleY = cursor.scaleX;
}
cursor.x = newX;
cursor.y = newY;
cursor.el.style.transform = `translate(${cursor.x}px, ${cursor.y}px) rotate(${toDegrees(angle)}deg) scale(${cursor.scaleX}, ${cursor.scaleY})`;
requestAnimationFrame(loop);
};
const angleBetween = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1);
const onPointerMove = (e) => {
if (!target.followMouse) {
return;
}
const pointer = (e.touches && e.touches.length) ? e.touches[0] : e;
const { clientX: x, clientY: y } = pointer;
target.x = x;
target.y = y;
};
const onPointerOver = (e) => {
const btn = e.target;
const rect = btn.getBoundingClientRect();
target.followMouse = false;
target.x = rect.left + (rect.width >> 1);
target.y = rect.top + (rect.height >> 1);
target.width = Math.max(rect.width, rect.height) + 50;
};
const onPointerOut = () => {
target.followMouse = true;
target.width = cursorWidth;
};
document.body.addEventListener('mousemove', onPointerMove);
document.body.addEventListener('touchmove', onPointerMove);
buttons.forEach((btn) => {
btn.addEventListener('touchstart', onPointerOver);
btn.addEventListener('mouseover', onPointerOver);
btn.addEventListener('touchend', onPointerOut);
btn.addEventListener('mouseout', onPointerOut);
});
loop();
html,
body {
margin: 0;
padding: 0;
}
.wrapper {
width: 100vw;
min-height: 1500px;
display: flex;
flex-direction: row;
align-items: center;
}
.container {
width: 100%;
display: flex;
padding: 0 1rem;
}
.cursor {
position: absolute;
z-index: 10;
width: 100px;
height: 100px;
border: 2px solid #23bfa0;
border-radius: 50%;
pointer-events: none;
}
.button {
padding: 1rem;
background-color: #23bfa0;
border: none;
box-shadow: 0 0 7px 0px rgba(0, 0, 0, 0.2);
color: white;
font-size: 1.2rem;
cursor: pointer;
transition: box-shadow 0.1s ease-in, transform 0.1s ease-in;
&--small {
padding: 0.75rem;
font-size: 0.75rem;
}
&:hover {
transform: translate(0%, -2px);
box-shadow: 0px 4px 9px 2px rgba(0, 0, 0, 0.2)
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="cursor border-cursor"></div>
<div class="wrapper">
<div class="container">
<button class="button button--small border-button">small</button>
<button class="button border-button">hover me</button>
<button class="button border-button">hover me more</button>
</div>
</div>
</body>
In onPointerMove, try replacing:
const { clientX: x, clientY: y } = pointer;
with:
const { pageX: x, pageY: y } = pointer;
Here's a good post explaining the differences between these values:
https://stackoverflow.com/a/9335517/965834
Also, change:
target.x = rect.left + (rect.width >> 1);
target.y = rect.top + (rect.height >> 1);
into:
target.x = window.scrollX + rect.left + (rect.width >> 1);
target.y = window.scrollY + rect.top + (rect.height >> 1);
This takes into account scrolling when calculating the position of your buttons.
Demo:
const windowW = window.innerWidth;
const windowH = window.innerHeight;
const maxLength = Math.max(windowW, windowH);
const cursorWidth = 100;
const cursorR = cursorWidth >> 1;
const cursorDelay = 10;
const buttons = Array.from(document.querySelectorAll('.border-button'));
const cursor = {
el: document.querySelector('.border-cursor'),
x: windowW >> 1,
y: windowH >> 1,
scaleX: 1,
scaleY: 1,
};
const target = {
x: windowW >> 1,
y: windowH >> 1,
width: cursorWidth,
followMouse: true,
};
const norm = (val, max, min) => (val - min) / (max - min);
const toDegrees = r => r * (180 / Math.PI);
const distanceBetween = (v1, v2) => Math.sqrt((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y +- v2.y));
const loop = () => {
const destX = target.x - cursorR;
const destY = target.y - cursorR;
const newX = cursor.x + ((destX - cursor.x) / cursorDelay);
const newY = cursor.y + ((destY - cursor.y) / cursorDelay);
const angle = angleBetween(cursor.x, cursor.y, newX, newY);
if (target.followMouse) {
const distance = Math.abs(distanceBetween(target, cursor));
const scale = norm(distance, maxLength, cursorR);
cursor.scaleX = 1 + scale;
cursor.scaleY = 1 - scale;
} else {
const targetScale = target.width / cursorWidth;
cursor.scaleX += (targetScale - cursor.scaleX) / (cursorDelay / 2);
cursor.scaleY = cursor.scaleX;
}
cursor.x = newX;
cursor.y = newY;
cursor.el.style.transform = `translate(${cursor.x}px, ${cursor.y}px) rotate(${toDegrees(angle)}deg) scale(${cursor.scaleX}, ${cursor.scaleY})`;
requestAnimationFrame(loop);
};
const angleBetween = (x1, y1, x2, y2) => Math.atan2(y2 - y1, x2 - x1);
const onPointerMove = (e) => {
if (!target.followMouse) {
return;
}
const pointer = (e.touches && e.touches.length) ? e.touches[0] : e;
const { pageX: x, pageY: y } = pointer;
target.x = x;
target.y = y;
};
const onPointerOver = (e) => {
const btn = e.target;
const rect = btn.getBoundingClientRect();
target.followMouse = false;
target.x = window.scrollX + rect.left + (rect.width >> 1);
target.y = window.scrollY + rect.top + (rect.height >> 1);
target.width = Math.max(rect.width, rect.height) + 50;
};
const onPointerOut = () => {
target.followMouse = true;
target.width = cursorWidth;
};
document.body.addEventListener('mousemove', onPointerMove);
document.body.addEventListener('touchmove', onPointerMove);
buttons.forEach((btn) => {
btn.addEventListener('touchstart', onPointerOver);
btn.addEventListener('mouseover', onPointerOver);
btn.addEventListener('touchend', onPointerOut);
btn.addEventListener('mouseout', onPointerOut);
});
loop();
html,
body {
margin: 0;
padding: 0;
}
.wrapper {
width: 100vw;
min-height: 1500px;
display: flex;
flex-direction: row;
align-items: center;
}
.container {
width: 100%;
display: flex;
padding: 0 1rem;
}
.cursor {
position: absolute;
z-index: 10;
width: 100px;
height: 100px;
border: 2px solid #23bfa0;
border-radius: 50%;
pointer-events: none;
}
.button {
padding: 1rem;
background-color: #23bfa0;
border: none;
box-shadow: 0 0 7px 0px rgba(0, 0, 0, 0.2);
color: white;
font-size: 1.2rem;
cursor: pointer;
transition: box-shadow 0.1s ease-in, transform 0.1s ease-in;
&--small {
padding: 0.75rem;
font-size: 0.75rem;
}
&:hover {
transform: translate(0%, -2px);
box-shadow: 0px 4px 9px 2px rgba(0, 0, 0, 0.2)
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="cursor border-cursor"></div>
<div class="wrapper">
<div class="container">
<button class="button button--small border-button">small</button>
<button class="button border-button">hover me</button>
<button class="button border-button">hover me more</button>
</div>
</div>
</body>

Check overlay for many divs issue

I want to check if some divs are overlaying. Here are the functions i'm using
function collision($div1, $div2) {
var x1 = $div1.offset().left;
var y1 = $div1.offset().top;
var h1 = $div1.outerHeight(true);
var w1 = $div1.outerWidth(true);
var b1 = y1 + h1;
var r1 = x1 + w1;
var x2 = $div2.offset().left;
var y2 = $div2.offset().top;
var h2 = $div2.outerHeight(true);
var w2 = $div2.outerWidth(true);
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2)
return false;
return true;
}
$("#flex[data-item-id]").each(function() {
var id_item = $(this).data('item-id');
var status = collision($('#c + id_item), $("#r" + id_item));
if (status) {
$('.here').css('background-color', 'red');
}
});
I don't know why but in console put ok true and false...exact where it needs but the if(status) won't work so well..
Like #Rory McCrossan just told, you are missing a ' in your selector.
Try this code:
function collision($div1, $div2) {
var x1 = $div1.offset().left;
var y1 = $div1.offset().top;
var h1 = $div1.outerHeight(true);
var w1 = $div1.outerWidth(true);
var b1 = y1 + h1;
var r1 = x1 + w1;
var x2 = $div2.offset().left;
var y2 = $div2.offset().top;
var h2 = $div2.outerHeight(true);
var w2 = $div2.outerWidth(true);
var b2 = y2 + h2;
var r2 = x2 + w2;
if (b1 < y2 || y1 > b2 || r1 < x2 || x1 > r2)
return false;
return true;
}
$.each( "#flex[data-item-id]" , function() {
var id_item = $(this).data('item-id');
var status = collision($('#c' + id_item), $("#r" + id_item));
if (status) {
$('.here').css('background-color', 'red');
}
});
EDIT: I adjusted the jQuery each function to the jQuery each documentation. I can't test if it's working untill you add your html code.
A working revision of your collision function, it checks for vertical overlap of both tops and bottoms in addition to horizontal overlaps to confirm an actual overlap.
function collision($div1, $div2) {
var x1 = $div1.offset().left,
y1 = $div1.offset().top,
b1 = $div1.outerHeight(true) + y1,
r1 = $div1.outerWidth(true) + x1;
var x2 = $div2.offset().left,
y2 = $div2.offset().top,
b2 = $div2.outerHeight(true) + y2,
r2 = $div2.outerWidth(true) + x2;
var v = false,
h = false,
collide = false;
if (b1 > y2 && b1 < b2) {
v = true;
}
if (b2 > y1 && b2 < b1) {
v = true;
}
// vertical overlap check
if (r1 > x2 && r1 < r2) {
h = true;
}
if (r2 > x1 && r2 < r1) {
h = true;
}
// horizontal overlap check
if (h && v) {
collide = true;
}
return collide
}
/*
$.each( "#flex[data-item-id]" , function() {
var id_item = $(this).data('item-id');
var status = collision($('#c' + id_item), $("#r" + id_item));
if (status) {
$('.here').css('background-color', 'red');
}
}); */
$("#monitor").text(collision($('#alpha'), $('#beta')));
// display the result
#alpha {
position: absolute;
left: 3em;
top: 2em;
width: 4em;
height: 4em;
background: #489;
}
#beta {
position: absolute;
left: 4em;
top: 4em;
width: 4em;
height: 4em;
background: #498;
}
#monitor {
position: fixed;
bottom: 1em;
left: 1em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="alpha"></div>
<div id="beta"></div>
<div id="monitor"></div>

Categories