How to make an image "loose" inside a div

6

I need to leave a "loose" image within div on my mobile site. The div has fixed dimensions but the image is much larger, so it would have to be something similar to iframe , however, without scrolling and the user can move the image freely with the 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 effect: (click to see the animated GIF)

An observation that may be important: I had to disable the "zoom" of the site, for reasons of greater forces .. in this, the pinch with the fingers I believe will not work, only with the basic movement of the fingers.

    
asked by anonymous 20.10.2014 / 18:51

1 answer

6

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

About the touchmove position:

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

(I'm using e.originalEvent because jQuery does not provide the touch property in the event. It only has the originalEvent property where it passes a reference to the original event).

So 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 this 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 toggleDrag function checks if the event type is to start and gives a true value to the flag that holds the information if the drag is happening. This function also saves the position of the event in relation to the position of the image, so that it can have this information in the other function when moving the image. I've put together 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 drag function changes the margin left and top according to mouse position.

It would still be possible to measure the speed of the touch so that you can move quickly and with acceleration effect. But that fits in well with another question. And part of it I've already replied here: How to know the direction of scrolling the mouse wheel

Example: link

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';
}
    
20.10.2014 / 20:29