iOS/Android浏览器:在touchmove上显示按钮的放大预览 [英] iOS/Android browser: showing a zoomed preview of button on touchmove

查看:103
本文介绍了iOS/Android浏览器:在touchmove上显示按钮的放大预览的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建类似于iPhone键盘的行为(请参见随附的图片).如图所示,当用户启动并移动触摸时,她会看到被触摸元素的缩放版本,并且在触摸时会进行选择.我正在使用Zepto.

I'm trying to create behavior similar to iPhone keyboard (see included image). As in, when user starts and moves touch, she sees a zoomed version of the element that is touched, and selection would happen when on touch up. I'm using Zepto.

我可以正确获取触摸坐标,但是在找到手指下方的物体时遇到了麻烦.我正在使用下面的代码来检查返回哪个元素作为事件的目标.

I can get the touch coordinates correctly, but have trouble finding the object that's under the finger. I'm using below code to check which element is returned as target of the event.

$("#myList li").live('touchmove', function(event) {
  console.log(event.touches[0].target.innerHTML);
});

这总是返回在starttouch上的事件.

This returns always the event that was on starttouch.

Apple文档触摸应该有 event.touches event.changedTouches event.targetTouches

On Apple documentation the touch should have event.touches event.changedTouches event.targetTouches

我尝试检查每个对象上的第一个元素,但它们似乎都只包含starttouch-element作为目标.这里有我想念的东西吗?

I've tried checking the first element on each of the objects, but they all seem to contain just the starttouch-element as target. Is there something I'm missing here?

我从以下位置正确获取了触摸的坐标

I get the coordinates for the touch correctly from

var positionTop = event.touches[0].pageY;
var positionLeft = event.touches[0].pageX;

如果所有其他方法都失败了,我开始认为也许有一种方法可以在与坐标接触的情况下找到DOM元素.

If all else fails, I started to think maybe there's a way to find the DOM-element under the touch with the coordinates.

任何想法都值得赞赏.

推荐答案

触摸事件下的对象由event.target给出.另外,您应该绑定到touchstarttouchend事件.看到我做的这个例子:

The object that is under the touch event is given by event.target. Also, you should bind to touchstart and touchend events. See this example I made:

http://ampersand.no.de/iOSkeyboard.html

源代码:

<html>

<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<style>
body{
    font-family:arial;
    -webkit-user-select: none;
    -khtml-user-select: none;
    -moz-user-select: none;
    -o-user-select: none;
    user-select: none;
}
.entry{
    border:1px solid green;
    color:darkGreen;
    margin:25px;
    font-size:25px;
    font-family:verdana, arial,"sans serif";
    padding:10px;
    width:500px;
    word-wrap:break-word;
}
.wrapper{
    height:200px;
    position:relative;
    margin:25px;
}
.keyboard{
    position:absolute;
    bottom:0;
}

.key{
    border:1px solid darkGray;
    display:inline-block;
    text-align:center;
    cursor:pointer;
    margin-top:1px;
    border-radius: 4px;
    font-family:arial,"sans serif";
    width:30px;
    height:30px;
    line-height:30px;
}

.shift{
    width:60px;
    margin-left:35px;
}
.spacebar{
    width:126px;
}
.backspace{
    width:60px;
}

.keypress{
    border:1px solid blue;
}

#floatKey{
    border-bottom-left-radius:10px;
    border-bottom-right-radius:10px;
    border-bottom:0px;
    border-color:blue;
    font-weight:bold;
    font-size:24px;
    cursor:pointer;
    width:40px;
    height:40px;
    line-height:40px;
    background-color:white;
    -moz-box-shadow: -5px 0px 5px #ccc;
    -webkit-box-shadow: -5px 0px 5px #ccc;
    box-shadow: -5px 0px 5px #ccc;
}

.touchStart{
    border-color:blue;
    border-top:0px;
    border-top-left-radius:0px;
    border-top-right-radius:0px;
    -moz-box-shadow: -5px 5px 5px #ccc;
    -webkit-box-shadow: -5px 5px 5px #ccc;
    box-shadow: -5px 5px 5px #ccc;
}

</style>
</head>

<body>
<h3>iOS-style keyboard examples</h3>
<div class="entry">|</div>

<div class="wrapper">
    <div>With mouse events:</div>
    <div class="keyboard" id="mousekb">
        <div class="row">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
            <span>5</span>
            <span>6</span>
            <span>7</span>
            <span>8</span>
            <span>9</span>
            <span>0</span>
        </div>
        <div class="row">
            <span>q</span>
            <span>w</span>
            <span>e</span>
            <span>r</span>
            <span>t</span>
            <span>y</span>
            <span>u</span>
            <span>i</span>
            <span>o</span>
            <span>p</span>
        </div>
        <div class="row" style="margin-left:18px">
            <span>a</span>
            <span>s</span>
            <span>d</span>
            <span>f</span>
            <span>g</span>
            <span>h</span>
            <span>j</span>
            <span>k</span>
            <span>l</span>
        </div>
        <div class="row">
            <span>z</span>
            <span>x</span>
            <span>c</span>
            <span>v</span>
            <span>b</span>
            <span>n</span>
            <span>m</span>
            <span>,</span>
            <span>.</span>
        </div>
        <div class="row">
            <span class="shift">shift</span>
            <span class="spacebar">&nbsp;</span>
            <span class="backspace">&lArr;</span>
        </div>
    </div>
</div>

<div class="entry">|</div>
<div class="wrapper">
    <div>With touch events (zoom in for better view):</div>
    <div class="keyboard" id="touchkb">
        <div class="row">
            <span>1</span>
            <span>2</span>
            <span>3</span>
            <span>4</span>
            <span>5</span>
            <span>6</span>
            <span>7</span>
            <span>8</span>
            <span>9</span>
            <span>0</span>
        </div>
        <div class="row">
            <span>q</span>
            <span>w</span>
            <span>e</span>
            <span>r</span>
            <span>t</span>
            <span>y</span>
            <span>u</span>
            <span>i</span>
            <span>o</span>
            <span>p</span>
        </div>
        <div class="row" style="margin-left:18px">
            <span>a</span>
            <span>s</span>
            <span>d</span>
            <span>f</span>
            <span>g</span>
            <span>h</span>
            <span>j</span>
            <span>k</span>
            <span>l</span>
        </div>
        <div class="row">
            <span>z</span>
            <span>x</span>
            <span>c</span>
            <span>v</span>
            <span>b</span>
            <span>n</span>
            <span>m</span>
            <span>,</span>
            <span>.</span>
        </div>
        <div class="row">
            <span class="shift">shift</span>
            <span class="spacebar">&nbsp;</span>
            <span class="backspace">&lArr;</span>
        </div>
    </div>
</div>

<div id="floatKey" class="key" style="display:none"></div>

<script>
SHIFT=false;
$('.keyboard span').addClass('key');


function touchStart(ev){
    ev.preventDefault();
    var o=$(ev.target).offset();
    $('#floatKey').html($(ev.target).html())
        .show()
        .offset({top:(o.top-$('#floatKey').outerHeight()), left:(o.left-5)});
    $(ev.target).addClass('touchStart');
}

function touchEnd(ev){
    ev.preventDefault();
    $('#floatKey').hide();
    $(ev.target).removeClass('touchStart');
}

function keyrelease(ev){
    ev.preventDefault();
    outlineKey(ev.target);
    $(ev.target).removeClass('keydown');
    $('#floatKey').removeClass('keydown');
    var text=$('.entry').eq(0).text();
    $('.entry').text(text.substr(0,text.length-1)+$(ev.target).text()+'|');
}

function shiftKey(ev){
    ev.preventDefault();
    if(SHIFT){
        $('.keyboard span').not('.shift').each(function(idx,el){
            $(el).text($(el).text().toLowerCase());
        })
        $(ev.target).removeClass('keypress');
        SHIFT=false;
    }else{
        $('.keyboard span').not('.shift').each(function(idx,el){
            $(el).text($(el).text().toUpperCase());
        })
        $(ev.target).addClass('keypress');
        SHIFT=true;
    }

}

function outlineKey(el){
    $(el).addClass('keypress');
    setTimeout(function(){
        $(el).removeClass('keypress')
    },500);
}
function backspace(ev){
    ev.preventDefault();
    outlineKey(ev.target);
    var text=$('.entry').eq(0).text();
    $('.entry').text(text.substr(0,text.length-2)+'|');
}

//mouse keyboard
$('#mousekb span').not('.spacebar,.shift,.backspace').bind('mouseenter',touchStart);
$('#mousekb span').not('.spacebar,.shift,.backspace').bind('mouseout',touchEnd)
$('#mousekb span').not('.shift,.backspace').bind('mouseup',keyrelease)
$('#mousekb .shift').bind('mouseup',shiftKey);
$('#mousekb .backspace').bind('mouseup',backspace);

//touch keyboard:
$('#touchkb span').not('.spacebar,.shift,.backspace').bind('touchstart',touchStart);
$('#touchkb span').not('.spacebar,.shift,.backspace').bind('touchend',touchEnd);
$('#touchkb span').not('.shift,.backspace').bind('touchend',keyrelease)
$('#touchkb .shift').bind('touchend',shiftKey);
$('#touchkb .backspace').bind('touchend',backspace);

</script>
</body> 

更新 好的,我找到了它,并将其称为document.getElementFromPoint(). Mozilla的网站上有一些文档(https://developer.mozilla.org/En/DOM/Document.elementFromPoint).它将获得给定顶部和左侧坐标的元素.可以轻松地使用它来跟踪手指当前在哪个键上.我已经更新了代码示例以使用此功能.以下是一些更新的功能,它们可以获取当前的触摸元素并更新悬停键":

UPDATE Ok, I found it, and 'it' is called document.getElementFromPoint(). There is some documentation on Mozilla's site (https://developer.mozilla.org/En/DOM/Document.elementFromPoint). It'll get the element given the top and left coordinates. This can be easily used to track which key the finger is currently over. I've updated my code example to use this awesome function. Here are some updated functions that get the current touch element and update the 'hover key':

//functions for touchmove implementation:
function getElAtTouchPosition(ev){
    var touch = ev.originalEvent.touches[0] || ev.originalEvent.changedTouches[0] || ev.touches[0];
    var top = touch.pageY;
    var left = touch.pageX;
    var el=document.elementFromPoint(left,top);
    if(el.className=='key'){
        return el;
    }else{
        return null;
    }
}

function move(ev){
    ev.stopImmediatePropagation();
    var el=getElAtTouchPosition(ev);
    if(el.className=='key' && el!=currentHoverKey){
        updateFloatKey(el);
        currentHoverKey=el;
    }
}
function updateFloatKey(el){
    var o=$(el).offset();
    $(currentHoverKey).removeClass('touchStart');
    $('#floatKey').html($(el).html())
        .show()
        .offset({top:(o.top-$('#floatKey').outerHeight()), left:(o.left-5)});
    $(el).addClass('touchStart');
}

function touchStart2(ev){
    ev.preventDefault();
    updateFloatKey(ev.target);
    currentHoverKey=ev.target;
}

function touchStop2(ev){
    $(currentHoverKey).removeClass('touchStart');
    $('#floatKey').hide();
}

查看示例,以了解如何使用所有这些.我已经在iPad 2(iOS 4.3)上对此进行了测试,并且可以正常工作.它仍然需要进行一些调整以提高平滑度,并解决触摸移动最终出现在非关键元素上的情况.我很想看看这在Android上如何运作.我还没有完成第三个键盘的文本输入代码,但是您可以结合以前的一些代码来使其工作.祝你好运.

Check out the example to see how all of this is used. I have tested this on iPad 2 (iOS 4.3), and it works. It still needs some tweaking to improve smoothness and account for cases when the touchmove ends up on a non-key element. I'd be interested to see how this works on Android. I haven't completed the text entry code for the third keyboard, but you can combine some of my previous code to make it work. Good luck.

注意:阻止touchmove事件传播/使DOM树冒泡是非常重要的.如果它确实传播了,那么它将变成一个滚动,并且在iOS设备上滚动期间, DOM操作被禁用,因此您将无法更新悬停键".当非关键元素触发touchmove事件时,您需要考虑所有边缘情况.

Note: It is extremely important to block touchmove event propagation/bubbling up the DOM tree. If it does propagate, then it will turn into a scroll, and during scrolling on iOS devices DOM manipulation is disabled, so you won't be able to update the 'hover key'. You need to account for all edge cases when the touchmove event fires over a non-key element.

这篇关于iOS/Android浏览器:在touchmove上显示按钮的放大预览的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆