javascript - iOS/Android浏览器: showing a zoomed preview of button on touchmove

标签 javascript mobile mobile-website touchscreen zepto

我正在尝试创建类似于 iPhone 键盘的行为(请参阅包含的图像)。例如,当用户开始并移动触摸时,她会看到所触摸元素的缩放版本,并且在触摸时会发生选择。我正在使用 Zepto。

我可以正确获取触摸坐标,但无法找到手指下方的物体。我使用下面的代码来检查哪个元素作为事件的目标返回。

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

这始终返回 starttouch 上的事件。

关于Apple documentation触摸应该有 事件.touches 事件.changedTouches event.targetTouches

我尝试检查每个对象上的第一个元素,但它们似乎都只包含 starttouch-element 作为目标。我在这里缺少什么吗?

我正确地获取了触摸的坐标

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

如果一切都失败了,我开始思考也许有一种方法可以通过坐标找到触摸下的 DOM 元素。

任何想法都会受到赞赏。

Behavior similar to iPhone keyboard

最佳答案

触摸事件下的对象由event.target给出。另外,您应该绑定(bind)到 touchstarttouchend 事件。请参阅我制作的这个示例:

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)。它将获取给定顶部和左侧坐标的元素。这可以很容易地用来跟踪手指当前位于哪个键上。我已经更新了我的代码示例以使用这个很棒的函数。以下是一些更新的函数,用于获取当前触摸元素并更新“悬停键”:

//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();
}

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

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

关于javascript - iOS/Android浏览器: showing a zoomed preview of button on touchmove,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6045817/

相关文章:

javascript - 解析javascript中制表符分隔的文件

html - 如何在我的网站上制作精美的 Angular 落

用于移动集成的 Jquery 菜单 - 从移动分辨率移动到桌面无法正常工作

android - 使用手机的唯一设备标识号而不是帐户

javascript - 您可以使用 JavaScript 从 Opera Mini 中的 5 向方向按钮捕获事件吗?

iphone - 具有宽 iframe 的网页在具有视口(viewport)的 iPhone 上不可滚动

javascript - 选择菜单不改变.css

javascript - 用键盘(没有鼠标)完全控制网站?

javascript - Vanilla JavaScript 向元素添加类

css - 如何仅为特定视口(viewport)删除类或激活类