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>
Related
I am making a cursor which always points to an object.
My transition-duration unfortunately makes the cursor lag on faster movements. How do I solve this issue without getting rid of the transition duration as it smoothes the movement? Are there any alternatives?
ps. I am a JS (JQuery) newbie so if you have any improvements for my code, please let me know.
jQuery(function($) {
let mousePos = {
x: 0,
y: 0
}
let lastMove = 0;
function onMouseMove(e) {
mousePos.x = e.pageX;
mousePos.y = e.pageY;
$(".cursor").setAngle(calcAngle(getCenter($(".light")), getCenter($(".cursor"))));
$(".cursor").setPos(e.pageX, e.pageY);
lastMove = Date.now();
}
//gets the center
function getCenter(container) {
let containerCenter = {
x: $(container).offset().left + $(container).width() / 2,
y: $(container).offset().top + $(container).height() / 2
};
return containerCenter;
}
//calculates an angle between two elements (obj2 is pointing towards obj1)
function calcAngle(obj1, obj2) {
let angle = Math.atan2(obj1.x - obj2.x, -(obj1.y - obj2.y)) * (180 / Math.PI);
return angle;
}
//sets the position
$.fn.setPos = function(x, y) {
this.css({
"left": (x - this.width() / 2) + "px",
"top": (y - this.height() / 2) + "px",
});
};
//sets the rotation of an element
$.fn.setAngle = function(angle) {
this.css({
"transform": "rotate(" + angle + "deg)",
"-webkit-transform": "rotate(" + angle + "deg)"
});
};
addEventListener("mousemove", onMouseMove);
});
body {
height: 100vh;
background: grey;
overflow: hidden;
}
.light {
position: absolute;
background-color: #fff;
height: 200px;
width: 200px;
border-radius: 50%;
left: 50%;
top: 0;
transform: translate(-50%, -50%);
}
.cursor {
background-color: white;
width: 20px;
height: 20px;
border: 1px solid white;
border-radius: 10%;
position: absolute;
transition-duration: 200ms;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<body>
<div class="light"></div>
<div class="cursor"></div>
</body>
I recommend using a canvas in the future for this applications
For now you could use transform instead of top and left
let mousePos = {
x: 0,
y: 0
}
let lastMove = 0;
function onMouseMove(e) {
mousePos.x = e.pageX;
mousePos.y = e.pageY;
angle = calcAngle(getCenter($(".light")), getCenter($(".cursor")));
$(".cursor").setTransform(e.pageX, e.pageY, angle);
lastMove = Date.now();
}
//gets the center
function getCenter(container) {
let containerCenter = {
x: $(container).offset().left + $(container).width() / 2,
y: $(container).offset().top + $(container).height() / 2
};
return containerCenter;
}
//calculates an angle between two elements (obj2 is pointing towards obj1)
function calcAngle(obj1, obj2) {
let angle = Math.atan2(obj1.x - obj2.x, -(obj1.y - obj2.y)) * (180 / Math.PI);
return angle;
}
//sets transform
$.fn.setTransform = function(x, y, a) {
x = x - this.width()
y = y - this.height()
this.css({
"transform": "translate(" + x + "px, " + y + "px) rotate(" + a + "deg)",
"-webkit-transform": "translate(" + x + "px, " + y + "px) rotate(" + a + "deg)",
});
};
addEventListener("mousemove", onMouseMove);
body {
height: 100vh;
background: grey;
overflow: hidden;
}
.light {
position: absolute;
background-color: #fff;
height: 200px;
width: 200px;
border-radius: 50%;
left: 50%;
top: 0;
transform: translate(-50%, -50%);
}
.cursor {
background-color: white;
width: 20px;
height: 20px;
border: 1px solid white;
border-radius: 10%;
position: absolute;
transition-duration: 100ms;
transition-timing-function: ease-out;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<body>
<div class="light"></div>
<div class="cursor"></div>
</body>
This question already has answers here:
Invert text color on mouse hover
(2 answers)
Closed 2 years ago.
When red cursor is hover on Works text, i want to change the Works text color black to blue and text will be zoom In on that red cursor area. anyone suggest me how to do this in JavaScript
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);
$(".cursor").css({left: xp +'px', top: yp +'px'});
}, 20);
});
h1{
text-align: center;
font-size: 5rem;
margin-top: 20%;
}
.cursor{
position: absolute;
background: red;
width: 100px;
height: 100px;
border-radius: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Works</h1>
<div class="cursor">
You should add pointer-events: none; to the cursor, so it doesn't interefer with the element below.
And then add Hover or whatever pseudoclass you need to colorize it.
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);
$(".cursor").css({left: xp +'px', top: yp +'px'});
}, 20);
});
h1{
text-align: center;
font-size: 5rem;
margin-top: 20%;
}
h1:hover {
color: red;
}
.cursor{
position: absolute;
background: red;
width: 100px;
height: 100px;
border-radius: 50px;
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Works</h1>
<div class="cursor">
Consider the following code example.
jQuery(function($) {
var mouseX = 0,
mouseY = 0,
xp = 0,
yp = 0;
function isOver(e, obj) {
var o = false,
x = e.pageX,
y = e.pageY;
var pos = obj.offset();
pos = {
x1: pos.left,
y1: pos.top,
x2: pos.left + obj.width(),
y2: pos.top + obj.height()
};
if ((x >= pos.x1 && x <= pos.x2) && (y >= pos.y1 && y <= pos.y2)) {
o = true;
}
return o;
}
function moveCursor(evt) {
mouseX = evt.pageX - 30;
mouseY = evt.pageY - 30;
xp += ((mouseX - xp) / 6);
yp += ((mouseY - yp) / 6);
$(".cursor").css({
left: xp + 'px',
top: yp + 'px'
});
if (isOver(evt, $("h1"))) {
$("h1").addClass("blue zoom");
} else {
$("h1").removeClass("blue zoom");
}
}
$(document).mousemove(moveCursor);
});
h1 {
text-align: center;
font-size: 5rem;
margin-top: 20%;
transform: scale(1);
}
.blue {
color: blue;
}
.zoom {
transform: scale(1.25);
}
.cursor {
position: absolute;
background: rgba(255, 0, 0, 0.45);
width: 100px;
height: 100px;
border-radius: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1>Works</h1>
<div class="cursor"></div>
It was not clear to me what you mean by "text will be zoom In on that red cursor area." I suspect you can transform the text maybe? At least this way you can trigger the zoom action you want.
This uses basic collision detection to determine if the mouse isOver() a specific element.
This question already has answers here:
Percent pie chart with css only
(3 answers)
Closed 3 years ago.
I want to create a circle that shows percent whit its border length like a
circular diagram but with border.
Like Have you seen https://pasteboard.co/IeLnpWt.jpg
you need svg in your html:
$(document).ready(function(){
$('circle.circle').each(function () {
var percent = Number($(this).data('value'));
var r = parseFloat($(this).css('r'));
var dasharray = parseFloat($(this).css('stroke-dasharray'));
var offset = dasharray - ((Math.PI*2*r) * (percent/100));
$(this).delay(1000).animate({strokeDashoffset: offset}, 1000);
});
});
.wrapper {
position: relative;
width: 60px;
height: 60px;
}
.bar {
position: relative;
transform: rotateZ(-90deg);
width: 60px;
height: 60px;
z-index: 2;
}
.circle {
cx: 50%;
cy: 50%;
r: 28px;
fill: white;
stroke: #0b65bf;
stroke-width: 4px;
stroke-dasharray: calc(3.14 * 56px);
stroke-dashoffset: calc(3.14 * 56px);
}
.border {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: #ddd;
border-radius: 50%;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg class="bar">
<circle class="circle" data-value="45" />
</svg>
function draw(radius,lineWidth,col,startPerc, endPerc)
{
var canvas = document.getElementById("imgCanvas");
var context = canvas.getContext("2d");
var posx = radius + lineWidth;
var posy = radius + lineWidth;
var start = -Math.PI/2; // Top of circle (0 would be right side)
context.lineWidth = lineWidth;
context.strokeStyle = col;
context.beginPath();
context.arc(posx, posy, radius, start + (2*Math.PI)*startPerc, start + (2*Math.PI)*endPerc);
context.stroke();
}
draw(30,5,"#2976CD",0,.60);
draw(30,5,"#E0E6E7",.60,1);
<canvas style="border:1px solid gray;" id="imgCanvas" width="100" height="100" onclick="draw()"></canvas>
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>
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>