In my JS code, I've added a EventListener on mousemove & touchmove, which makes it so that my div follows the cursor. (as such)
CSS:
<style>
body {
padding: 0;
margin: 0;
height: 100vh;
background: linear-gradient(135deg, #8fc7f1, #7173f5);
overflow: hidden;
}
#my-div {
width: 300px;
height: 250px;
background-color: #ffffff;
position: absolute;
}
</style>
HTML:
<div id="my-div">
<h1>Hello</h1>
</div>
JAVASCRIPT:
let myDiv = document.getElementById("my-div");
//Detect touch device
function isTouchDevice() {
try {
//We try to create TouchEvent. It would fail for desktops and throw error
document.createEvent("TouchEvent");
return true;
} catch (e) {
return false;
}
}
const move = (e) => {
//Try, catch to avoid any errors for touch screens (Error thrown when user doesn't move his finger)
try {
//PageX and PageY return the position of client's cursor from top left of screen
var x = !isTouchDevice() ? e.pageX : e.touches[0].pageX;
var y = !isTouchDevice() ? e.pageY : e.touches[0].pageY;
} catch (e) {}
//set left and top of div based on mouse position
myDiv.style.left = x - 150 + "px";
myDiv.style.top = y - 120 + "px";
// myDiv.style.opacity = 0;
// console.log(myDiv.getBoundingClientRect())
};
//For mouse
document.addEventListener("mousemove", (e) => {
move(e);
console.log("Mouse")
});
//For touch
document.addEventListener("touchmove", (e) => {
move(e);
});
JSFIDDLE CODE
What I'm trying to do is to add a iframe inside my div and the div should still follow the cursor, but when I add the iframe inside the div, then the EventListener stops working and my div stops following the cursor. I'm not sure what the issue is. (as such)
<div id="my-div">
<iframe src="https://example.com/" width="300" height="250">
</div>
JSFIDDLE CODE WITH IFRAME
Any help and suggestion is appreciated!
You forgot the closing iframe tag
<div id="my-div">
<iframe src="https://example.com/" width="300" height="250"></iframe>
</div>
I think you should change the position of your div to relative and the position of your iframe to absolute.
Related
How would I go about making a scroll-and-pan effect with the mouse wheel for the entire page? Basically like any 2D editor with the scroll to zoom, click and drag to pan but for the entire body.
I haven't been able to find anything online about it.
If you don't know where to start, you will very soon hit another wall, because knowing where to start is the easy part. Here is a rough guide:
Add event listener to the wheel event (learn how](https://stackoverflow.com/a/51276012/104380))
Start with an initial (current) zoom value and calculate the delta from the wheel event and update your zoom value.
Use the zoom value to manipulate the scale of the page in some form. You can use CSS transform: scale() for that, on the body element.
Add event listener for the mousemove event (learn how](https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event))
Act upon the detected mouse move, and calculate how much you need to pan the zoomed body element in order to reach any of the 4 edges, and not beyond.
panning may be done via CSS transform: translate(x,y)
Implementation I made based off of vsyncs answer:
window.onload = init;
let root;
let content;
let zoom = 1.0;
let translateY = 0;
let translateX = 0;
let middleMouseDown = false;
function init(){
content = document.getElementById("content");
root = document.getElementById("root");
root.addEventListener("wheel", (event)=>{
zoom += event.wheelDelta / 1000;
if(zoom > 2.0){zoom = 2.0}
else if (zoom < 0.5) {zoom = 0.5}
console.log(zoom);
transform();
})
root.addEventListener("mousedown", (event)=>{
event.preventDefault();
middleMouseDown = (event.button == 1);
})
root.addEventListener("mouseup", (event)=>{
if(event.button == 1){
middleMouseDown = false;
}
})
root.addEventListener("mousemove", (event)=>{
// console.log(event);
if(middleMouseDown){
translateY += event.movementY;
translateX += event.movementX;
transform();
}
})
}
function transform(){
content.style.transform = `scale(${zoom}, ${zoom}) translate(${translateX}px, ${translateY}px)`;
}
body{
margin: 0px;
}
#root{
width: 400px;
height: 400px;
border: 1px solid red;
overflow: scroll;
}
#content{
width: 200px;
height: 200px;
border: 1px solid black;
}
<html lang="en">
<head>
<link rel="stylesheet" href="index.css">
<script src="main.js"></script>
</head>
<body>
<div id="root">
<div id="content">
</div>
</div>
</body>
</html>
I have problem with "double scrolling"; This is screen from my app:
As you can see, the space for adding tables is surrounded by a scroll bar.
I just need the scroll function to zoom in and out of my diagram, not to move it up and down. The current situation is that if I run my function that zooms in and out on the diagram, it also scrolls up or down. It makes such a double scroll which makes no sense.
Is it possible to turn off only the "scroll" function without turning off the scroll bars on the sides?
This is some code (my event wheel)(i am using library "MindFusion Diagramming"):
document.addEventListener('wheel', function (e) {
var zoom = diagram.getZoomFactor();
zoom -= e.deltaY / 35;
if(zoom > 70 && zoom < 200 )
{
diagram.setZoomFactor(zoom);
}
//e.preventDefault();
});
And this is an error when I uncomment e.preventDefault ()
My divs (content is an area with scrollbars):
<div id="content" style="position: static; width: 1600px; height: 700px;" >
<!-- The Overview component is bound to the canvas element below -->
<div style="position: absolute; right: 120px; width: 200px;
height: 200px; border: 1px solid #ffffff; background-color: #c0c0c0;">
<canvas id="overview" width="200" height="200">
</canvas>
</div>
<!-- The Diagram component is bound to the canvas element below -->
<div style="position: static; width: 100%; height: 100%; overflow: auto;">
<canvas id="diagram" width="2100" height="2100">
This page requires a browser that supports HTML 5 Canvas element.
</canvas>
</div>
</div>
Try,
document.addEventListener('wheel', function (e) {
e.preventDefault();
var zoom = diagram.getZoomFactor();
zoom -= e.deltaY / 35;
if(zoom > 70 && zoom < 200 )
{
diagram.setZoomFactor(zoom);
}
}, { passive : false});
reference: what are passive event listeners
I assume you overrode the scroll event to achieve your zoom functionality. You would need to call the preventDefault function on the event object you get in your event listener.
Edit:
Your event listener is passive because scroll event listeners are usually disruptive to user experience. To register it as non-passive:
document.addEventListener('wheel', function (e) {
var zoom = diagram.getZoomFactor();
zoom -= e.deltaY / 35;
if(zoom > 70 && zoom < 200 )
{
diagram.setZoomFactor(zoom);
}
e.preventDefault();
}, {passive: false});
I have an implementation of hover(mouseenter), click, mouseleave, which shows and hide the popup modal component whenever the target element is hovered.
But the issue is the popup modal component opens a bit far away from the hovered element that is due to the top,left position I am giving.
How can I correctly position this modal component and is it possible to place the popup component just by the side of the mouse cursor instead of the popup being by the side of the hovered element?
(And also the distance of the popup component varies when I hover over the element).
Maybe CSS :after can be a solution?
Minimum Reproducible example
https://stackblitz.com/edit/angular-34rr1t?file=src/app/app.component.html
TS file for handling opening and closing of popup modal
modalShow = false;
modalleft;
modaltop;
addClickEvent(e,name) {
if (e.type === 'click') {
this.modalShow= true;
}
else if (e.type === 'mouseenter') {
this.modalleft = e.clientX
this.modaltop = e.clientY
this.closeModal("room");
this.modalShow= true;
}
else if (e.type === 'mouseleave') {
this.closeModal('room');
this.modalShow= false;
}
}
closeModal(modalType: string) {
this.modal[modalType].active = false;
}
HTML for handling opening and closing of popup modal
<div class="fs-heatmap-wrapper__content__box"
*ngFor="let existingZone of floor.droppeditem"
(mouseenter)="addClickEvent($event,floor.name)"
(mouseleave)="addClickEvent($event,floor.name)"
(click)="addClickEvent($event,floor.name)">
</div>
<fs-modal *ngIf="!modalShow"
[ngStyle]="{'top.px': modalleft,
'left.px':modaltop ,
'position':'absolute'}"
(onCloseModal)="closeModal('room')">
</fs-modal>
HTML fs-modal
<div class="modal">
<div class="modal__body">
</div>
</div>
CSS fs-modal
.modal {
background: rgba(0, 0, 0, 0.5);
max-height: 100%;
overflow-y: scroll;
z-index: 9999999;
&__body {
pointer-events: all;
padding: 50px;
background: #ffffff;
box-shadow: 4px 45px 23px -6px rgba(0, 0, 0, 0.4);
margin: 2% 0;
height: auto;
*min-height: 1200px;
}
There are multiple problems in your code:
You're assigning left value of mouse position to top value of modal and top value of mouse position to left value of modal. You need to reverse that.
mouseenter and mouseleave are fired only once, when pointer enters the DOM element and leaves it respectively. That's why your modal shows up in some corner as the values are for the event when the mouse pointer first entered or left.
If you want a behaviour of the modal following your pointer, as mentioned in the link posted in the comments, you'll need the mousemove event
Your addClickEvent (I would name it handleEvent), needs to be like this:
addClickEvent(e) {
if (e.type === 'mousemove') {
this.modalleft = e.clientX
this.modaltop = e.clientY
}
else if (e.type === 'mouseenter') {
this.modalShow = true;
}
else if (e.type === 'mouseleave') {
this.modalShow = false;
}
}
Fork of your code, with these changes: https://stackblitz.com/edit/angular-zqeeqv?file=src/app/app.component.html
I have a fixed div containing an image that scrolls with the user from the top of the page. As new content divs enter the viewport I want the image to change.
I found a related piece of code that will change the image based on how far a user scrolls in pixels. This works, but only if the viewport is a specific size, else the image changes too early/late:
Example
I'm trying to modify this so that the change is instead based on when another div comes into view so that it works no matter the screen size (content div heights are set with relative units). I think this can be done if the other divs positions are saved to a variable and then used in place of the pixel values in the above code. However I can't seem to get this right, probably because I've not calculated the other div positions correctly.
$("#display1").fadeIn(1000);
$(window).scroll(function() {
var pos = $(window).scrollTop();
var first = $("#first").offset();
var second = $("#second").offset();
if (pos < first) {
hideAll("display1");
$("#display1").fadeIn(1000);
}
if (pos > first && pos < second) {
hideAll("display2");
$("#display2").fadeIn(1000);
}
etc...
});
function hideAll(exceptMe) {
$(".displayImg").each(function(i) {
if ($(this).attr("id") == exceptMe) return;
$(this).fadeOut();
});
}
You should try
getBoundingClientRect()
JS method, since It gets the position of the elements relative to the viewport. Check this answer: https://stackoverflow.com/a/7557433/4312515
Here is a quick proof of concept of changing a background image based on an element getting into view.
There are three divs. When the third div reaches the bottom of the viewport it will change the color of the background. When the third divs scroll out of the view again the background color is reset to its initial color.
Normally you should debounce the scroll event to prevent slowing down the UI. For this example I didn't debounce the event so you get a better sense of when the background is changed.
const
card3 = document.getElementById('card3'),
background = document.getElementById('background');
let
isCardVisible = false;
function checkDivPosition() {
const
cardTopPosition = card3.getBoundingClientRect().top,
viewportHeight = document.documentElement.clientHeight,
isInView = cardTopPosition - viewportHeight < 0;
if (isInView && !isCardVisible) {
background.style.backgroundColor = 'rebeccapurple';
isCardVisible = true;
} else if (!isInView && isCardVisible) {
background.style.backgroundColor = 'orange';
isCardVisible = false;
}
}
function onWindowScroll(event) {
checkDivPosition();
}
window.addEventListener('scroll', onWindowScroll);
body {
margin: 0;
}
.background {
height: 100vh;
opacity: .2;
position: fixed;
transition: background-color .3s ease-out;
width: 100vw;
}
.card {
border: 1px solid;
height: 100vh;
width: 100vw;
}
.card + .card {
margin-top: 5vh;
}
<div id="background" class="background" style="background-color:orange"></div>
<div class="card">
Card 1
</div>
<div class="card">
Card 2
</div>
<div id="card3" class="card">
Card 3.
</div>
I have a sample code:
<div style="background: url('test.jpg') no-repeat left center; width: 500px; height: 334px;">
<div id="button-wrapper" style="position: absolute; opacity: 1; z-index: 100;">
<input type="button" value="submit">
</div>
</div>
And Jquery
jQuery(document).ready(function(){
jQuery("div[id^=\'button-wrapper\']").parent().mousemove(function(e){
jQuery("div[id^=\'button-wrapper\']").css({
top:e.pageY-5,
left:e.pageX-5
});
});
});
Error when I mouse move out of the frame (div id="button-wrapper") it's run when out of frame, How to fix it, to only run in the frame ? (demo here)
Define the containment for mousemove in your code.
Check this link.. code updated...
CHECK THIS LINK
I had Added constraint on that mouse movemnet
var a = $(this).height()-15;
var b = $(this).width()-35;
if(e.pageY < a&& e. pageX < b)
{
$('div[id^="button-wrapper"]').css({
top:e.pageY-5,
left:e.pageX-5
});
}
You need to check if the mouse is being moved outside the parent div. See example at - http://jsfiddle.net/qCbwr/40/.
var _c = $(this);
var _p = _c.position();;
if (_top > (_p.top + _c.height())) _top = _p.top + _c.height();
if (_left > (_p.left + _c.width())) _left = _p.left +_c.width();
You will need to allow for the size of the button if you do not want the control to go outside the div entirely.