Skip to content Skip to sidebar Skip to footer

Ios/android Browser: Showing A Zoomed Preview Of Button On Touchmove

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, an

Solution 1:

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

Source code:

<html><head><scriptsrc="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: -5px0px5px#ccc;
    -webkit-box-shadow: -5px0px5px#ccc;
    box-shadow: -5px0px5px#ccc;
}

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

</style></head><body><h3>iOS-style keyboard examples</h3><divclass="entry">|</div><divclass="wrapper"><div>With mouse events:</div><divclass="keyboard"id="mousekb"><divclass="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><divclass="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><divclass="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><divclass="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><divclass="row"><spanclass="shift">shift</span><spanclass="spacebar">&nbsp;</span><spanclass="backspace">&lArr;</span></div></div></div><divclass="entry">|</div><divclass="wrapper"><div>With touch events (zoom in for better view):</div><divclass="keyboard"id="touchkb"><divclass="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><divclass="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><divclass="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><divclass="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><divclass="row"><spanclass="shift">shift</span><spanclass="spacebar">&nbsp;</span><spanclass="backspace">&lArr;</span></div></div></div><divid="floatKey"class="key"style="display:none"></div><script>SHIFT=false;
$('.keyboard span').addClass('key');


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

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

functionkeyrelease(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()+'|');
}

functionshiftKey(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;
    }

}

functionoutlineKey(el){
    $(el).addClass('keypress');
    setTimeout(function(){
        $(el).removeClass('keypress')
    },500);
}
functionbackspace(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 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:functiongetElAtTouchPosition(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{
        returnnull;
    }
}

functionmove(ev){
    ev.stopImmediatePropagation();
    var el=getElAtTouchPosition(ev);
    if(el.className=='key' && el!=currentHoverKey){
        updateFloatKey(el);
        currentHoverKey=el;
    }
}
functionupdateFloatKey(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');
}

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

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

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.

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.

Post a Comment for "Ios/android Browser: Showing A Zoomed Preview Of Button On Touchmove"