How to "click through" fixed overlay div, without disabling its pointer events - javascript

I have a use case where I need to overlay fixed div over canvas element. This div is used to listen for scroll event and then transfer that data to canvas it is covering. Simplified html for these could look like following:
<canvas style="width: 100vw; height: 100vh;"></canvas>
<div style="position: fixed; width: 100vw; height: 100vh; top: 0; left: 0;"></div>
I ran across an issue. My canvas is also interactive, it has button elements and other stuff like that, unfortunately I had to implement scrolling behaviour this way for better performance and to keep default browser behaviours like "bounce scroll" on ios.
Is it at all possible to have this approach but also translate all mouse / touch event from the div to canvas behind it?

okay, so you cannot really pass a click event programmatically and have x and y coordimates (as seen in the fiddle I attached).
What you can do is define global vars that store x and y coords on click of div. and then trigger click on canvas like this:
var div = document.querySelector('#theDiv')
var canvas = document.querySelector('#theCanvas')
var x = 0;
var y = 0;
div.addEventListener('click', function(event) {
console.log('div clicked', event); // event.clientX and event.clientY have correct values
x = event.clientX;
y = event.clientY;
canvas.click();
});
canvas.addEventListener('click', function(event) {
console.log('canvas clicked', x, y, event); // event.clientX and event.clientY are both 0
})
Here is the fiddle, where you can see it in action (I have added some styles to differentiate between the div and canvas)
https://jsfiddle.net/m1n4xave/10/

Related

How to do eventListener by holding right click using VANILLA JS

I want to display the div wherever the cursor is holding right click.
in my case i have this code
<div class="d-none" id="item"></div>
#item{
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background: royalblue;
/* transform: translate(calc(287px - 50%), calc(77px - 50%)); */
}
.d-none{
display: none;
}
var myMouseX, myMouseY;
function getXYPosition(e) {
myMouseX = (e || event).clientX;
myMouseY = (e || event).clientY;
getPosition(myMouseX, myMouseY);
function getPosition(x, y) {
console.log('X = ' + x + '; Y = ' + y);
let div = document.querySelector("#item");
if (div.classList.contains('d-none')) {
div.classList.remove('d-none');
} else {
div.classList.add('d-none');
}
divX = x + "px";
divY = y + "px";
div.style.transform = `translate(calc(`+divX+` - 50%) , calc(`+divY+` - 50%))`;
}
}
window.addEventListener('click', function () {
getXYPosition()
})
or you can see my Fiddle
Its work on left click by default using window.addEventListener('click')
so how do i change from left click to holding right click a few seconds
The MouseEvent API (with its mousedown and mouseup events) lets us check the event.button property to learn which mouse button the user is activating. And we can keep track of how much time passes between mousedown and mouseup to decide what to do when the mouse button is released, such as running a custom showOrHideDiv function.
And the contextmenu event fires after a right-click (unless the relevant context menu is already visible, I guess.) We can suppress the default contextmenu behavior if necessary -- although this power should be used sparingly if at all.
Note that the technique used here is problematic in that it assumes the user will never use their keyboard to see the context menu, which will eventually cause accessibility snafus and other unpleasant surprises for users. This is why hijacking the default right-click behavior should be avoided if possible (maybe in favor of something like Shift + right-click) unless the user explictly opts in to the new behavior.
// Defines constants and adds main (`mousedown`) listener
const
div = document.querySelector("#item"),
RIGHT = 2,
DELAY = 150;
document.addEventListener('mousedown', forceDelay);
// Main listener sets subsequent listeners
function forceDelay(event){
// Right mouse button must be down to proceed
if(event.button != RIGHT){ return; }
// Enables contextmenu and disables custom response
document.removeEventListener('contextmenu', suppressContextMenu);
document.removeEventListener('mouseup', showOrHideDiv);
// After 150ms, disables contextmenu and enables custom response
setTimeout(
function(){
document.addEventListener('contextmenu', suppressContextMenu);
document.addEventListener('mouseup', showOrHideDiv);
},
DELAY
);
}
// The `contextmenu` event listener
function suppressContextMenu(event){
event.preventDefault();
}
// The `mouseup` event listener
function showOrHideDiv(event){
if(event.button != RIGHT){ return; }
const
x = event.clientX,
y = event.clientY;
div.classList.toggle('d-none'); // classList API includes `toggle`
div.style.transform = `translate(calc(${x}px - 50%), calc(${y}px - 50%))`;
}
#item{ position: absolute; top: 0; left: 0; width: 100px; height: 100px; background: royalblue; }
.d-none{ display: none; }
<div id="item" class="d-none"></div>
EDIT
Note: The script works properly when tested in a standalone HTML file using Chrome, but (at least with my laptop's touchpad) behaves strangely when run here in a Stack Overflow snippet. If you experience similar issues, you can paste it into a <script> element in an HTML file (with the CSS in a <style> element) to see it working.

Using MouseMove function to move elements in svg with svelte framework

Apologies if this is a dumb question, as I'm new to web development, and many thanks in advance!
I'm currently using a svg inside svelte framework. I defined my svg as <svg width={svg_width} height={svg_height}>. The whole structure looks like
<div class="demo-container">
|-<div id="playground-container">
|-<svg>
Here is my css:
.demo-container {
display:inline-block;
}
#playground-container {
position: relative;
width: 75%;
float: left;
margin-right:5px;
}
I'm having trouble relating the coordinate in svg (e.g. the location of shapes in the svg) to the mouse event (event.ClientX & event.ClientY). They do not seem to have linear or affine relationship. Additionally, when I inspect the webpage, the dimension of the svg displayed does not match what I defined it to be.
As a result, when I set the location of shapes directly to event.ClientX & event.ClientY, they go nuts. How should I convert the location of the mouse to location of the svg?
Please provide some help. Thanks
Assuming your mousemove event handler is attached to the svg element, the way to get x and y coordinates in reference to the svg itself (with the top left corner of the svg having coordinates (0,0) and the bottom right corner having the coordinates (svg_width, svg_height)) is to use getBoundingClientRect:
<script>
function mouseHandler(e) {
const rect = e.currentTarget.getBoundingClientRect()
console.log(`x: ${e.clientX - rect.x}, y: ${e.clientY - rect.y}`)
}
</script>
<div class="demo-container">
<div id="playground-container">
<svg width={svg_width} height={svg_height} on:mousemove={mouseHandler}>
// svg data (shapes, paths, etc.)
</svg>
</div>
</div>
You need to place a on:mousemove={fixElement} in your html-tag.
a function like this might work as you discribe:
function fixElement(event) {
console.log("in");
let elem = document.querySelector('#playground-container');
let y = event.clientY;
let x = event.clientX;
elem.style.setProperty('position', 'absolute');
elem.style.setProperty('left', x + 'px');
elem.style.setProperty('top', y + 'px');
}

window.onmousemove and document.onmousemove doesn't capture iframe events [duplicate]

I have an iframe that takes up the entire window (100% wide, 100% high), and I need the main window to be able to detect when the mouse has been moved.
Already tried an onMouseMove attribute on the iframe and it obviously didn't work. Also tried wrapping the iframe in a div like so:
<div onmousemove="alert('justfortesting');"><iframe src="foo.bar"></iframe></div>
.. and it didn't work. Any suggestions?
If your target isn't Opera 9 or lower and IE 9 or lower you can use css attribute pointer-events: none.
I found it the best way just to ignore iframe. I add class with this attribute to iframe in onMouseDown event and remove in onMouseUp event.
Works perfect for me.
Iframes capture mouse events, but you can transfer the events to the parent scope if the cross-domain policy is satisfied. Here's how:
// This example assumes execution from the parent of the the iframe
function bubbleIframeMouseMove(iframe){
// Save any previous onmousemove handler
var existingOnMouseMove = iframe.contentWindow.onmousemove;
// Attach a new onmousemove listener
iframe.contentWindow.onmousemove = function(e){
// Fire any existing onmousemove listener
if(existingOnMouseMove) existingOnMouseMove(e);
// Create a new event for the this window
var evt = document.createEvent("MouseEvents");
// We'll need this to offset the mouse move appropriately
var boundingClientRect = iframe.getBoundingClientRect();
// Initialize the event, copying exiting event values
// for the most part
evt.initMouseEvent(
"mousemove",
true, // bubbles
false, // not cancelable
window,
e.detail,
e.screenX,
e.screenY,
e.clientX + boundingClientRect.left,
e.clientY + boundingClientRect.top,
e.ctrlKey,
e.altKey,
e.shiftKey,
e.metaKey,
e.button,
null // no related element
);
// Dispatch the mousemove event on the iframe element
iframe.dispatchEvent(evt);
};
}
// Get the iframe element we want to track mouse movements on
var myIframe = document.getElementById("myIframe");
// Run it through the function to setup bubbling
bubbleIframeMouseMove(myIframe);
You can now listen for mousemove on the iframe element or any of its parent elements -- the event will bubble up as you would expect.
This is compatible with modern browsers. If you need it to work with IE8 and below, you'll need to use the IE-specific replacements of createEvent, initMouseEvent, and dispatchEvent.
Another way to solve this that work well for me is to disable mouse move events on the iframe(s) with something like on the mouse down:
$('iframe').css('pointer-events', 'none');
and then, re-enable mouse move events on the iframe(s) on the mouse up:
$('iframe').css('pointer-events', 'auto');
I tried some of the other approaches above and they work, but this seems to be the simplest approach.
Credit to: https://www.gyrocode.com/articles/how-to-detect-mousemove-event-over-iframe-element/
MouseEvent.initMouseEvent() is now deprecated, so #Ozan's answer is a bit dated. As an alternative to what's provided in his answer, I'm now doing it like this:
var bubbleIframeMouseMove = function( iframe ){
iframe.contentWindow.addEventListener('mousemove', function( event ) {
var boundingClientRect = iframe.getBoundingClientRect();
var evt = new CustomEvent( 'mousemove', {bubbles: true, cancelable: false})
evt.clientX = event.clientX + boundingClientRect.left;
evt.clientY = event.clientY + boundingClientRect.top;
iframe.dispatchEvent( evt );
});
};
Where I'm setting clientX & clientY you'll want to pass any info from the content window's event to the event we'll be dispatching (i.e., if you need to pass something like screenX/screenY, do it there).
The page inside your iframe is a complete document. It will consume all events and have no immediate connection to it's parent document.
You will need to catch the mouse events from javascript inside the child document and then pass this somehow to the parent.
I have been faced with a similar issue, where I had div's that I wanted to drag around over an iFrame. Problem was that if the mouse pointer moved outside the div, onto the iFrame, the mousemove events were lost and the div stopped dragging. If this is the sort of thing you want to do (as opposed to just detecting the user waving the mouse over the iFrame), I found a suggestion in another question thread which seems to work well when I tried it.
In the page that contains the and the things you want to drag, also include a like this:
<div class="dragSurface" id="dragSurface">
<!-- to capture mouse-moves over the iframe-->
</div>
Set it's initial style to be something like this:
.dragSurface
{
background-image: url('../Images/AlmostTransparent.png');
position: absolute;
z-index: 98;
width: 100%;
visibility: hidden;
}
The z-index of '98' is because I set the div's I want to drag around to be z-index:99, and the iFrame at z-index:0.
When you detect the mousedown in the to-be-dragged object (not the dragSurface div), call the following function as part of your event handler:
function activateDragSurface ( surfaceId )
{
var surface = document.getElementById( surfaceId );
if ( surface == null ) return;
if ( typeof window.innerWidth != 'undefined' )
{ viewportheight = window.innerHeight; }
else
{ viewportheight = document.documentElement.clientHeight; }
if ( ( viewportheight > document.body.parentNode.scrollHeight ) && ( viewportheight > document.body.parentNode.clientHeight ) )
{ surface_height = viewportheight; }
else
{
if ( document.body.parentNode.clientHeight > document.body.parentNode.scrollHeight )
{ surface_height = document.body.parentNode.clientHeight; }
else
{ surface_height = document.body.parentNode.scrollHeight; }
}
var surface = document.getElementById( surfaceId );
surface.style.height = surface_height + 'px';
surface.style.visibility = "visible";
}
Note: I cribbed most of that from somebody else's code I found on the internet! The majority of the logic is just there to set the size of the dragSurface to fill the frame.
So, for example, my onmousedown handler looks like this:
function dragBegin(elt)
{
if ( document.body.onmousemove == null )
{
dragOffX = ( event.pageX - elt.offsetLeft );
dragOffY = ( event.pageY - elt.offsetTop );
document.body.onmousemove = function () { dragTrack( elt ) };
activateDragSurface( "dragSurface" ); // capture mousemoves over the iframe.
}
}
When dragging stops, your onmouseup handler should include a call to this code:
function deactivateDragSurface( surfaceId )
{
var surface = document.getElementById( surfaceId );
if ( surface != null ) surface.style.visibility = "hidden";
}
Finally, you create the background image (AlmostTransparent.png in my example above), and make it anything except completely transparent. I made an 8x8 image with alpha=2.
I have only tested this in Chrome so far. I need to get it working in IE as well, and will try and update this answer with what I discover there!
I found a relatively simple solution to this for a similar issue I was having where I wanted to resize the iframe and a long with a div sitting next to it. Once the mouse went over the iframe jquery would stop detecting the mouse.
To fix this I had a div sitting with the iframe both filling the same area with the same styles except for the z-index of the div (set to 0) and the iframe (set to 1). This allowed for the iframe to be used normally when not resizing.
<div id="frameOverlay"></div>
<iframe></iframe>
When resizing, the div z-index gets set to 2 and then back to 0 afterwards. This meant the iframe was still visible but the overlay was blocking it, allowing for the mouse to be detected.
On your "parent" frame, select your "child" iframe and detect the event you are interested, in your case mousemove
This an example of code to be used in your "parent" frame
document.getElementById('yourIFrameHere').contentDocument.addEventListener('mousemove', function (event) {
console.log(, event.pageX, event.pageY, event.target.id);
}.bind(this));
<script>
// dispatch events to the iframe from its container
$("body").on('click mouseup mousedown touchend touchstart touchmove mousewheel', function(e) {
var doc = $("#targetFrame")[0].contentWindow.document,
ev = doc.createEvent('Event');
ev.initEvent(e.originalEvent.type, true, false);
for (var key in e.originalEvent) {
// we dont wanna clone target and we are not able to access "private members" of the cloned event.
if (key[0] == key[0].toLowerCase() && $.inArray(key, ['__proto__', 'srcElement', 'target', 'toElement']) == -1) {
ev[key] = e.originalEvent[key];
}
}
doc.dispatchEvent(ev);
});
</script>
<body>
<iframe id="targetFrame" src="eventlistener.html"></iframe>
</body>
Here is my solution with jQuery. You can detect multiple events as I do below. Putting the .on() event handler inside the .on('load') event handler is necessary, because it would stop detecting the iframe content events when the iframe navigates to a new page otherwise. Additionally, I believe this only works if the iframe content is on the same domain as the parent page due to security, and there is no way around that.
$(document).ready(function() {
$('#iframe_id').on('load', function() {
$('#iframe_id').contents().on('click mousemove scroll', handlerFunction);
});
});
handlerFunction() {
//do stuff here triggered by events in the iframe
}
Basic way in document
var IE = document.all?true:false;
// If NS -- that is, !IE -- then set up for mouse capture
if (!IE) document.captureEvents(Event.MOUSEMOVE);
// Set-up to use getMouseXY function onMouseMove
document.onmousemove = getMouseXY;
// Temporary variables to hold mouse x-y pos.s
var tempX = 0;
var tempY = 0;
// Main function to retrieve mouse x-y pos.s
function getMouseXY(e) {
if (IE) { // grab the x-y pos.s if browser is IE
tempX = event.clientX + document.body.scrollLeft;
tempY = event.clientY + document.body.scrollTop;
} else { // grab the x-y pos.s if browser is NS
tempX = e.pageX;
tempY = e.pageY;
}
// catch possible negative values in NS4
if (tempX < 0){tempX = 0}
if (tempY < 0){tempY = 0}
// show the position values in the form named Show
// in the text fields named MouseX and MouseY
console.log(tempX, tempY);
return true;
}
Detect Mouse Move over Iframe
window.frames['showTime'].document.onmousemove = getMouseXY;
Detect Mouse Move over in Child Iframe under parent's Iframe
window.frames['showTime'].document.getElementById("myFrame").contentWindow.onmousemove = getMouseXY;
Trigger an IDLE detect function when no mouse move in Browser.
you can add a overlay on top of iframe when drag begin ( onmousedown event ) , and remove it when drag end ( on mouserup event ).
the jquery UI.layout plugin use this method to solve this problem.

Event listener on a canvas behind another element

I have a mouse move event listener attached to my canvas. But on top of my canvas is a div with a higher z-index, this contains some menu buttons.
The problem i face is, i want the mouse move event to still activate when the mouse is over the menu element - of which is over the canvas element.
Currently, it acts as if the mouse is no longer on top of the canvas because the menu element takes precedence due to z-index order.
Is there a way to make this event listener ignore any elements that get in the way?
My code:
var canvas = new function(){
var self = this
self.outputMouseData = function(evt,el){
var pos = mouse.relativePosition(evt,el);
el.ctx.clearRect(0,0,el.width,el.height);
el.ctx.fillStyle = "white";
el.ctx.font = "bold 16px Arial";
el.ctx.fillText(pos.x+' | '+pos.y, el.width-150,el.height-10);
}
}
elements.addEvent(foreground,'mousemove',
function(evt){ canvas.outputMouseData(evt,foreground); }
);
My HTML
<div class="parent">
<canvas id="canvas"></canvas>
<div class="menu">Menu output</div>
</div>
Parent is relative positioned. Canvas and menu are absolute positioned but menu is z-index'd on top of canvas.
HTML Events are bubbling up the node tree (You can read a good explanation about that here).
What that means is that if you attach an event handler to an element that contains other elements, that handler is called even when the event occurs on a child element (given bubbling wasn't explicitly aborted). You can wrap your canvas & div in a wrapper element (a span for example) and attach the handler on that. You'll get the event regardless of z-index.
Here's a short example of what the code could look like (the getOffsetSum of taken from here):
var canvas = document.getElementById('canvas');
var canvasPos = getOffsetSum(canvas);
var ctx = canvas.getContext('2d');
ctx.fillStyle = "rgb(200,0,0)";
ctx.fillRect(0, 0, 99, 99);
var container = document.getElementById('container');
var mousemove = document.getElementById('mousemove');
container.addEventListener('mousemove', function(evt) {
var pos = getOffsetSum(evt.target);
pos.top += evt.offsetY - canvasPos.top;
pos.left += evt.offsetX - canvasPos.left;
mousemove.innerHTML = 'offsetX: ' + evt.offsetX + ' | offsetY: ' + evt.offsetY + '<br/>' +
'canvasX: ' + pos.left + ' | canvasY: ' + pos.top;
});
function getOffsetSum(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop);
left = left + parseInt(elem.offsetLeft);
elem = elem.offsetParent;
}
return {
top: top,
left: left
}
}
.ontop {
position: absolute;
top: 20px;
left: 20px;
}
<span id="container">
<canvas id="canvas" width="100" height="100"></canvas>
<div class="ontop">ON TOP</div>
</span>
<div id="mousemove"></div>
Put both the canvas and your menu-div into a container div.
Then use jQuery event delegation to listen for mousemove events on the container but have your canvas respond to those mousemove events.
$('#container').on('mousemove','#myCanvas',function(){ doSomething(); }
You can learn more about event delegation here: http://api.jquery.com/on/
Rather than having to use a wrapper as suggested in other answers, you can simply apply pointer-events: none; to the menu div. This will allow the canvas to emit a mousemove event.
.menu {
pointer-events: none;
}
My initial thoughts was to add the "mousemove" event to the document itself (instead of the canvas element or elements), and track the elements using evt.currTarget or evt.target. by this way mousemove evt will always be present whether you hover over the menu or canvas (or anywhere for that matter).

mouseMove very laggy

I am trying to obtain the image effect that 99designs is obtaining when hovering a mouse over a design.. [99designs.ca] Logo design contest: Runningbug Needs Logo 220626
I am currently obtaining the position of the mouse on mousemove, then using that to move my popover <img>, and everything works fine, but it is very laggy.. and presumably its from so many calls being made.
To get the position of the mouse:
jQuery(document).ready(function(){
//$("#special").click(function(e){
$(".imgWrap").mousemove(function(e){
//$('#status2').html(e.pageX +', '+ e.pageY);
//alert(e.pageX + ', ' + e.pageY);
mouseX = e.pageX;
mouseY = e.pageY;
});
})
I'm not sure of another way I can do this.. any ideas?
On the full course of events is the following:
User mouses over an img tag.
I get the position of the mouse as per above.
The <img> tag also calls a js function which changes the position of an img tag to the position of the mouse.
Actually, you can check it here: pokemonsite
update: I see there is a bounty placed (thanks !). I'm a little busy at the moment and can't check all the other answers, but I'll make sure to check them asap
There are several ways to improve performance when using mousemove events.
Use backface-visibility: hidden on popover element to force hardware acceleration. Same thing can be achived with transform: translate3d(0,0,0) but that makes difficult to use CSS transform function (see point #2).
Use CSS transform function for absolute positioning to avoid repaints but keep popover element absolute or fixed positioned.
When setting inline CSS via JS use requestAnimationFrame to avoid unnecesary layout trashing.
(maybe, optionally) hide cursor when hovering and use popover element as position indicator.
Move everything you can from JS to CSS ie. :hover state can be used to toggle display of popover element.
I made demo example combining all things listed. There is still some latency between cursor position and popover image and none of example links in original question work so I can't compare against it but I hope someone finds this useful.
DEMO
<div id="imgHolder" class="imgHolder">
<img src="//placehold.it/200x200" alt="" />
</div>
<div id="bigImgHolder" class="imgHover">
<img src="//placehold.it/500x500" alt="" />
</div>
.imgHover {
display: none;
backface-visibility: hidden;
position: fixed;
top: 0; left: 0;
pointer-events: none;
}
.imgHolder:hover ~ .imgHover { display: block; }
// uncomment if it makes sense
//.imgHolder:hover { cursor: none; }
var posX, posY;
$('#imgHolder').mousemove(HoverImg);
function HoverImg(e) {
posX = e.pageX;
posY = e.pageY;
window.requestAnimationFrame(showBigImg);
}
function showBigImg() {
$('#bigImgHolder').css({'-webkit-transform': 'translateX(' + posX + 'px) translateY(' + posY + 'px)', 'transform': 'translateX(' + posX + 'px) translateY(' + posY + 'px)' });
}
references:
http://davidwalsh.name/translate3d
http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/
https://css-tricks.com/using-requestanimationframe/
Try this:
jQuery(document).ready(function(){
$(".imgWrap").mousemove(function(e){
e.stopPropagation();
mouseX = e.pageX;
mouseY = e.pageY;
});
})
Use e.offsetX and e.offsetY or (recommended) e.clientX and e.clientY instead of pageX and pageY. Maybe this will be a better solution. Note: offsetx and offsety do not work in Firefox as far as I know.
If the absolute (x, y) position is not so important (meaning: some pixel-values can be omitted without destroying your logic), you could try to skip some frames of your mousemove-event.
var globalSkipCounter = 0;
var globalSkipRate = 5;
$(".imgWrap").mousemove(function(e){
if(globalSkipCounter >= globalSkipRate){
var mouseX = e.pageX;
var mouseY = e.pageY;
do_stuff(mouseX, mouseY);
globalSkipCounter = 0;
}
else{
globalSkipCounter+=1;
}
});
This way, you omit redrawing your image on every mousemove-event, instead your draw-routines (do_stuff) are only invoked, once every 5 events.
Cache the position and wrap the update in an if(oldpos !== newpos) type check (remembering to update oldpos inside it).
Use requestAnimationFrame to handle the update - if you have a normal function and pass that as the callback then it will only get called once per frame (ie, don't use an anonymous function).
Finally make use of transform:translate(x,y) to set the position and make better use of the GPU etc. Related to this, there's no harm in making use of the css will-change keyword if you want to use top/left instead.
try a maximum event per second based approach:
jQuery(document).ready(function(){
var now, then, delta, interval = 1000/60; //maximum 60 eps, you can change
//$("#special").click(function(e){
$(".imgWrap").mousemove(function(e){
now = Date.now();
delta = now - then;
if (delta > interval) {
then = now - delta % interval; //subtract extra waited time
//$('#status2').html(e.pageX +', '+ e.pageY);
//alert(e.pageX + ', ' + e.pageY);
mouseX = e.pageX;
mouseY = e.pageY;
// do your thing
}
});
})
EDIT: didn't know then is a reserved word in javascript, you can rename it.
I have a sortable listview in angular, but dragging items with the mouse in chrome was lagging a lot. I tried disabling all chrome extensions and now the lag is totally gone.
It turned out that TamperMonkey was causing it.
Instead of using "left" or "right" property of CSS rather try to use
"transform" I was trying to do the same thing as asked in question, and using "transform" worked for me like a charm.
for example:
transform: translate(30px);
this will move the element, 30px to the right.
by using transform we can move elements to left, right, top and bottom according to the need.

Categories