How to Dynamically Move Div by Clicking and Dragging - javascript

I want to move div according to mouse position within the parent div after click on it.When we leave the mouse pointer then set the div position.
I have searched everywhere and it has led me to over-complicated ways of doing the same thing and involves the use of j-query. I need to strictly use javascript for what I am trying to do.
it's css code
body {
margin: 0px;
padding: 0px;
}
.crop-container{
width: 500px;
height: 500px;
border:5px solid black;
position: relative;
}
.crop-lense{
width: 100px;
height: 100px;
border: 5px dotted black;
position: relative;
z-index: 10;
resize: both;
background-color: transparent;
}
It's html code
<div class="crop-container" id="container" onmousemove="showCoords(event)">
<div class="crop-lense" id="lense">
</div>
</div>
It's javascript code
var lense = document.getElementById('lense');
var container = document.getElementById("container");
var lensemflag = false;
var x;
var y;
lense.addEventListener('mousedown',function(){
lensemflag = true;
console.log(lensemflag);
});
lense.addEventListener('mouseup',function(){
lensemflag = false;
console.log(lensemflag);
});
function showCoords(event) {
x = event.offsetX;
y = event.offsetY;
y = y - 50;
x = x - 50;
}
if(lensemflag==true){
setInterval(function() {
lense.style.top = y + 'px';
lense.style.left = x + 'px';
},
1);
}

Shortest answer:
var lense = document.getElementById("lense");
var container = document.getElementById("container");
var x;
var y;
lense.addEventListener("mousedown", function() {
lense.addEventListener("mousemove", showCoords)
});
lense.addEventListener("mouseup", removeListener);
lense.addEventListener("mouseout", removeListener);
function removeListener() {
lense.removeEventListener("mousemove", showCoords)
}
function showCoords(event) {
if(container.offsetWidth >= event.pageX + lense.offsetWidth / 2 + 10 &&
container.offsetHeight >= event.pageY + lense.offsetHeight / 2 + 10 &&
event.pageX - lense.offsetWidth / 2 > 0 &&
event.pageY - lense.offsetHeight / 2 > 0){
x = event.pageX - lense.offsetWidth / 2;
y = event.pageY - lense.offsetHeight / 2;
lense.style.top = y + "px";
lense.style.left = x + "px";
}
}
body {
margin: 0px;
padding: 0px;
}
.crop-container{
width: 500px;
height: 500px;
border:5px solid black;
position: relative;
}
.crop-lense{
width: 100px;
height: 100px;
border: 5px dotted black;
position: relative;
z-index: 10;
resize: both;
background-color: transparent;
t
}
<div class="crop-container" id="container">
<div class="crop-lense" id="lense">
</div>
</div>

Related

Play button follow cursor in a div

I have found this codepen https://codepen.io/plankton/pen/aGejYq working good as expected.
I have an element that follows the cursor. But I don't know how limit it to a div and when the cursor goes in this div, this element goes smoothly to the cursor. If I leave from the div, just the element returns to his spot. Just like in the video in this web https://obys.agency/
If It can be done with JavaScript alone it's ok for me.
jQuery(document).ready(function() {
var mouseX = 0,
mouseY = 0;
var xp = 0,
yp = 0;
$(document).mousemove(function(e) {
mouseX = e.pageX - 30;
mouseY = e.pageY - 30;
});
setInterval(function() {
xp += ((mouseX - xp) / 6);
yp += ((mouseY - yp) / 6);
$("#circle").css({
left: xp + 'px',
top: yp + 'px'
});
}, 20);
});
body,
html {
position: relative;
height: 100%;
width: 100%;
margin: 0;
background-color: #000000;
}
.circle {
position: absolute;
border: solid 1px #ccc;
width: 60px;
height: 60px;
border-radius: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="circle" class="circle"></span>
Here's what I came up with.
jQuery(document).ready(function() {
const constraint = document.getElementById('constraint');
const circle = document.getElementById('circle');
var mouseX = 0, mouseY = 0;
var xp = 0, yp = 0;
$(document).mousemove(function(e){
if (e.target === constraint || (e.target === circle && e.pageX >= 0 && e.pageX <= 300 && e.pageY >= 0 && e.pageY <= 300)) {
mouseX = e.pageX - 30;
mouseY = e.pageY - 30;
} else {
mouseX = 0;
mouseY = 0;
}
});
setInterval(function(){
xp += ((mouseX - xp)/6);
yp += ((mouseY - yp)/6);
$("#circle").css({left: xp +'px', top: yp +'px'});
}, 20);
});
#import url(https://fonts.googleapis.com/css?family=Roboto:400,900);
body, html {
position: relative;
height: 100%;
width : 100%;
margin: 0;
background-color: #000000;
}
.circle {
position: absolute;
border: solid 1px #ccc;
width: 60px;
height: 60px;
border-radius: 50%;
}
.constraint {
position: absolute;
width: 300px;
height: 300px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<div id="constraint" class="constraint">
<span id="circle" class="circle"></span>
</div>

Fill in overlapping circle area

I have two circles that intersect and I want to make the intersecting area have a color, even when the two circles are transparent. I thought I could find some way to do this with css mix-blend-mode property but I have had no success with it.
Of course, I could make the circles have color and decrease their opacity, but I want them to be either white or transparent, where only the overlapped area gets background color.
I want the intersecting area to be able to change dynamically because one circle will follow the mouse.
Here is the codepen for that.
I'm not sure where to start on this, if css has some technique or if it will have to be done with jquery.
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true)/2;
var d2 = c2.outerWidth(true)/2;
// centers of first circle
var x1 = c1.offset().left + c1.width()/2;
var y1 = c1.offset().top + c1.height()/2;
// centers of second circle
var x2 = c2.offset().left + c2.width()/2;
var y2 = c2.offset().top + c2.height()/2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = c1.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
var d = (b*b+c*c-a*a)/(2*c);
var h = Math.sqrt((b*b) - (d*d));
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1;
var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1;
var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1;
var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({ top: y3-5, left: x3-5});
i2.offset({ top: y4-5, left: x4-5});
} calc();
});
body {
background: #fff;
}
.overlap {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
overflow: none;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
}
.circle::after,
.cursor::after {
display: block;
content: '';
height: 1px;
background: #c9d3ff;
position: absolute;
top: 50%;
left: 0;
right: 0;
}
.circle::before,
.cursor::before {
display: block;
content: '';
width: 1px;
background: #c9d3ff;
position: absolute;
left: 50%;
top: 0;
bottom: 0;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>
One way you can approach this is by adding a "inner-cursor" circle inside the main circle. Based on mouse movement it will move with the main cursor given the illusion of overlap.
In this case, the background color of the intersecting circles will not matter. Also, you do not have to worry about mix-blend-mode since the inner cursor has a background color and is hidden. It is only viewed if the mouse hovers over the main circle.
See this example:
$(document).mousemove(function(e) {
// elements
let cursor = $('.cursor');
let innerCursor = $('.inner-cursor');
let c2 = $('.circle');
let pos = {
left: e.pageX - 25,
top: e.pageY - 20
};
cursor.css(pos);
innerCursor.css({
left: pos.left - c2.offset().left,
top: pos.top - c2.offset().top
});
// circles
// radius
var d1 = cursor.outerWidth(true) / 2;
var d2 = c2.outerWidth(true) / 2;
// centers of first circle
var x1 = cursor.offset().left + cursor.width() / 2;
var y1 = cursor.offset().top + cursor.height() / 2;
// centers of second circle
var x2 = c2.offset().left + c2.width() / 2;
var y2 = c2.offset().top + c2.height() / 2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = cursor.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
var d = (b * b + c * c - a * a) / (2 * c);
var h = Math.sqrt((b * b) - (d * d));
// console.log(a, b, c, d, h);
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2 - x1) * d / c + (y2 - y1) * h / c + x1;
var y3 = (y2 - y1) * d / c - (x2 - x1) * h / c + y1;
var x4 = (x2 - x1) * d / c - (y2 - y1) * h / c + x1;
var y4 = (y2 - y1) * d / c + (x2 - x1) * h / c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({
top: y3 - 5,
left: x3 - 5
});
i2.offset({
top: y4 - 5,
left: x4 - 5
});
}
calc();
});
body {
background: #fff;
}
.clip {
display: inline-block;
background: blue;
height: 50px;
width: 50px;
border-radius: 50%;
clip-path: ellipse(50px 50px at 50% 0%);
position: absolute;
left: 750px;
top: 40px;
}
.cursor {
left: 750px;
top: 40px;
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
overflow: none;
mix-blend-mode: multiply;
background: rgba(100, 100, 100, 0.1);
}
.circle {
background: rgba(100, 100, 100, 0.1);
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
overflow: hidden;
}
.circle::after,
.cursor::after {
display: block;
content: '';
height: 1px;
background: #c9d3ff;
position: absolute;
top: 50%;
left: 0;
right: 0;
}
.circle::before,
.cursor::before {
display: block;
content: '';
width: 1px;
background: #c9d3ff;
position: absolute;
left: 50%;
top: 0;
bottom: 0;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
.inner-cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
background: green;
left: 50%;
top: 50%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<span class="clip"></span>
<div class="circle">
<div class='inner-cursor'></div>
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
</div>
On easy idea using only CSS is to consider a radial-gradient as background using background-attachement:fixed. You apply this background to the cursor element and you make its dimension/position the same as the fixed element.
All you need to add in your code is:
background:radial-gradient(circle,blue 100px,transparent 100px) fixed no-repeat
I have also optimized the code to remove the line you draw with pseudo element to consider linear-gradient
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true)/2;
var d2 = c2.outerWidth(true)/2;
// centers of first circle
var x1 = c1.offset().left + c1.width()/2;
var y1 = c1.offset().top + c1.height()/2;
// centers of second circle
var x2 = c2.offset().left + c2.width()/2;
var y2 = c2.offset().top + c2.height()/2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = c1.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
var d = (b*b+c*c-a*a)/(2*c);
var h = Math.sqrt((b*b) - (d*d));
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1;
var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1;
var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1;
var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({ top: y3-5, left: x3-5});
i2.offset({ top: y4-5, left: x4-5});
} calc();
});
body {
background: #fff;
margin:0;
}
*{
box-sizing:border-box;
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
radial-gradient(circle,blue 100px,transparent 101px) fixed,
yellow;
background-repeat:no-repeat;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
#f2f2f2;
background-repeat:no-repeat;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>
And if the circle is not in the middle you simply adjust the position.
$(document).mousemove(function(e) {
$('.cursor').eq(0).css({
left: e.pageX - 25,
top: e.pageY - 20
});
// circles
var c1 = $('.cursor');
var c2 = $('.circle');
// radius
var d1 = c1.outerWidth(true)/2;
var d2 = c2.outerWidth(true)/2;
// centers of first circle
var x1 = c1.offset().left + c1.width()/2;
var y1 = c1.offset().top + c1.height()/2;
// centers of second circle
var x2 = c2.offset().left + c2.width()/2;
var y2 = c2.offset().top + c2.height()/2;
var i1 = c2.find('.inter1');
var i2 = c2.find('.inter2');
var o = c1.find('.overlap');
function calc() {
var a = d2;
var b = d1;
var c = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
var d = (b*b+c*c-a*a)/(2*c);
var h = Math.sqrt((b*b) - (d*d));
if (d < 0 || $.isNumeric(h)) {
c2.css('border-color', 'red');
} else {
c2.css('border-color', 'black');
}
var x3 = (x2-x1)*d/c + (y2-y1)*h/c + x1;
var y3 = (y2-y1)*d/c - (x2-x1)*h/c + y1;
var x4 = (x2-x1)*d/c - (y2-y1)*h/c + x1;
var y4 = (y2-y1)*d/c + (x2-x1)*h/c + y1;
if ($.isNumeric(h)) {
i1.show();
i2.show();
} else {
i1.hide();
i2.hide();
}
i1.offset({ top: y3-5, left: x3-5});
i2.offset({ top: y4-5, left: x4-5});
} calc();
});
body {
background: #fff;
margin:0;
}
*{
box-sizing:border-box;
}
.cursor {
height: 50px;
width: 50px;
border-radius: 50%;
position: absolute;
pointer-events: none;
z-index: 999;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
radial-gradient(circle at 20% 50%,blue 100px,transparent 101px) fixed
yellow;
background-repeat:no-repeat;
}
.circle {
border-radius: 50%;
position: absolute;
top: 50%;
left: 20%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
border: 1px solid black;
outline: 1px solid #c9d3ff;
background:
linear-gradient(#c9d3ff,#c9d3ff) center/100% 1px,
linear-gradient(#c9d3ff,#c9d3ff) center/1px 100%,
#f2f2f2;
background-repeat:no-repeat;
}
.inter {
width: 10px;
height: 10px;
background: black;
border-radius: 50%;
position: absolute;
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cursor">
</div>
<div class="circle">
<div class="inter1 inter"></div>
<div class="inter2 inter"></div>
<div>
We basically use the same value of top/left to have the following:
radial-gradient(circle at [left] [top],blue [radius],transparent [radius]);
I add 1px to transparent to avoid the jagged edge
If you feel comfortable with HTML <canvas> element it's probably your best friend for this type of task, I doubt there's a CSS way to achieve what you want.
(If there is a CSS way, it's probably going to be lot more complicated and have much slower perfomance than doing it with canvas anyway)
You can take a look at the code below to be inspired (source and live example)
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body data-rsssl=1>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var offset = 50;
/*
* save() allows us to save the canvas context before
* defining the clipping region so that we can return
* to the default state later on
*/
context.save();
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.clip();
// draw blue circle inside clipping region
context.beginPath();
context.arc(x - offset, y - offset, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'blue';
context.fill();
// draw yellow circle inside clipping region
context.beginPath();
context.arc(x + offset, y, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'yellow';
context.fill();
// draw red circle inside clipping region
context.beginPath();
context.arc(x, y + offset, radius, 0, 2 * Math.PI, false);
context.fillStyle = 'red';
context.fill();
/*
* restore() restores the canvas context to its original state
* before we defined the clipping region
*/
context.restore();
context.beginPath();
context.arc(x, y, radius, 0, 2 * Math.PI, false);
context.lineWidth = 10;
context.strokeStyle = 'blue';
context.stroke();
</script>
</body>
</html>

Change color of the div shown in the window

I'm trying to change the colors of the divs from skyblue to yellow, when a specific div appears OR goes through the middle of the window. I have been building my own logic which works fine when I scroll the page up and down slowly. But it doesn't work when I scroll the page fast. I have inserted a button which takes the page to the fourth div (Box - 5) from the 100 divs. When the fourth div appears the background color does not switch, I have the keep scrolling up and down for my logic to change the fourth background color. The button is placed at the bottom of the page.
So I need help in making a better logic to changing the div's background color when the div is at or goes through the middle of the window, no matter the page is being scrolled fast or slow OR the page being
directly shifted to a specific div. Thanks
My index.html:
window.onbeforeunload = function() {
this.scrollTo(0, 0);
}
var content = document.getElementById("content"),
current = 0;
for (var y = 0; y < 100; y++) {
var box = document.createElement("div");
box.id = "box";
box.innerHTML = "Box - " + (y + 1);
content.appendChild(box);
}
content.children[current].style.backgroundColor = "yellow";
window.onscroll = function() {
if (this.oldScroll > this.scrollY) {
if (current >= 1) {
var previous_box = content.children[current - 1];
if ((this.scrollY + this.innerHeight / 2) < previous_box.offsetTop + previous_box.clientHeight) {
content.children[current].style.backgroundColor = "skyblue";
current--;
content.children[current].style.backgroundColor = "yellow";
}
}
} else {
if (current < 99) {
var next_box = content.children[current + 1];
if ((this.scrollY + this.innerHeight / 2) > next_box.offsetTop) {
content.children[current].style.backgroundColor = "skyblue";
current++;
content.children[current].style.backgroundColor = "yellow";
}
}
}
this.oldScroll = this.scrollY;
}
document.querySelector("button").onclick = function() {
var y = content.children[4].offsetTop - (content.children[4].clientHeight / 4);
window.scrollTo(0, y);
};
body {
margin: 0;
}
#navigation {
min-width: 620px;
background-color: blue;
width: 100%;
height: 50px;
z-index: 1;
position: fixed;
top: 0;
}
#box {
position: relative;
height: 75%;
width: 100%;
margin: 15% auto 15% auto;
color: black;
background-color: skyblue;
border: black 1px solid;
font-size: 50px;
text-align: center;
}
button {
margin: 0% auto 15% auto;
left: 50%;
}
<div id="navigation"></div>
<div id="content"></div>
<button>GO TO BOX 5</button>
window.onbeforeunload = function() {
this.scrollTo(0, 0);
}
var content = document.getElementById("content"),
current = 0;
for (var y = 0; y < 100; y++) {
var box = document.createElement("div");
box.id = "box";
box.innerHTML = "Box - " + (y + 1);
content.appendChild(box);
}
content.children[current].style.backgroundColor = "yellow";
window.onscroll = function() {
for(var i=0;i<content.children.length;i++){
var top = content.children[i]. getBoundingClientRect().top;
var height = top+content.children[i].clientHeight;
var halfWindow = window.innerHeight*0.5;
if(top<halfWindow&&height>halfWindow){
content.children[i].style.backgroundColor = "skyblue";
}
else{
content.children[i].style.backgroundColor = "yellow";
}
}
}
document.querySelector("button").onclick = function() {
var y = content.children[4].offsetTop - (content.children[4].clientHeight / 4);
window.scrollTo(0, y);
};
body {
margin: 0;
}
#navigation {
min-width: 620px;
background-color: blue;
width: 100%;
height: 50px;
z-index: 1;
position: fixed;
top: 0;
}
#box {
position: relative;
height: 75%;
width: 100%;
margin: 15% auto 15% auto;
color: black;
background-color: skyblue;
border: black 1px solid;
font-size: 50px;
text-align: center;
}
button {
margin: 0% auto 15% auto;
left: 50%;
}
<div id="navigation"></div>
<div id="content"></div>
<button>GO TO BOX 5</button>

Javascript div box that follow cursor position

I'm trying to create a circle navigation button to follow mouse movement when the cursor is inside a certain box.
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
pro.addEventListener("mouseover", function() {
var e = window.event;
var x = e.clientX;
var y = e.clientY;
cer.style.top = y + "px";
cer.style.left = x + "px";
cer.style.transition = "2s";
});
pro.addEventListener("mouseout", function() {
cer.style.top = "15px";
cer.style.left = "15px";
});
#prova {
width: 200px;
height: 200px;
border: 1px solid black;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 90px;
position: absolute;
left: 15px;
top: 15px;
}
#innercircle {
width: 120px;
height: 120px;
position: relative;
left: 40px;
top: 30px;
border: 1px solid red;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
</div>
</div>
so it actually follows the first position of the mouse inside the black bordered box, i want it to update the cursor positioning every time and follow it, also i don't want the red circle to go out the red box, any suggestion? please javascript only not jquery, thanks!
The main problem is your usage of window.event and wrong event handlers.
Here's a solution that uses standard event handling:
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
var proR = pro.getBoundingClientRect();
var cirR = cer.getBoundingClientRect();
// radii
var rW = (cirR.right - cirR.left) / 2;
var rH = (cirR.bottom - cirR.top) / 2;
// page coords of center
var oX = (proR.right + proR.left) / 2;
var oY = (proR.bottom + proR.top) / 2;
var x, y;
// max movement
var max = 15;
function setPos(x, y) {
cer.style.left = (x + oX - rW) + "px";
cer.style.top = (y + oY - rH) + "px";
}
pro.addEventListener("mouseleave", function() {
setPos(0, 0);
});
pro.addEventListener("mousemove", function(e) {
// 0,0 is at center
x = e.clientX - oX;
y = e.clientY - oY;
// limit to max
if (x < -max) x = -max;
if (x > max) x = max;
if (y < -max) y = -max;
if (y > max) y = max;
// set circle position
setPos(x, y);
});
setPos(0, 0);
#prova {
display: inline-block;
border: 1px solid black;
padding: 40px;
}
#innercircle {
width: 120px;
height: 120px;
border: 1px solid red;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 50%;
transition: .5s;
position: absolute;
pointer-events: none;
}
#prova,
#innercircle,
#cerchio {
box-sizing: border-box;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
</div>
</div>
I've also changed the calculation to
determine the x,y values such that the center of the area is (0, 0)
limit the values to a set boundary
add back the offset to position the circle
Your main problem is that you're using 'mouseover'. This event only activates when the mouse enters the element. This way, if works the first time you move over the rectangle, or when you move between the black and red rectangles.
If you use 'mousemove', it works right.
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
pro.addEventListener("mousemove", function() {
var e = window.event;
var x = e.clientX;
var y = e.clientY;
cer.style.top = y + "px";
cer.style.left = x + "px";
cer.style.transition = "2s";
});
pro.addEventListener("mouseout", function() {
cer.style.top = "15px";
cer.style.left = "15px";
});
#prova {
width: 200px;
height: 200px;
border: 1px solid black;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 90px;
position: absolute;
left: 15px;
top: 15px;
}
#innercircle {
width: 120px;
height: 120px;
position: relative;
left: 40px;
top: 30px;
border: 1px solid red;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>
</div>
</div>
"mousemove" is the event you want to track for this as you want the position of the mouse as it moves inside the element. You should also pass the event as a callback to the event handler
I also fixed the positioning using the getBoundingClientRect() method.
var cer = document.getElementById('cerchio');
var pro = document.getElementById('prova');
var innerC = document.getElementById('innercircle');
innerC.addEventListener("mousemove", function(e) {
var square = this.getBoundingClientRect();
var squareX = square.x;
var squareY = square.y;
var squareWidth = square.width;
var squareHeight = square.height;
var mouseX = e.clientX;
var mouseY= e.clientY;
var x = e.clientX;
var y = e.clientY;
cer.style.top = (-squareY + mouseY - (squareHeight / 2 - 15)) + "px";
cer.style.left = (-squareX + mouseX - (squareWidth / 2 - 15)) + "px";
cer.style.transition = "2s";
});
innerC.addEventListener("mouseout", function() {
cer.style.top = "15px";
cer.style.left = "15px";
});
#prova {
width: 200px;
height: 200px;
border: 1px solid black;
}
#cerchio {
width: 90px;
height: 90px;
border: 1px solid red;
border-radius: 90px;
position: absolute;
z-index: -1;
left: 15px;
top: 15px;
}
#innercircle {
width: 120px;
height: 120px;
position: relative;
z-index: 2;
left: 40px;
top: 30px;
border: 1px solid red;
}
<div id="prova">
<div id="innercircle">
<div id="cerchio"></div>

Smoke Trail Effect - Javascript

How can one make a smooth smoke trail effect with Javascript, out of the code I attached? The trail should follow an object, but have the position the object had a moment ago. The code I attached does have some sort of trail effect, but it is not smooth. Can give the trail a position using something like this: position:trail = position:object, 5 ms ago?
var left = parseInt(document.getElementById("thingy").style.left);
setInterval(fly, 10);
function fly() {
if (left > 300) {
left = 300;
};
left++;
document.getElementById("thingy").style.left = left + "px";
}
setInterval(trail, 100);
function trail() {
document.getElementById("trail").style.left = left + "px";
}
<div id="thingy" style="position:absolute; top:100px; left: 0px; width: 100px; height: 100px; background-color:#000000;"></div>
<div id="trail" style="position:absolute; top:125px; left: 0px; width: 50px; height: 50px; background-color:#CCCCCC; z-index: -10;"></div>
If it is possible I would like to stay out of jQuery.
This solution clones the element each time it moves.
CSS3 transitions are used on the cloned nodes' background to simulate a smoke trail.
The code ensures there are never more than 100 cloned nodes.
var thingy= document.getElementById('thingy'),
left = thingy.offsetLeft,
shadows= [],
delta= 4;
setInterval(fly, 10);
function fly() {
var shadow= thingy.cloneNode();
shadow.classList.add('shadow');
shadow.style.backgroundColor= 'silver';
document.body.appendChild(shadow);
setTimeout(function() {
shadow.style.backgroundColor= 'white';
},100);
shadows.push(shadow);
if(shadows.length>100) {
shadows[0].parentNode.removeChild(shadows[0]);
shadows.shift();
}
if(left+delta > document.body.offsetWidth-thingy.offsetWidth || left < 0) {
delta= -delta;
}
left+= delta;
thingy.style.left = left + 'px';
}
body {
margin: 0;
padding: 0;
}
#thingy {
position: absolute;
top: 100px;
left: 0px;
width: 100px;
height: 100px;
background-color: orange;
border-radius: 50%;
}
.shadow {
transition: all 1s;
z-index: -1;
}
<div id="thingy"></div>
Update
For a "smokier" effect, you can use random values for the cloned nodes' width, height, transition, etc., like I've done in this Snippet:
var thingy= document.getElementById('thingy'),
tleft = thingy.offsetLeft,
ttop = thingy.offsetTop,
smokes= [],
deltaX= deltaY= 2;
setInterval(fly, 10);
function fly() {
if(Math.random()>0.5) {
var smoke= thingy.cloneNode();
smoke.classList.add('smoke');
smoke.style.background= 'gray';
smoke.style.opacity= 0.2;
smoke.style.transition= Math.random()+'s';
smoke.style.width= Math.random()*thingy.offsetWidth+'px';
smoke.style.height= Math.random()*thingy.offsetHeight+'px';
smoke.style.marginTop= smoke.offsetHeight+'px';
smoke.style.borderRadius= (Math.random()*25+25)+'%';
document.body.appendChild(smoke);
setTimeout(function() {
smoke.style.opacity= 0;
},100);
smokes.push(smoke);
if(smokes.length>20) {
smokes[0].parentNode.removeChild(smokes[0]);
smokes.shift();
}
}
if(tleft+deltaX > document.body.offsetWidth-thingy.offsetWidth || tleft < 0) {
deltaX= -deltaX;
}
if(ttop +deltaY > document.body.offsetHeight-thingy.offsetHeight || ttop < 0) {
deltaY= -deltaY;
}
tleft+= deltaX;
ttop += deltaY;
thingy.style.left = tleft + 'px';
thingy.style.top = ttop + 'px';
}
body {
margin: 0;
padding: 0;
background: black;
height: 100vh;
}
#thingy {
position: absolute;
top: 100px;
left: 0px;
width: 100px;
height: 100px;
background-color: orange;
border-radius: 50%;
}
.smoke {
z-index: -1;
}
<div id="thingy"></div>

Categories

Resources