I build a website with some sliders (Wordpress - Divi). I added some javascript to let the slider description follow the mousepointer when the mouse hovers over the slider. Works perfectly, BUT: when I scroll the mouse the pointer shifts downwards as expected, but the slider description does not shift accordingly; it remains where it was. So from that point on the link between the mouse and the description is gone.
Question: how can I enforce the description to follow the mouse when scrolling......
If you want to see the result until now, please check https://roel.famnabuurs.nl
Any help appreciated
The code as requested:
const sliderzelf = document.getElementById(slidernaam);
const titleblockslist = document.getElementById(slidernaam).getElementsByClassName('et_pb_slide_description');
for (let indslide of titleblockslist) {
indslide.style.setProperty('opacity',1, 'important');
var sliderOffset = sliderzelf.getBoundingClientRect();
let xpos = e.clientX - sliderOffset.left ;
// do not shift too far to the right
if (xpos > sliderzelf.clientWidth - indslide.clientWidth) {
xpos = sliderzelf.clientWidth - indslide.clientWidth;
}
if (xpos < 15) {
// do not shift too far to the left
xpos = 15;
}
indslide.style.left = (xpos) + 'px';
indslide.style.top = e.clientY + 'px';
}
Related
I want to pan an element only vertically and it gets resized and minimized (transforming scale and origin) until reaching the bottom of the screen when I release the touch. This behaviour that I try to reproduce is very simillar with the behaviour of the video stream on youtube(when you drag the video down it sends the container in the bottom right of the screen).
function dragStart(e) {
var transforms = [];
e.preventDefault();
currentScale = adjustScale - (e.distance/1000);
console.log(currentScale);
currentDeltaX = adjustDeltaX + (e.deltaX / currentScale);
currentDeltaY = adjustDeltaY + (e.deltaY / currentScale);
transforms.push('scale(' + currentScale + ')');
elem.style.transform = transforms.join(' ');
elem.style.transformOrigin = "100% 100%";
}
This is a sample of my code: https://codepen.io/ACondur/pen/qVYeVJ
The questions are:
How to make the pan accept only vertical pan?
How to make the element scale properly?
How to stop the panning of the element when it reaches the width that I want it to be?
What I'm trying to create is a small canvas widget that would allow a user to dynamically create a shape onto an image and then place it above an area that caught their interest, effectively it is a highlighter.
The problem is with adding a zoom function, as when I zoom onto the image I would like to ensure that;
There is no possible way for the dynamically created shape to be
dragged anywhere outside the image area. (completed - ish, relies on 2nd step)
You cannot drag the image out of the page view, the canvas area cannot show white space. Part of the image must always be shown, and fill the entire canvas area. (problem)
Here are two examples that I've drawn up, neither of which work correctly;
First example - getBoundingRect does not update and is bound to the image
Second example - getBoundingRect does update and is bound to the grouped object
From the link description you can see that I think I've narrowed the problem down, or at least noticed a key difference between the scripts with how the getBoundingRect behaves.
The first plunk seems to work fine, until you try to zoom in multiple times and at a greater zoom level, then it seems to start bugging out (may take a few clicks and a bit of messing around, it is very inconsistent). The second plunk is very jittery and doesn't work very well.
I've been stuck on this for a week or so now, and I'm at breaking point! So really hoping someone can point out what I'm doing wrong?
Code snippet below for first plunk;
// creates group
var objs = canvas.getObjects();
var group = new fabric.Group(objs, {
status: 'moving'
});
// sets grouped object position
var originalX = active.left,
originalY = active.top,
mouseX = evt.e.pageX,
mouseY = evt.e.pageY;
active.on('moving', function(evt) {
group.left += evt.e.pageX - mouseX;
group.top += evt.e.pageY - mouseY;
active.left = originalX;
active.top = originalY;
originalX = active.left;
originalY = active.top;
mouseX = evt.e.pageX;
mouseY = evt.e.pageY;
// sets boundary area for image when zoomed
// THIS IS THE PART THAT DOESN'T WORK
active.setCoords();
// SET BOUNDING RECT TO 'active'
var boundingRect = active.getBoundingRect();
var zoom = canvas.getZoom();
var viewportMatrix = canvas.viewportTransform;
// scales bounding rect when zoomed
boundingRect.top = (boundingRect.top - viewportMatrix[5]) / zoom;
boundingRect.left = (boundingRect.left - viewportMatrix[4]) / zoom;
boundingRect.width /= zoom;
boundingRect.height /= zoom;
var canvasHeight = canvas.height / zoom,
canvasWidth = canvas.width / zoom,
rTop = boundingRect.top + boundingRect.height,
rLeft = boundingRect.left + boundingRect.width;
// checks top left
if (rTop < canvasHeight || rLeft < canvasWidth) {
group.top = Math.max(group.top, canvasHeight - boundingRect.height);
group.left = Math.max(group.left, canvasWidth - boundingRect.width);
}
// checks bottom right
if (rTop > 0 || rLeft > 0) {
group.top = Math.min(group.top, canvas.height - boundingRect.height + active.top - boundingRect.top);
group.left = Math.min(group.left, canvas.width - boundingRect.width + active.left - boundingRect.left);
}
});
// deactivates all objects on mouseup
active.on('mouseup', function() {
active.off('moving');
canvas.deactivateAll().renderAll();
})
// sets group
canvas.setActiveGroup(group.setCoords()).renderAll();
}
EDIT:
I've added comments and tried to simplify the code in the plunks.
The relevant code starts within the if (active.id == "img") { code block.
I've put irrelevant code as functions at the bottom, they can largely be ignored. ( createNewRect() + preventRectFromLeaving() )
I've removed one of the plunks to avoid confusion.
Let me know if it helps, or If I should try to simplify further.
Thanks!
I think that the grouping was messing with the position of the background image. So, I tried removing the group when the image is moving and manually updating the position of the rect instead.
It sets the last position of the image before moving
var lastLeft = active.left,
lastTop = active.top;
And then it updates those and the position of the rect every time the image moves
rect.left += active.left - lastLeft;
rect.top += active.top - lastTop;
// I think this is needed so the rectangle can be re-selected
rect.setCoords();
lastLeft = active.left;
lastTop = active.top;
Since the image has to stay within the canvas, the rect stays inside the canvas, too, whenever the image moves. The rest of the code you wrote seemed to work fine.
http://plnkr.co/edit/6GGcUxGC7CjcyQzExMoK?p=preview
I am building a custom tooltip functionality where I am supposed to show a video as a tooltipo over an image. Now, I have some initial thing working, but I am stuck at finding the area around mouse pointer where I should display the tooltip.
I am having the tooltip always visible at the bottom right of mouse cursor, no matter where mouse currently is in screen, this is what I have so far :
window.onmousemove = function (e) {
var x = e.clientX, y = e.clientY;
tooltipSpan.style.top = (y + 10) + 'px';
tooltipSpan.style.left = (x + 10) + 'px';
};
where tooltip is my target element.
What I am looking for, is, that my code should find the largest area around mouse available on screen, and adjust the tooltip to display there. Any pointers for this would help a lot.
Note: jQuery is not an option, I have to build in core JS.
You can get the width and the dimensions of the viewport using window.innerWidth and window.innerHeight (in my example below this refers to window because the code is running inside window)
Using viewport dimensions and the mouse position using ev.clientX/Y you can determine the pixel space on the left/right and top/bottom side of the cursor as in example below.
Using property offsetWidth and offsetHeight we get the dimensions of the tooltip and we can use that to set the tooltip position relative to cursor position. For example if the topLeft quadrant is the largest, the tooltip will show top left relatively to cursor (meaning the bottom right corner of the tooltip will "touch" the cursor).
I hope this example helps :).
var tooltip = this.document.getElementsByClassName("tooltip")[0];
window.onmousemove = function(ev) {
// Getting pixel space
var leftPixelSpace = ev.clientX;
var rightPixelSpace = this.innerWidth - leftPixelSpace;
var topPixelSpace = ev.clientY;
var bottomPixelSpace = this.innerHeight - topPixelSpace;
// Determining the position of topleft corner of the tooltip
var tooltipPosX = leftPixelSpace > rightPixelSpace ? leftPixelSpace - tooltip.offsetWidth : leftPixelSpace;
var tooltipPosY = topPixelSpace > bottomPixelSpace ? topPixelSpace - tooltip.offsetHeight : topPixelSpace;
// Setting tooltip position
tooltip.style.left = tooltipPosX+"px";
tooltip.style.top = tooltipPosY+"px";
};
.tooltip {
width: 150px;
height: 100px;
border: 1px solid black;
background-color : lightblue;
text-align: center;
position: absolute
}
<div class="tooltip">floating tooltip</div>
Something like this? A switch with conditions for calculating in which quadrant the mouse cursor is.
var wM = window.innerWidth / 2;
var hM = window.innerHeight / 2;
document.addEventListener('mousemove', function(e) {
var w = e.clientX;
var h = e.clientY;
var pos;
switch (true) {
case (w <= wM && h <= hM):
pos = 'top-left';
break;
case (w <= wM && h >= hM):
pos = 'bottom-left';
break;
case (w > wM && h < hM):
pos = 'top-right';
break;
case (w > wM && h > hM):
pos = 'bottom-right';
break;
default:
pos = undefined;//Here you could even assign a default quadrant to relay on, in case any condition is met.
}
console.log(pos);
});
wM for widthMiddle, the middle point in the window's width.
hM: same, but with the height.
w for the mouse width/X position; h for height/Y.
A switch based on conditions according to a quadrant system.
In javascript, is there a way I can create a variable and a function that "simulates" smooth mouse movement? i.e., say the function simulates a user starts from lower left corner of the browser window, and then moves mouse in a random direction slowly...
The function would return x and y value of the next position the mouse would move each time it is called (would probably use something like setInterval to keep calling it to get the next mouse position). Movement should be restricted to the width and height of the screen, assuming the mouse never going off of it.
What I don't want is the mouse to be skipping super fast all over the place. I like smooth movements/positions being returned.
A "realistic mouse movement" doesn't mean anything without context :
Every mouse user have different behaviors with this device, and they won't even do the same gestures given what they have on their screen.
If you take an FPS game, the movements will in majority be in a small vertical range, along the whole horizontal screen.
Here is a "drip painting" I made by recording my mouse movements while playing some FPS game.
If we take the google home page however, I don't even use the mouse. The input is already focused, and I just use my keyboard.
On some infinite scrolling websites, my mouse can stay at the same position for dozens of minutes and just go to a link at some point.
I think that to get the more realistic mouse movements possible, you would have to record all your users' gestures, and repro them.
Also, a good strategy could be to get the coordinates of the elements that will attract user's cursor the more likely (like the "close" link under SO's question) and make movements go to those elements' coordinates.
Anyway, here I made a snippet which uses Math.random() and requestAnimationFrame() in order to make an object move smoothly, with some times of pausing, and variable speeds.
// Canvas is here only to show the output of function
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
var maxX = canvas.width = window.innerWidth;
var maxY = canvas.height = window.innerHeight;
window.onresize = function(){
maxX = canvas.width = window.innerWidth;
maxY = canvas.height = window.innerHeight;
}
gc.onclick = function(){
var coords = mouse.getCoords();
out.innerHTML = 'x : '+coords.x+'<br>y : '+coords.y;
}
var Mouse = function() {
var that = {},
size = 15,
border = size / 2,
maxSpeed = 50, // pixels per frame
maxTimePause = 5000; // ms
that.draw = function() {
if (that.paused)
return;
that.update();
// just for the example
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(show.checked){
ctx.drawImage(that.img, that.x - border, that.y - border, size, size)
}
// use requestAnimationFrame for smooth update
requestAnimationFrame(that.draw);
}
that.update = function() {
// take a random position, in the same direction
that.x += Math.random() * that.speedX;
that.y += Math.random() * that.speedY;
// if we're out of bounds or the interval has passed
if (that.x <= border || that.x >= maxX - border || that.y <= 0 || that.y >= maxY - border || ++that.i > that.interval)
that.reset();
}
that.reset = function() {
that.i = 0; // reset the counter
that.interval = Math.random() * 50; // reset the interval
that.speedX = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the horizontal direction
that.speedY = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the vertical direction
// we're in one of the corner, and random returned farther out of bounds
if (that.x <= border && that.speedX < 0 || that.x >= maxX - border && that.speedX > 0)
// change the direction
that.speedX *= -1;
if (that.y <= border && that.speedY < 0 || that.y >= maxY - border && that.speedY > 0)
that.speedY *= -1;
// check if the interval was complete
if (that.x > border && that.x < maxX - border && that.y > border && that.y < maxY - border) {
if (Math.random() > .5) {
// set a pause and remove it after some time
that.paused = true;
setTimeout(function() {
that.paused = false;
that.draw();
}, (Math.random() * maxTimePause));
}
}
}
that.init = function() {
that.x = 0;
that.y = 0;
that.img = new Image();
that.img.src ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABJUlEQVRIic2WXbHEIAyFI6ESKgEJkVIJlYCTSqiESIiESqiEb19gL9Od3f5R5mbmPPHwBTgnIPJfChiAGbCkCQgtG7BpmgAWIALaDDyOI2bGuq40BasqIoKZATgwNAWHEEjHbkBsBhYRVJUYIwBNwVlFaVOwiDDPMylmQ1OwquY7d0CBrglYkuEeidoeOKt61I6Cq0ftKFhqR+0MOKuo2BQsInnndvnOr4JvR+0qWO5G7Q44K0XtOXDf96jqh9z9WXAy1FJ8l0qd+zbtvU7lWs7wIzkuh8SvpqqDi3zGndPQauDkzvdESm8xZvbh4mVZ7k8ud/+aR0C3YPk7mVvgkCZPVrdZV3dHVem6bju1roMPNmbAmq8kG+/ynD7ZwNsAVVz9dL0AhBrZq7F+CSQAAAAASUVORK5CYII=";
that.reset();
}
that.getCoords = function(){
return {x: that.x, y:that.y};
}
that.init()
return that;
}
var mouse = new Mouse()
mouse.draw();
html,body {margin: 0}
canvas {position: absolute; top:0; left:0;z-index:-1}
#out{font-size: 0.8em}
<label for="show">Display cursor</label><input name="show" type="checkbox" id="show" checked="true"/><br>
<button id="gc">get cursor Coords</button>
<p id="out"></p>
Last I heard the browser's mouse position cannot be altered with JavaScript, so the question really has no answer "as is". The mouse position can be locked though. I'm not certain whether it would be possible to implement a custom cursor that allows setting the position. This would include hiding and perhaps locking the stock cursor.
Having something smoothly follow the cursor is quite straight forward. You may be able to reverse this process to achieve what you need. Here's a code snippet which simply calculates the distance between the cursor and a div every frame and then moves the div 10% of that distance towards the cursor:
http://jsfiddle.net/hpp0qb0d/
var p = document.getElementById('nextmove')
var lastX,lastY,cursorX,cursorY;
window.addEventListener('mousemove', function(e){
cursorX = e.pageX;
cursorY = e.pageY;
})
setInterval(function(){
var newX = p.offsetLeft + (cursorX - lastX)/10
var newY = p.offsetTop + (cursorY - lastY)/10
p.style.left = newX+'px'
p.style.top = newY+'px'
lastX = p.offsetLeft
lastY = p.offsetTop
},20)
I want find top position of rotated div from element, I can able find top position of element but I want top(Y pos) position from left(x) position.
I am used this
var degree = degree;
if (degree < 0) {
var sign = -1;
} else {
var sign = 1;
}
var numY = Math.abs(myElem.position().top + sign * ((myElem.outerHeight() / 2) - Math.sin(degree)));
var numX = 0
var bottom = myElem.position().top + myElem.outerHeight(true);
y = numY;
Thanks in Advance
Slope:20 deg, height: 20px,width:400px, left 150px i want find top position
I want to re arrange dragged items after rotation for that I am finding top position.
Please find the jsbin link drop weights into plank.
I think it makes more sense to add the draggable image into the rotated div and to let everything rotate together, rather than worrying about the position of the draggable image. Here is a jsfiddle with your code updated (I only implemented dropping on the right side): http://jsfiddle.net/brendaz/17wwtffz/
drop:
// ...
var offset = ui.draggable.offset();
var rotateOffset = $('.rotatableAra').offset();
// Take the weight out of it's parent div and add it to the rotatable area
ui.draggable.remove();
ui.draggable.addClass("dropped");
ui.draggable.addClass("rightPlankDropped");
$('.rotatableAra').append(ui.draggable);
ui.draggable.css("top", ($('.rightPlank').position().top- ui.draggable.height()).toString() + "px");
ui.draggable.css("left", (offset.left - rotateOffset.left).toString() + "px");
rightArray[ind] = $textval * pos;
// ...