2011-05-18 288 views
0

我試圖創建類似於iPhone鍵盤的行爲(請參閱包含的圖像)。如在用戶啓動並移動觸摸時,她看到被觸摸的元素的縮放版本,並且在觸摸時選擇會發生。我正在使用Zepto。iOS/Android瀏覽器:顯示touchmove上的縮放按鈕預覽

我可以正確地獲取觸摸座標,但無法找到手指下的對象。我使用下面的代碼來檢查哪個元素作爲事件的目標返回。

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

這總是返回starttouch上的事件。

Apple documentation觸摸應有 event.touches event.changedTouches event.targetTouches

我已經試過檢查每一個對象的第一要素,但他們似乎都包含只是starttouch-元素作爲目標。有什麼我在這裏失蹤?

我得到的座標爲觸摸正確地從

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

如果一切都失敗了,我開始覺得也許有辦法找到座標的觸摸下的DOM元素。

任何想法表示讚賞。

Behavior similar to iPhone keyboard

回答

3

即觸摸事件下的目的是通過event.target給出。此外,您應該綁定到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> 

UPDATE 好吧,我發現了它,並且 '它' 被稱爲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)上測試過了,它可以工作。它仍然需要進行一些調整以提高平滑度並解決touchmove結束於非關鍵元素時的情況。我很想看看它如何在Android上運行。我還沒有完成第三個鍵盤的文本輸入代碼,但您可以結合我以前的一些代碼來使其工作。祝你好運。

注:這是極其重要阻止touchmove事件傳播/冒泡DOM樹。如果它傳播,那麼它將變成滾動​​,並且在iOS設備上滾動時DOM操作被禁用,因此您將無法更新'懸停鍵'。當touchmove事件觸發非關鍵元素時,您需要考慮所有邊緣情況。

+0

「它」(document.getElementFromPoint())正是我沒有找到:)。我希望會有這樣的功能,但無法在任何地方找到它。 – Marcus 2011-05-26 07:08:55

+0

@Marcus,我非常希望看到你最終實現這種類型的鍵盤。如果您的網站是公開的,請發佈鏈接!謝謝。 – ampersand 2011-05-30 06:13:13

+0

它可能需要一段時間纔會公開,但當它發生時,我會嘗試在此處發佈鏈接。感謝您發現document.getElementFromPoint和這個很好的例子。我很確定這些用於移動/觸摸的界面將在未來變得更加流行。 – Marcus 2011-05-30 12:15:17