How to make an image "loose" inside a div

Asked

Viewed 1,438 times

6

I need to leave a "loose" image inside a div on my mobile site. A div has fixed dimensions but the image is much larger, so it would have to be something similar to iframe, however, without scroll and the user will be able to move the image freely with his fingers.

Actually, it’s a list of images, each using the same class.

Example:

<div class="box">
   <img src="imagem1" class="dragme" />
</div>
<div class="box">
   <img src="imagem2" class="dragme" />
</div>
<div class="box">
   <img src="imagem3" class="dragme" />
</div>
<div class="box">
   <img src="imagem4" class="dragme" />
</div>

Example of the effect: (click to see the animated GIF)

A remark that may be important: I had to disable the "zoom" of the site, for reasons of larger forces.. In this, the "Pinch" with the fingers I believe will not work, being only with the basic movement of the fingers.

  • 1

    Please post the image here, if the tinypic disappears, the question loses quite a bit of meaning...

  • You’re right.. Edited question.

  • Can you make this image stop moving? I was a bit dizzy reading this question kkk

  • 1

    @Rodrigoborth, I just fixed it :)

  • 2

    Is it supposed to look like the last comic? http://xkcd.com/1110/ (I hope you’re in time)

  • @Bacco yes, like the last comic.

Show 1 more comment

1 answer

6


What you need is drag-like functionality.
I leave below an example I did now for drag on touch and mouse.

About the position of the touchmove:

The event that is passed in the eventhandler is different for mouse and touch events. In mouse events the pointer position is obtained by evento.clientX and evento.clientY. However in touch this event is in evento.touches[0].clientX and public relations. evento.touches[0].clientY. Because of this I had to add a function to normalize the event detecting whether it is a touch or a mouse. I could have done via e.type but I chose this.

(I’m using e.originalEvent because jQuery does not provide the property touch at the event. Available only on the property originalEvent where it passes a reference to the original event).

Therefore the function to normalize the position:

function normalizarEvento(e) {
    if (e.originalEvent.touches && e.originalEvent.touches.length) return e.originalEvent.touches[0];
    return e;
}

For that you need to listen to some events:

To start the drag:

$('img').on('mousedown touchstart', toggleDrag);

To stop the drag:

$('img').on('mouseup touchend mouseout', toggleDrag);

The function toggleDrag checks if the event type is to start and gives a value true the flag that stores the information if the drag is happening. This function also stores the position of the event in relation to the position of the image, in order to have this information in the other function when moving the image. I added an extra function for this given the relative position on the page:

function buscarPosicaoRelativa(el) {
    var bodyRect = document.body.getBoundingClientRect();
    var elemRect = el.getBoundingClientRect();
    return {
        x: elemRect.left - bodyRect.left,
        y: elemRect.top - bodyRect.top
    }
}

The function drag changes the margin left and top as the mouse position.

It would also be possible to measure the speed of the touch to be able to move quickly and with an acceleration effect. But this fits well with another question. And part of it I’ve already answered here: How to know the scroll direction of the mouse wheel

Example: http://jsfiddle.net/3t6q1hme/

var ondrag = {};
$('.dragme').on('mouseup touchend mouseout', toggleDrag);
$('.dragme').on('mousedown touchstart', toggleDrag);
$('.dragme').on('mousemove touchmove', drag);

function normalizarEvento(e) {
    if (e.originalEvent.touches && e.originalEvent.touches.length) return e.originalEvent.touches[0];
    return e;
}

function buscarPosicaoRelativa(el) {
    var bodyRect = document.body.getBoundingClientRect();
    var elemRect = el.getBoundingClientRect();
    return {
        x: elemRect.left - bodyRect.left,
        y: elemRect.top - bodyRect.top
    }
}

function toggleDrag(evt) {
    evt.preventDefault();
    var moveTouch = normalizarEvento(evt);
    ondrag.on = evt.type == 'mousedown' || evt.type == 'touchstart';
    if (ondrag.on) ondrag.start = {
        x: moveTouch.clientX - this.getBoundingClientRect().left,
        y: moveTouch.clientY - this.getBoundingClientRect().top
    };
}

function toggleDrag(evt) {
    evt.preventDefault();
    var moveTouch = normalizarEvento(evt);
    var posicaoElemento = buscarPosicaoRelativa(this);
    ondrag.on = evt.type == 'mousedown' || evt.type == 'touchstart';
    if (ondrag.on) ondrag.start = {
        x: moveTouch.clientX - posicaoElemento.x + this.parentNode.getBoundingClientRect().left,
        y: moveTouch.clientY - posicaoElemento.y + this.parentNode.getBoundingClientRect().top
    };
}

function drag(evt) {
    evt.preventDefault();
    var moveTouch = normalizarEvento(evt);
    if (!ondrag.on) return;
    var x = moveTouch.clientX;
    var y = moveTouch.clientY;
    this.style.marginLeft = x - ondrag.start.x + 'px';
    this.style.marginTop = y - ondrag.start.y + 'px';
}
  • 3

    propose onDragon or onDragão :) I just tested a variable with accent (ondragão) and the fiddle accepted (¡?)

  • Replaces $('img') by a specific class, and that class has position:relative. The effect didn’t work, it has something to do with that position?

  • @brasofilo picked up a website that classes and functions had accents... it’s funny to take jobs like this

  • I believe that it should not be by positioning. I am not able to make it work. Maybe because it is a list of images? All with the same class and when you "move" one of them, it gives conflict with the others?

  • @Ricardo can edit my jsFiddle and put here the code with problems?

  • @Sergio sim, http://jsfiddle.net/z53te9u4/9/ - Note that only the first one you touch works, the other "Uga".

  • 1

    @Ricardo added more details to the answer and changed jsFiddle to the new version.

  • @Yes, in JS almost everything is valid as identifier.

  • @Cool Sergio, now it’s more like what I need. The only problem is that when I click first on the last one, or the last one, they disappear!

  • @Sergio Tested now on my mobile and in fact the images are disappearing when played. Some do not disappear completely, just scroll down.

  • @Have you tested with the version in the post? (this: http://jsfiddle.net/3t6q1hme/) On my iPdad it works, I can test iPhone later.

  • 1

    @Ricardo tested on iPhone and tablet Samsung and jsFiddle works well. Which platform are you using?

  • @Sergio seriously? Well, by the tests done on Chroms Desktop, gives this bug. Use iPhone 5C. Soon I will do more tests and return. Thanks :D

  • @Sergio noticed that there are two function toggleDrag(evt) and was giving conflict. I took one and it worked! Thank you!!

  • 1

    @Ricardo Aha, Sorry, please. It should not differ because re-declaring one function causes the other to be overwritten, but should: http://jsfiddle.net/3t6q1hme/4/

Show 10 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.