edit- I actually had my image originally position:relative. I have fixed that in my code. I would like the image to scroll left until it has disappeared from the window. I would like it to stop moving, or even reset. I can do that part. I used the developer window in chrome to check, and the position:right of the image in question moves on well past 1700px, which I tried to stop with my if block in paraScrollRight
I'm trying to get an image to stop moving, so that I can get another image to move while the user scrolls down the page. For some reason, my if logic doesn't stop scrolling at all.
var yPos, image;
function paraScrollDown(){
yPos = window.pageYOffset;
image = document.getElementById("image");
image.style.top = (yPos * 1.0) + "px";
}
function paraScrollRight(){
yPos = window.pageYOffset;
image = document.getElementById("image");
if(image.style.right <= 1,374 + "px") {
image.style.right = (yPos * 2.7) + "px";
}
}
window.addEventListener("scroll",paraScrollRight);
<img id="image" style="position:relative" src="https://s-media-cache-ak0.pinimg.com/236x/ee/94/32/ee94322ba44eebc686d2e8381a84259c.jpg" />
Try this: https://jsfiddle.net/92rse23e/
I only handled the paraScrollDown method since that's what I understood what you needed to be taken care of. An important thing you needed to add was to make the image position: absolute; in CSS.
Related
New to javascript. I am trying to use p5.js to allow users the ability to move images on screen when they click on the image and drag their mouse. I have loaded in an image called cart1, with an initial position of (cart1X, cart1Y). Here is my attempt:
function mouseDragged() {
if ((cart1X < mouseX < (cart1X + 50)) && (cart1Y < mouseY < (cart1Y + 50))) {
cart1X = mouseX;
cart1Y = mouseY;
}
}
Where the image is 50px by 50px. This does update the position of the cart, but it is like java script is ignoring my if statement, as it updates the position no matter where the user clicks on screen when dragging. I also tried putting the mouseDragged() function within my if statement, but then nothing happens at all. Any help would be appreciated!
Don't do that, try using :-
if(mousePressedOver (cart1)){
cart1.X = mouse.X;
cart1.Y = mouse.Y;
}
I have an image which I would like to move around on my iPad3
The problem is that it isn't going as good as I hoped for, the image doesn't move smooth and is moving behind the gesture.
What I have is as follows (3MB base64 image)
<img src="data:image/jpeg;base64,/9j/4AAQ....">
css:
img {
transform: translate3d(0,0,0);
}
And the javascript is
img.on('touchstart', function (e) {
var diffX = e.pageX;
var diffY = e.pageY;
img.on('touchmove', function (e) {
translateX += e.pageX - diffX;
translateY += e.pageY - diffY;
img.css({'-webkit-transform': 'translate(' + translateX + 'px, ' + translateY + 'px)'});
diffX = e.pageX;
diffY = e.pageY;
});
return false;
})
...
It works great on my laptop, but not my iPad3.
I also tried requestAnimationFrame, but then nothing happens until I stop moving. Any suggestion how to improve the performance on my iPad ?
This does most of the math outside of the touchmove function
and sets the webkittransform directly without passing by a very long jquery css function.
it also uses the 3d transition witch isn't properly set with just adding translate3d in css file with the ios7
var sx,sy,cx=0,cy=0,img=document.images[0];
img.addEventListener('touchstart',ts,false);
img.addEventListener('touchmove',tm,false);
img.addEventListener('touchend',te,false);
function ts(e){
e.preventDefault();
sx=e.pageX-cx;
sy=e.pageY-cy;
}
function tm(e){
this.style.webkitTransform='translate3d('+
(e.pageX-sx)+'px,'+(e.pageY-sy)+'px,0)';
}
function te(e){
cx=e.pageX-sx;
cy=e.pageY-sy;
}
another point is ... even if you have the ipad 3 it can't handle a big image like that so consider putting all inside a div with overflow:hidden this will increase the performance too.
div{
width:400px;/*try 100%*/
height:400px;/*try 100%*/
overflow:hidden;
}
Mouse move example (not touch but its the same except you don't need the isup check)
http://jsfiddle.net/AtBUh/
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.
My problem:
Changing the margin-top property via JavaScript objectName.style.marginTop = value; works well in Chrome and Safari, however in Firefox, the positioning seems to be all wrong. Instead of placing the element over the viewport, subsequently lowering it until it is slightly underneath the desired position and then moving it up a bit, Firefox places it way underneath the final position, moves it up and then down, almost mirroring the desired animation.
If I switch of Javascript and enter the value in CSS, the positioning is alright, so I guess the mistake lies in the .js.
Context:
I am trying to create a simple animated logo via JavaScript. I want it to drop from outside the browser viewport into its position. The logo is the HTML-element <img id="site_logo" src="logo.png" />
Here goes the JavaScript code:
var logoValue = -400;
function onLoad(){
// ...
logoStarter();
}
function logoStarter(){ //sets the logo in its starting position outside the viewport
var site_logo = document.getElementById("site_logo");
site_logo.style.marginTop = logoValue +"px";
logoAnimationDown();
}
function logoAnimationDown(){ // moves the logo down until it is somewhat underneath its final position
if(logoValue <= 20){
console.log(logoValue);
logoValue += 17;
var site_logo = document.getElementById("site_logo");
site_logo.style.marginTop = logoValue +"px";
setTimeout('logoAnimationDown()', 30);
}
else{
setTimeout('logoAnimationUp()', 30);
}
}
function logoAnimationUp(){ // moves the logo up to its final position
if(logoValue > 0){
console.log(logoValue);
logoValue -= 10;
var site_logo = document.getElementById("site_logo");
site_logo.style.marginTop = logoValue + "px";
setTimeout('logoAnimationUp()', 30);
}
}
It seems that FF does the procedure twice. Declare your setTimeouts like this:
setTimeout(logoAnimationDown, 30);
setTimeout(logoAnimationUp, 30);
If you use this kind of a quoted string setTimeout('doFunction()',30) to assign the target function, FF does this: eval('doFunction()'), and executes the function immediately (beacause of "()"), and then again after the delay time.
function jsiBoxAdjustTop()
{
var top
if ( jsiBox.preloadImg.height <= 699){
top = 216;
}
else{
top = 17;
}
jsiBox.boxNode.style.top = (top) + 'px';
}
I'm using that function to adjust a div's top position depending on the image that is in it's height. It's on a light box sort of script so every time I click the next button, a new image which could either be taller or smaller appears. It's working alright and it adjusts its position when the image is taller but my problem is it just jumps to that position. I'm really new to javascript so can anyone help me out to make this as if it's travelling/animating to it's position? I tried using setTimeOut but I think I was doing it wrong. I'd really love to know what I'm doing wrong.
Here's the full script if that helps. Link
you can use jQuery or YUI to do animate, such as
jQuery(jsiBox.boxNode).animate({'top': top}, 3000);
or you can write some simple code with setTimeout just for this case;
following code assume the begin top is 0.
var boxStyle = jsiBox.boxNode.style;
function animateTop(to) {
boxStyle.top = parseInt(boxStyle.top, 10) + 1 + 'px';
if (parseInt(boxStyle.top, 10) != to) {
setTimeout(function() {
animate(to);
}, 50);
}
}
animateTop(top);