Как я могу перехватывать события touchmove для элемента, который добавляется в DOM после того, как мой палец уже находится на экране?

Я работаю над проектом Javascript/html5 для iPad.

Мне нужно иметь возможность перехватывать события touchmove для элемента, который не добавляется к DOM до тех пор, пока не сработает событие touchstart (т. е. до тех пор, пока человек не прикоснется пальцем к экрану).

Я попытался смоделировать событие touchstart и запустить его программно...

$( "#container" ).append( element );
element.on( "touchmove", doStuff );
var ev = $.Event( "touchstart" );
element.trigger( ev );

... однако это не работает. Единственный способ, которым я могу заставить doStuff начать стрельбу, — это поднять палец, а затем снова коснуться экрана, вызывая второе событие touchstart.

Как я могу поймать события touchmove для элемента, добавленного в DOM после того, как мой палец уже находится на экране?


person user1031947    schedule 18.09.2014    source источник
comment
Можно ли создать упрощенную версию этой проблемы на jsfiddle.net? Я не слишком хорошо знаком с перетаскиваемыми предметами, но если я смогу с ними поиграться, может быть, мы сможем что-нибудь придумать.   -  person Huangism    schedule 18.09.2014
comment
Конечно, поиграйте здесь: jsfiddle.net/rx4qdtuj/3   -  person user1031947    schedule 18.09.2014
comment
Я не уверен в запуске события, но если ваша цель состоит в том, чтобы переместить поле, когда ваш палец перемещается в первый раз, когда вы касаетесь, вам, возможно, придется получить x и y мыши/касания и соответственно переместить поле   -  person Huangism    schedule 18.09.2014
comment
Цель состоит не в том, чтобы перетаскивать — моя первоначальная формулировка была неправильной — цель состоит в том, чтобы событие touchmove начало запускать новый элемент, когда мой палец касается его, — без необходимости поднимать палец и снова опускать его. По ряду причин я не могу вместо этого прослушивать события touchstart/touchmove для родительского элемента — он должен быть в только что добавленном элементе.   -  person user1031947    schedule 18.09.2014
comment
О, я вижу, я могу заставить его срабатывать один раз, но он не распознает движение от вашего первого прикосновения.   -  person Huangism    schedule 18.09.2014
comment
Да, движение от начального прикосновения — это то, что мне нужно.   -  person user1031947    schedule 18.09.2014
comment
Что-то вроде этого?   -  person Roamer-1888    schedule 19.09.2014
comment
По какой причине вы не принимаете решение Roamer-1888?   -  person ChocolateAndCheese    schedule 16.12.2014


Ответы (3)


Подводя итог, вы, кажется, хотите:

  • on touchstart: для отображения и позиционирования стилизованного элемента div.
  • on touchmove: перетаскивание элемента не отпуская и не нажимая повторно кнопку мыши.

Если эта интерпретация верна, то ответ заключается в том, чтобы обрабатывать события touchmove для того же элемента, на который был первоначально нажат, а именно на элемент "body". Нет необходимости обрабатывать события touchmove элемента, который вы хотите перетащить (добавленный элемент).

Должно быть много способов написать код. Вот один из них, который, вероятно, не совсем то, что вам нужно (в основном в математике позиционирования), но его легко адаптировать:

var $element = $("<div class='element' />");

$("body").on({
    'touchstart mousedown': function (e) {
        $element.appendTo("body");
        $(this).on('touchmove mousemove', move);
        move(e);//you could do `$(this).trigger('touchmove', e)` but a conventional function call keeps `move` simple.
    },
    'touchend mouseup': function (e) {
        $(this).off('touchmove mousemove');
    }
});

function move(e) {
    $element.css({
        left: (e.pageX - 10) + 'px',
        top: (e.pageY - 10) + 'px',
        cursor: 'pointer'
    });
}

mousedown/mousemove/mouseup позволяют тестировать настольные компьютеры и могут быть удалены для использования на сенсорных устройствах.

ДЕМО

person Roamer-1888    schedule 19.09.2014
comment
Спасибо за предоставление решения в рамках спецификации проблемы. Я имел дело с той же проблемой, что и ОП. - person ChocolateAndCheese; 16.12.2014
comment
Спасибо, @ChocolateAndCheese, вы выражаете больше благодарности, даже больше признаков жизни, чем ОП. - person Roamer-1888; 16.12.2014

Если вам просто нужно, чтобы он срабатывал один раз, то это довольно просто

function addElement() {
    $( "body" ).append( element );

    element.on( "touchmove", doStuff );
    element.trigger("touchmove"); 
}

http://jsfiddle.net/rx4qdtuj/8/

Я проверил это на симуляторе ipad. Я заменил предупреждение на добавление, чтобы вы не получали постоянное предупреждение на iPad.

Если вы хотите, чтобы он постоянно срабатывал, единственная возможная вещь, о которой я могу думать, это подделать touchmove на созданном элементе.

http://jsfiddle.net/rx4qdtuj/9/

var element = $("<div class='element' />");

$( "body" ).on( "touchstart", addElement );
$(".wrapper").on("touchmove", addElement);

function addElement() {
    $( "body" ).append( element );

    element.on( "touchmove", doStuff );
    element.trigger("touchmove"); 
}

function doStuff() {
    $('body').append('a ')
}

HTML

<div class="wrapper"></div>

CSS

.wrapper {
    position: absolute;
    top: 100px;
    left: 100px;
    width: 300px;
    height: 300px;
}

Движение фактически срабатывает в уже созданной оболочке div, которая находится в том же месте, что и созданный элемент.

person Huangism    schedule 18.09.2014
comment
К сожалению, мне нужно, чтобы touchmove стрелял сам по себе и неоднократно. - person user1031947; 18.09.2014
comment
А, понятно. К сожалению, в моем случае это тоже не работает. Вместо этого я не могу прослушивать события родительского элемента (сложно...). Я могу прослушивать события только элемента, добавленного в DOM. - person user1031947; 18.09.2014
comment
@ user1031947 почему бы и нет? этот элемент существует с единственной целью захвата touchmove. Вы можете использовать его, чтобы делать все, что нужно, с только что созданным элементом. На самом деле, его можно удалить после завершения touchmove. Извините, это не родитель, это просто еще один элемент, который находится в том же месте, что и созданный элемент. - person Huangism; 18.09.2014
comment
Поскольку IRL — это веб-представление, встроенное в слой steroidsJS, который не становится видимым до тех пор, пока не произойдет событие touchstart в отдельном слое steroids. Это похоже на то, как если бы вы держали палец на экране перед загрузкой и инициализацией страницы, а затем вам нужно было бы обнаружить события touchmove после завершения инициализации страницы, не поднимая палец и не опуская его снова. - person user1031947; 19.09.2014
comment
@user1031947 user1031947, тогда, честно говоря, я вообще не думаю, что это проблема. Если человек коснется экрана до того, как что-то начнет происходить, этот человек будет достаточно умен, чтобы понять, что ему нужно что-то сделать, прежде чем начнет происходить что-то еще. - person Huangism; 19.09.2014
comment
Я здесь не для обсуждения рабочего процесса - мне просто интересно, возможно ли это сделать. Цените вашу помощь, несмотря ни на что. - person user1031947; 19.09.2014
comment
@user1031947 user1031947 Я просто говорю, что ты можешь ни о чем не беспокоиться. Я не думаю, что это возможно, но я действительно ничего не знаю о js lib, который вы используете. - person Huangism; 19.09.2014
comment
Спасибо - да, это немного больно, и если я не смогу понять это, мне придется немного переосмыслить. Я оставлю этот вопрос на некоторое время и посмотрю, появятся ли какие-либо другие предложения. - person user1031947; 19.09.2014

см. документацию по функции перетаскивания

применить вашу функцию

<div id="track" class="track">
<div id="box2" style="left:0; top:0">Drag Me</div>
</div>

родной javascript

window.addEventListener('load', function(){

 var box2 = document.getElementById('box2'),
 boxleft, // left position of moving box
 startx, // starting x coordinate of touch point
 dist = 0, // distance traveled by touch point
 touchobj = null // Touch object holder

 box2.addEventListener('touchstart', function(e){
  touchobj = e.changedTouches[0] // reference first touch point
  boxleft = parseInt(box2.style.left) // get left position of box
  startx = parseInt(touchobj.clientX) // get x coord of touch point
  e.preventDefault() // prevent default click behavior
 }, false)

 box2.addEventListener('touchmove', function(e){
  touchobj = e.changedTouches[0] // reference first touch point for this event
  var dist = parseInt(touchobj.clientX) - startx // calculate dist traveled by touch point
 // move box according to starting pos plus dist
 // with lower limit 0 and upper limit 380 so it doesn't move outside track:
  box2.style.left = ( (boxleft + dist > 380)? 380 : (boxleft + dist < 0)? 0 : boxleft + dist ) + 'px'
  e.preventDefault()
 }, false)

}, false)
person alessandrio    schedule 18.09.2014
comment
Можете ли вы добавить объяснение того, что вы написали здесь? - person Huangism; 18.09.2014
comment
это по ссылкам в начале моего ответа, так как он очень длинный - person alessandrio; 18.09.2014
comment
Затем вставьте или создайте краткую версию объяснения и поместите ее здесь. Если ссылка когда-нибудь сломается, объяснения не будет. - person Huangism; 18.09.2014
comment
четко объяснено в комментариях к коду. конкретно в чем вопрос. - person alessandrio; 18.09.2014
comment
Это не отвечает на мой вопрос. Я спрашиваю, как распознавать события touchmove для элемента, который не добавляется в DOM до тех пор, пока ваш палец не окажется на экране, поэтому на нем не сработает событие touchstart. - person user1031947; 18.09.2014
comment
цикл должен начинаться с первого касания, а не движения - person alessandrio; 18.09.2014