I am trying to create a custom cursor on a website (a blurry yellow spot). I created a div in HTML for the custom cursor and styled it in CSS. I gave the 'cursor: none' property to the body tag to hide the default cursor. I also put 'pointer-events: none' on the custom cursor div. Still, click events are not (or hardly) working on buttons (for example I cannot close a pop-up window with the close button). When I remove 'cursor: none', everything works fine, but the default cursor returns beside the yellow spot. Could you please help me in solving this? How could I remove the default cursor without affecting click events? Thank you in advance.
// move yellow spot as cursor
const moveCursor = (e) => {
const mouseY = e.clientY;
const mouseX = e.clientX;
const yellowSpot = document.querySelector(".yellow-spot");
yellowSpot.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0)`;
}
window.addEventListener('mousemove', moveCursor);
document.querySelector("input[type=button]").addEventListener("click", () => {
console.log("Button clicked");
});
*,
body {
cursor: none !important;
}
.yellow-spot {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 1.625rem;
height: 1.625rem;
border-radius: 50%;
background: #ffeb77;
box-shadow: 0 0 15px 5px #ffeb77;
pointer-events: none;
}
<div class="yellow-spot"></div>
<input type="button" value="Click Me">
The issue is that the actual cursor is at the top-left of the yellow spot, not in the middle, so it's easy to miss things when trying to click on them. You can see that if you remove the cursor: none rule:
// move yellow spot as cursor
const moveCursor = (e) => {
const mouseY = e.clientY;
const mouseX = e.clientX;
const yellowSpot = document.querySelector(".yellow-spot");
yellowSpot.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0)`;
}
window.addEventListener('mousemove', moveCursor);
document.querySelector("input[type=button]").addEventListener("click", () => {
console.log("Button clicked");
});
*,
body {
/* cursor: none !important; */
}
.yellow-spot {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 1.625rem;
height: 1.625rem;
border-radius: 50%;
background: #ffeb77;
box-shadow: 0 0 15px 5px #ffeb77;
pointer-events: none;
}
<div class="yellow-spot"></div>
<input type="button" value="Click Me">
To fix it, center the yellow spot over the cursor rather than moving it to the top-left (I also changed how the yellow spot is moved, but that's not the important thing):
const yellowSpot = document.querySelector('.yellow-spot');
// move the yellow spot to the mouse position
document.addEventListener('mousemove', function(e) {
// Make sure the *center* of the yellow spot is where the
// cursor is, not the top left
const {clientWidth, clientHeight} = yellowSpot;
yellowSpot.style.left = ((e.pageX - (clientWidth / 2)) + 'px');
yellowSpot.style.top = (e.pageY - (clientHeight / 2)) + 'px';
});
*,
body {
cursor: none !important;
}
.yellow-spot {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 1.625rem;
height: 1.625rem;
border-radius: 50%;
background: #ffeb77;
box-shadow: 0 0 15px 5px #ffeb77;
pointer-events: none;
}
<div class="yellow-spot"></div>
<button onclick="alert('test')">Click me</button>
Here's a version with the cursor showing so you can see how it's centered in the yellow spot now:
const yellowSpot = document.querySelector('.yellow-spot');
// move the yellow spot to the mouse position
document.addEventListener('mousemove', function(e) {
// Make sure the *center* of the yellow spot is where the
// cursor is, not the top left
const {clientWidth, clientHeight} = yellowSpot;
yellowSpot.style.left = ((e.pageX - (clientWidth / 2)) + 'px');
yellowSpot.style.top = (e.pageY - (clientHeight / 2)) + 'px';
});
*,
body {
/*cursor: none !important;*/
}
.yellow-spot {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: 1.625rem;
height: 1.625rem;
border-radius: 50%;
background: #ffeb77;
box-shadow: 0 0 15px 5px #ffeb77;
pointer-events: none;
}
<div class="yellow-spot"></div>
<button onclick="alert('test')">Click me</button>
Related
I am trying to make an eyeball that follows the mouse around using only html, css, and javascript. Currently, I have the eyeball rendered and even got the pupil to move around when you hover over the eye. Unfortunately, the pupil is not moving in the direction of the mouse at all & will only begin moving when you hover over the eyeball itself.
I am not worried about the location or size of the eye right now, just trying to get everything working. I have tried to setup an event listener in javascript using 'mousemove' then getting the vertical and horizontal access using 'getBoundingClientRect()'. Then I believe you should be able to calculate the rotation of the pupil using some equations I found using the mouseX & mouseY values from the 'mousemove' but this is where I get stuck & I believe it is also where the problem is occurring. I will be attaching my code below. Any help would be appreciated!
const container = document.querySelector('.container');
container.addEventListener('mousemove', (e) => {
const eyeball = document.querySelectorAll('.eye-inner');
[].forEach.call(eyeball, function(eye) {
let mouseX = eye.getBoundingClientRect().left;
let mouseY = eye.getBoundingClientRect().top;
let radianDegrees = Math.atan2(e.pageX - mouseX, e.pageY - mouseY);
let rotationDegrees = radianDegrees * (180 / Math.PI) * -1 + 180;
eye.style.transform = `rotate(${rotationDegrees}deg)`;
});
});
* {
background: black;
}
.eye {
display: flex;
width: 48px;
height: 48px;
position: absolute;
bottom: 41px;
background: #fff;
border-radius: 75% 0;
transform: translate(300%, 0) rotate(45deg);
}
.eye-inner {
position: relative;
display: inline-block;
border-radius: 50%;
width: 40px;
height: 40px;
background-color: black;
margin-left: 4px;
margin-top: 4px;
}
.pupil {
position: absolute;
top: 2px;
left: 10px;
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
content: " ";
}
<div class="container">
<div class="eye">
<div class="eye-inner">
<div class="pupil"></div>
</div>
</div>
</div>
The solution I'm after: to detect if a point falls within the red area below.
Now the difficulty here is that the red area isn't an image, it's actually a div that has been rotated into position.
Using JavaScript, how can I detect if a point lands in this area? And ideally in an efficient manner as this check might need to be called often and on slow devices.
CSS details: It has position: absolute on it, rotated 45 degrees and has been positioned using left: -135 and top:0.
My current approach has been to try and perform some calculation to determine where X intersects with the viewport, which will then give me Y (and I can calculate from there) but I have had no luck. Using getBoundingClientRect() on the element returns a square around the shape, but not of the shape itself.
How can this be done? Here is a small example (I want to detect if the top left corner of the intersecting element intersects with the red triangle):
body {
background: #ffd0ff;
padding: 12px;
margin: 0;
}
.sash {
position: absolute;
width: 270px;
height: 80px;
top: 0;
left: -135px;
background-color: #e10a0a;
opacity: 0.5;
transform: rotate(-45deg);
}
.intersection {
background: rgba(0, 255, 0, 0.5);
padding: 12px;
display: inline-block;
}
<div class="sash"></div>
<span class="intersection">
Some intersecting div
</span>
You can make use of the document.elementFromPoint(x, y) method, e.g.:
function isPointInElement(x, y, selector) {
let element = document.querySelector(selector);
let elementFromPoint = document.elementFromPoint(x, y);
return element == elementFromPoint;
}
function isIntersecting(selector1, selector2) {
let element1 = document.querySelector(selector1);
let element1Coords = element1.getBoundingClientRect();
return isPointInElement(element1Coords.top, element1Coords.left, selector2);
}
let isIntersectionInRedArea = isIntersecting('.intersection', 'div.sash');
console.log(`.intersection and div.sash are ${ isIntersectionInRedArea ? '' : 'not '}intersecting.`);
let isNonIntersectionInRedArea = isIntersecting('.non-intersection', 'div.sash');
console.log(`.non-intersection and div.sash are ${ isNonIntersectionInRedArea ? '' : 'not '}intersecting.`);
body {
background: #ffd0ff;
padding: 12px;
margin: 0;
}
.sash {
position: absolute;
width: 270px;
height: 80px;
top: 0;
left: -135px;
background-color: #e10a0a;
opacity: 0.5;
transform: rotate(-45deg);
}
.intersection {
background: rgba(0, 255, 0, 0.5);
padding: 12px;
display: inline-block;
}
.non-intersection {
background: rgba(0, 0, 255, 0.5);
padding: 12px;
display: inline-block;
}
<div class="sash"></div>
<span class="intersection">
Some intersecting div
</span>
<span class="non-intersection">
Non intersecting div
</span>
Trying to fix div "flicker" on page scroll in Safari browser ( ver 12.0.2 on macOS High Sierra), but don't understand why this is happening, also i've tried to fix this via CSS methods, like transformZ(0), webkit-backface-visibility: hidden, webkit-transform-style: preserve-3d, will-change: top, but this doesn't help, any ideas? thanks!
var scroll = document.getElementById('scroll').style;
window.onscroll = function () {
scroll.top = middleOfScreen();
};
var raf = document.getElementById('raf').style;
requestAnimationFrame(function setRaf () {
raf.top = middleOfScreen();
requestAnimationFrame(setRaf);
});
function middleOfScreen() {
return window.pageYOffset + window.innerHeight/2 + 'px';
}
body {
height: 20000px;
margin: 0;
font-family: sans-serif;
text-align: center;
}
div {
width: 23%;
top: 50%;
background-color: rgba(0, 0, 0, 0.2);
padding: 1em 0;
}
div:nth-child(2n) {
background-color: rgba(0, 0, 0, 0.4);
}
#static {
position: absolute;
left: 0;
}
#scroll {
position: absolute;
left: 24%;
}
#raf {
position: absolute;
left: 48%;
}
#css {
position: fixed;
right: 0;
}
<div id=static>position:static</div>
<div id=scroll>set to top:50% onScroll</div>
<div id=raf>set to top:50% on requestAnimationFrame</div>
<div id=css>posision:fixed </div>
also Codepen
Why do you need to set top every time your scroll event fire? it seems that setting top value affecting to the flicker. If you want to listen on scroll and set top anyway so I suggest to use throttle so your event listeners will do only once.
I want to drag a div and drop anywhere in its parent div . For dragging I use css style
draggable="true"
and for drop, I use 'mousemove' event X and Y values and use this values for div top and left .The code I used is
$(".drop").mousedown(function () {
$(this).mousemove(function (e) {
var k = e.clientX ;
var f = e.clientY;
$(".drop").text(k+ ", " + f);
$(".drop").css("top",f);
$(".drop").css("left",k);
});
}).mouseup(function () {
$(this).unbind('mousemove');
}).mouseout(function () {
$(this).unbind('mousemove');
});
.drop{
position: absolute;
left: 300;
top: 200; /* set these so Chrome doesn't return 'auto' from getComputedStyle */
width: 200px;
background: rgba(255,255,255,0.66);
border: 2px solid rgba(0,0,0,0.5);
border-radius: 4px; padding: 8px;
z-index: 3;
}
.gridPart{
padding: 20px;
background-color: #FFF;
border-radius: 5px;
margin: auto;
margin: 20px;
padding-right: 0px;
padding-bottom: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gridpart">
<div class="drop" draggable="true" ></div>
<div>
Now it's drag & drop if I drag with increasing left value. But if I drag with decreasing left value it's not dropping. And how I stop the drag if it reach the end of the main div(GridPart)?
I have fixed your code. All you did is quite good but you should have to use the mousemove event with $(document) element and not with the div. Since when you drag backwards, mouse movement is going out of the div and so its no longer dragging.
Also, as you used custom dragging, you don't need to use draggable="true".
$(".drop").mousedown(function () {
$(document).mousemove(function (e) {
var k = e.clientX;
var f = e.clientY;
$(".drop").text(k+ ", " + f);
$(".drop").css("top", f + 'px');
$(".drop").css("left", k + 'px');
});
});
$(document).mouseup(function () {
$(document).unbind('mousemove');
});
.drop{
position: absolute;
left: 300;
top: 200; /* set these so Chrome doesn't return 'auto' from getComputedStyle */
width: 200px;
background: rgba(255,255,255,0.66);
border: 2px solid rgba(0,0,0,0.5);
border-radius: 4px; padding: 8px;
z-index: 3;
}
.gridPart{
padding: 20px;
background-color: #FFF;
border-radius: 5px;
margin: auto;
margin: 20px;
padding-right: 0px;
padding-bottom: 3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="gridpart">
<div class="drop" ></div>
<div>
Simply use the JQueryUi Draggable:
https://jqueryui.com/draggable/
UPDATE: sample code here:
http://embed.plnkr.co/5W3ACU/
I think what i have discerned from your question you are trying to do, is limit dragging to within the .gridpart div.
The key was moving the drag detection to the container div, and then moving the drag component based on the mousedown position
JSFIDDLE
JS
$(".gridpart").mousedown(function () {
var containerDims = $(this)[0].getBoundingClientRect();
var dropEl = $(this).find('.drop');
// measure the size of the drop element
var dropDims = dropEl[0].getBoundingClientRect()
$(this).mousemove(function (e) {
// position the element centered under the cursor
var k = e.clientX - dropDims.width / 2;
var f = e.clientY - dropDims.height / 2;
if( k >= 0 && k <= containerDims.width - dropDims.width){
dropEl.css("left",k);
}
if(f >= 0 && f <= containerDims.height - dropDims.height){
dropEl.css("top", f);
}
dropEl.text(k + ', ' + f);
});
}).mouseup(function () {
$(this).unbind('mousemove');
});
CSS
.drop{
position: absolute;
left: 0;
top: 20px;
width: 200px;
background: rgba(255,255,255,0.66);
border: 2px solid rgba(0,0,0,0.5);
border-radius: 4px; padding: 8px;
z-index: 3;
/* prevent 'shadow' drag preventing mouseup firing */
-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
user-drag: none;
}
.gridpart{ /* correct camelcase typo */
background-color: #F00;
border-radius: 5px;
margin: 20px;
padding-right: 0px;
position: relative;
height: 58px;
}
HTML
<div class="gridpart">
<div class="drop" draggable="true">0, 0</div>
<div>
Im trying to move the #frame-slider-thumb across the image. I had it working by just keeping track of the diff in mouseX position. But the problem was that if the thumb wasn't at 0 to begin with it would jump back to 0. Thus I added the curr variable in the logic to add the diff from its current position. Now it moves much to quickly though. I'm not sure why. Any help much appreciated.
Heres a codepen.
HTML
<div id="frame-slider">
<img id="frame-slider-background" src="http://imagej.1557.x6.nabble.com/file/n5009735/OCT_pre_segmented.png" alt="" />
<div id="frame-slider-track">
<div id="frame-slider-thumb">
<div class="top-half"></div>
<div class="bottom-half"></div>
</div>
</div>
</div>
JS
var mouseStartPosition = {};
var thumb = document.getElementById('frame-slider-thumb');
window.addEventListener("mousedown", mousedownThumb);
function mousedownThumb(e) {
mouseStartPosition.x = e.pageX;
// add listeners for mousemove, mouseup
window.addEventListener("mousemove", mousemoveThumb);
window.addEventListener("mouseup", mouseupThumb);
}
function mousemoveThumb(e) {
var curr = isNaN(parseFloat(thumb.style.left)) ? 0 : parseFloat(thumb.style.left);
var diff = -1 * (mouseStartPosition.x - e.pageX);
var newLeft = curr + diff;
thumb.style.left = newLeft + 'px';
}
function mouseupThumb(e) {
window.removeEventListener("mousemove", mousemoveThumb);
window.removeEventListener("mouseup", mouseupThumb);
}
CSS
html,
body {
width: 100%;
height: 100%;
}
#frame-slider {
height: 150px;
width: 50%;
position: relative;
}
#frame-slider-background {
width: 100%;
max-height: 100%;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-user-drag: none;
user-drag: none;
-webkit-touch-callout: none;
}
#frame-slider-track {
height: 100%;
width: 100%;
position: absolute;
top: 0;
}
#frame-slider-thumb {
position: absolute;
left: 0;
margin-left: -4px;
width: 8px;
height: 100%;
cursor: pointer;
}
#frame-slider-thumb .top-half {
background-color: rgba(0, 0, 255, 0.7);
height: 50%;
}
#frame-slider-thumb .bottom-half {
background-color: rgba(255, 0, 0, 0.7);
height: 50%;
}
Fixed by adding a thumbStart position to mousedownThumb. Basically diff isn't the difference in position from the last mousemove event, its the difference from the last mousemove event and the mousedown event.
var mouseStartPosition = {};
var thumbStart;
var thumb = document.getElementById('frame-slider-thumb');
window.addEventListener("mousedown", mousedownThumb);
function mousedownThumb(e) {
mouseStartPosition.x = e.pageX;
thumbStart = isNaN(parseFloat(thumb.style.left)) ? 0 : parseFloat(thumb.style.left);
// add listeners for mousemove, mouseup
window.addEventListener("mousemove", mousemoveThumb);
window.addEventListener("mouseup", mouseupThumb);
}
function mousemoveThumb(e) {
var diff = -1 * (mouseStartPosition.x - e.pageX);
var newLeft = thumbStart + diff;
thumb.style.left = newLeft + 'px';
}
function mouseupThumb(e) {
window.removeEventListener("mousemove", mousemoveThumb);
window.removeEventListener("mouseup", mouseupThumb);
}