Dokunmatik özellikli tarayıcılarda fareyle üzerine gelme simülasyonunu nasıl yaparım?


120

Bunun gibi bazı HTML ile:

<p>Some Text</p>

Sonra bunun gibi bazı CSS'ler:

p {
  color:black;
}

p:hover {
  color:red;
}

Dokunma özellikli bir cihaza uzun bir dokunuşun fareyle üzerine gelmeyi çoğaltmasına nasıl izin verebilirim? İşaretlemeyi değiştirebilir / JS vb. Kullanabilirim, ancak bunu yapmanın kolay bir yolunu düşünemiyorum.


Özellikle iPhone işletim sistemini düşünüyorum - bu, başlatmak için tıklama yerine fareyle üzerine gelmenin kullanımının kolay olduğu bir CSS animasyon demosu.
Rich Bradshaw

Yanıtlar:


172

Tamam, hallettim! CSS'yi biraz değiştirmeyi ve biraz JS eklemeyi içerir.

Kolaylaştırmak için jQuery'yi kullanma:

$(document).ready(function() {
    $('.hover').on('touchstart touchend', function(e) {
        e.preventDefault();
        $(this).toggleClass('hover_effect');
    });
});

İngilizce: Bir dokunuşu başlattığınızda veya bitirdiğinizde, sınıfı açın hover_effectveya kapatın.

Ardından, HTML'nizde, bunun birlikte çalışmasını istediğiniz her şeye bir sınıf fareyle üzerine gelin. CSS'nizde aşağıdakilerin herhangi bir örneğini değiştirin:

element:hover {
    rule:properties;
}

ile

element:hover, element.hover_effect {
    rule:properties;
}

Ve sadece daha fazla fayda sağlamak için bunu CSS'nize de ekleyin:

.hover {
-webkit-user-select: none;
-webkit-touch-callout: none;        
}

Tarayıcının sizden görüntüyü kopyalamanızı / kaydetmenizi / seçmenizi istemesini durdurmak için.

Kolay!


Bu harika. Yine de domready işlevini böldüm çünkü togglekullanıcı bir öğeye dokunursa ve başka bir öğeye sürüklerse (örneğin, yanlış öğeye dokunursa ve dokunmayı iptal etmeye
çalışırsa

Kaldırdım touchendve preventDefault()web sitemde iyi çalışıyor ama şimdi menüler hedef dışı dokunarak otomatik olarak kapanmıyor.
Даниил Пронин

Ayrıca, kullanıcı başka bir yere dokunduğunda veya kaydırmaya başladığında böyle bir menünün nasıl kapatılacağı konusunda da biraz tavsiye istiyorum. Sanırım touchstartvücutta başka bir dinleyici (veya benzeri) olabilir ama daha iyi bir yol olup olmadığını merak ettim. Teşekkürler!
Darryl Young

2
Kaydırma hareketini göz ardı etmenin bir yolu var mı? Bu tam olarak ihtiyacım olan şeyi yapıyor ancak şimdi bu etkiye sahip içeriği yukarı ve aşağı kaydıramıyorum.
alsobubbly

1
Kaydırmanın kullanılabilir olmasını istediğimden, preventDefault'u kaldırdım, ancak touchstart ve touchend ile ilgili ipuçları için teşekkürler! Tüm tarayıcılarda güvenilir şekilde çalışan tek yanıt budur.
Petraeus

54

Tek yapmanız gereken touchstart'ı bir ebeveyne bağlamaktır. Bunun gibi bir şey işe yarayacak:

$('body').on('touchstart', function() {});

İşlevde hiçbir şey yapmanıza gerek yok, boş bırakın. Bu, fareyle üzerine gelmek için yeterli olacaktır, bu nedenle bir dokunuş daha çok şu şekilde davranır: fareyle üzerine gelme ve daha az: etkin. iOS büyüsü.


2
Bu çözüm, bağlantının ikinci dokunuşta yürütülmesine izin veriyor mu?
samuelkobe

1
Hayır, ilk dokunuşta tıklamayı tetikler. Daha yeni test ettim.
Jack

Harika çözüm! Çabuk ve kolay.
Hunter Turner

41

Bunu dene:

<script>
document.addEventListener("touchstart", function(){}, true);
</script>

Ve CSS'nizde:

element:hover, element:active {
-webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-user-select: none;
-webkit-touch-callout: none /*only to disable context menu on long press*/
}

Bu kodla fazladan bir .hover sınıfına ihtiyacınız yok!


1
bu benim için çalışıyor .. buna daha fazla yardımcı olabilecek diğer bazı şeyler javascript eklemek yerine, şunu yapın: <body ontouchstart = ""> sonra css: active event: tr: active {background-color'a küçük bir zamanlayıcı ekleyin : # 118aab; geçiş: tümü .2s doğrusal; -webkit-dokunma-vurgulama-rengi: rgba (0,0,0,0); -webkit-user-select: yok; -webkit-touch-callout: yok}
Kozy

Benim için çalıştı. Teşekkürler ... Tek şey - biraz gecikiyor ... Yani - düğmesine bastıktan sonra anında yüklenmiyor.
Roman Losev

Gecikmeyi gidermek için fastclick.js kullanın
Anselm

25

Ana sorunuzu yanıtlamak için: "Dokunmatik özellikli tarayıcılarda fareyle üzerine gelme simülasyonunu nasıl yaparım?"

Öğenin 'tıklanmasına' izin verin (ekrana dokunarak) ve ardından hoveretkinliği JavaScript kullanarak tetikleyin .

var p = document.getElementsByTagName('p')[0];
p.onclick = function() {
 // Trigger the `hover` event on the paragraph
 p.onhover.call(p);
};

Bu hover, cihazınızda bir olay olduğu sürece çalışmalıdır (normalde kullanılmasa bile).

Güncelleme: Bu tekniği iPhone'umda test ettim ve iyi çalışıyor gibi görünüyor. Burada deneyin: http://jsfiddle.net/mathias/YS7ft/show/light/

Bunun yerine fareyle üzerine gelmeyi tetiklemek için 'uzun dokunuş' kullanmak istiyorsanız, yukarıdaki kod parçacığını bir başlangıç ​​noktası olarak kullanabilir ve zamanlayıcılar ve diğer şeylerle eğlenebilirsiniz;)


Onhover.call (p) bit hakkında bir şey bilmiyordum, bu oldukça havalı. Yine de havada gezinme yok ...
Rich Bradshaw

Bunu birden çok öğe ve uzun dokunuşla test ettiniz mi? Kullanıcının parmağını ekranda hareket ettirmesi ve her öğe için bir fareyle üzerine gelme stili göstermesi anlamına mı geliyor?
Marcus

Görünüşe göre zaten jQuery kullanıyorsanız, hover olayını jQuery'nin kendisi ile çağırabilirsiniz, örneğin: jQuery.hover (); API'nin bunu desteklediğinden emin değilim.
Kzqai

Maalesef, bu aslında jQuery kullanan yukarıdaki gönderiye daha uygun bir yorumdu, üzgünüm.
Kzqai

Herhangi bir özel komut dosyasına sahip olmanız veya işlevi aramanız gerekiyor mu? Benim için çalışıyor ama sadece bir sayfada ve farkın ne olduğunu bilmiyorum.
Richard Young

13

Daha Gelişmiş Çözüm

Önce Rich Bradshaw'ın yaklaşımıyla gittim ama sonra sorunlar ortaya çıkmaya başladı. E.preventDefault () 'touchstart' üzerinde yaparak olayı, sayfa artık verilirse ve ne uzun basın seçenekler menüsünü ne de çift tıklama zoom ateş edebiliyor yürütme bitirmek edebiliyor.

Bir çözüm, hangi olayın çağrıldığını bulmak olabilir ve e.preventDefault () sonrakinde , 'touchend' olabilir . Spirallerin yana 'touchmove' önce gelir 'touchEnd' varsayılan olarak olarak kalır ve 'tık' de olay zincirinde afterwords geliyor beri engelledi şöyle mobil uygulanır:

// Binding to the '.static_parent' ensuring dynamic ajaxified content
$('.static_parent').on('touchstart touchend', '.link', function (e) {

    // If event is 'touchend' then...
    if (e.type == 'touchend') {
        // Ensuring we event prevent default in all major browsers
        e.preventDefault ? e.preventDefault() : e.returnValue = false;
    }

    // Add class responsible for :hover effect
    $(this).toggleClass('hover_effect');
});

Ancak daha sonra, seçenekler menüsü göründüğünde, artık sınıfın değiştirilmesinden sorumlu 'touchend'i ateşlemiyor ve bir dahaki sefere gezinme davranışı tam tersi olacak, tamamen karışık olacak.

O zaman bir çözüm, koşullu olarak hangi etkinlikte bulunduğumuzu bulmak veya yalnızca ayrı etkinlikler yapmak ve sırasıyla "touchstart" ve "touchend" için addClass () ve removeClass () 'ı kullanarak her zaman başlayıp bitmesini sağlamak olacaktır. Koşullu olarak karar vermek yerine sırasıyla ekleme ve çıkarma. Bitirmek için, geri çağrının kaldırılmasını 'focusout' olay türüne de bağlayacağız, bu şekilde devam eden ve bir daha asla tekrar ziyaret edilmeyen herhangi bir bağlantının üzerine gelme sınıfını temizlemekten sorumlu olmaya devam edeceğiz :

$('.static_parent').on('touchstart', '.link', function (e) {
    $(this).addClass('hover_effect');
});

$('.static_parent').on('touchend focusout', '.link', function (e) {
    // Think double click zoom still fails here
    e.preventDefault ? e.preventDefault() : e.returnValue = false;
    $(this).removeClass('hover_effect');
});

atention: Önceki iki çözümde bazı hatalar hala ortaya çıkıyor ve ayrıca düşünün (test edilmedi), çift tıklama yakınlaştırma da hala başarısız oluyor.

Düzenli ve Umarım Hatasız (değil :)) Javascript Çözümü

Şimdi , bir saniye için, sadece javascript kullanarak (.hover sınıfı ve pseudo: hover arasında bir karışım yok) ve evrensel (mobil ve masaüstü) 'tıklama' olayında ajax davranışınızı doğrudan çağırabileceğiniz bir yaklaşımla, daha temiz, daha düzenli ve duyarlı bir yaklaşım , Sonunda dokunma ve fare olaylarını çeşitli olay geri aramaları kaçınılmaz olarak olay zincirinde değiştirmeden nasıl karıştırabileceğimi anladığım oldukça iyi yanıtlanmış bir soru buldum . Bunu nasıl yapacağınız aşağıda açıklanmıştır:

$('.static_parent').on('touchstart mouseenter', '.link', function (e) {
    $(this).addClass('hover_effect');
});

$('.static_parent').on('mouseleave touchmove click', '.link', function (e) {
    $(this).removeClass('hover_effect');

    // As it's the chain's last event we only prevent it from making HTTP request
    if (e.type == 'click') {
        e.preventDefault ? e.preventDefault() : e.returnValue = false;

        // Ajax behavior here!
    }
});

3

Fare hoverefekti dokunmatik cihazda uygulanamaz. Aynı durumla göründüğümde css'de etkili olmak için safari ioskullandım :active.

yani.

p:active {
  color:red;
}

Benim durumumda çalışıyor. Javascript kullanmadan kullanılabilecek durum da bu olabilir. Sadece bir dene.


2

Bu kodu ekleyin ve ardından bu şekilde çalışmak istediğiniz öğelere "tapHover" sınıfını ayarlayın. Bir öğeye ilk kez dokunduğunuzda, sözde sınıf ": hover" ve "tıklandı" sınıfı kazanacaktır. Tıklama olayı engellenecektir. Aynı öğeye ikinci kez dokunduğunuzda - tıklama olayı tetiklenecektir.

// Activate only in devices with touch screen
if('ontouchstart' in window)
{
    // this will make touch event add hover pseudoclass
    document.addEventListener('touchstart', function(e) {}, true);

    // modify click event
    document.addEventListener('click', function(e) {
        // get .tapHover element under cursor
        var el = jQuery(e.target).hasClass('tapHover')
            ? jQuery(e.target)
            : jQuery(e.target).closest('.tapHover');

        if(!el.length)
            return;

        // remove tapped class from old ones
        jQuery('.tapHover.tapped').each(function() {
            if(this != el.get(0))
                jQuery(this).removeClass('tapped');
        });

        if(!el.hasClass('tapped'))
        {
            // this is the first tap
            el.addClass('tapped');
            e.preventDefault();
            return false;
        }
        else
        {
            // second tap
            return true;
        }
    }, true);
}
.box {
	float:		left;
	
	display:	inline-block;
	margin:		50px 0 0 50px;
	width:		100px;
	height:		100px;
	overflow:	hidden;
	
	font-size:	20px;
	
	border:		solid 1px black;
}
.box.tapHover {
	background:	yellow;
}
.box.tapped {
	border:		solid 3px red;
}
.box:hover {
	background:	red;
}
<div class="box" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>
<div class="box tapHover" onclick="this.innerHTML = Math.random().toFixed(5)"></div>


1

Cihaza (veya tarayıcıya) özgü JS olmadan, şansınız kalmadığından eminim.

Düzenleme: Sorunuzu tekrar okuyana kadar bundan kaçınmak istediğinizi düşündüm. Mobil Safari durumunda, yerel UIView-lerle yapabileceklerinize benzer tüm dokunma olaylarını almak için kayıt olabilirsiniz. Şu anda belgeleri bulamıyorum, yine de deneyecek.


1

Bunu yapmanın bir yolu, dokunma başladığında fareyle üzerine gelme efektini yapmak, ardından dokunma hareket ettiğinde veya bittiğinde fareyle üzerine gelme efektini kaldırmaktır.

Bu, iPhone'dan bahsettiğinizden beri genel olarak dokunmatik kullanım hakkında Apple'ın söylediği şeydir .


Bağlantı içeriği şimdi hala alakalı mı?
Flavien Volken

1

Benim kişisel zevkim, :hovertarzları :focuseyalete de atfetmek , örneğin:

p {
    color: red;
}

p:hover, p:focus {
    color: blue;
}

Ardından aşağıdaki HTML ile:

<p id="some-p-tag" tabindex="-1">WOOOO</p>

Ve aşağıdaki JavaScript:

$("#some-p-tag").on("touchstart", function(e){
    e.preventDefault();
    var $elem = $(this);

    if($elem.is(":focus")) {
        //this can be registered as a "click" on a mobile device, as it's a double tap
        $elem.blur()
    }
    else {
        $elem.focus();
    }
});

1

Çözüldü 2019 - Dokunulduğunda Üzerine Gel

Şimdi, fareyle üzerine gelme özelliğini genel olarak ios veya touch ile kullanmaktan kaçınmak en iyisidir. Aşağıdaki kod, dokunma sürdürüldüğü sürece ve diğer ios çıkışları olmadan css'nizi uygular. Bunu yap;

  1. Jquery add: $ ("p"). On ("touchstart", function (e) {$ (this) .focus (); e.preventDefault ();});

  2. CSS: p: hover'ı p: focus ile değiştirin ve p: active ekleyin

Seçenekler;

  • jquery p seçiciyi herhangi bir sınıf vb. ile değiştirin

  • efektin kalması için, p: hover tutun ve body {cursor: ponter;} ekleyin, böylece herhangi bir yere dokunmak sona erdirir

  • tıklama ve fareyle üzerine gelme olaylarının yanı sıra dokunmatik başlatmayı aynı kodda deneyin (ancak test edilmemiştir)

  • e.preventDefault () kaldırmak; kullanıcıların ios açılır pencerelerinden yararlanmasını sağlamak için, örneğin kopyalama

notlar

  • yalnızca metin öğeleri için test edilmiştir, ios girişleri vb. farklı şekilde değerlendirebilir

  • Safari veya Chrome kullanılarak yalnızca iphone XR ios 12.1.12 ve ipad 3 ios 9.3.5 üzerinde test edilmiştir.


0

Yerel Javascript ve jQuery'nin bir karışımı:

var gFireEvent = function (oElem,sEvent) 
{
 try {
 if( typeof sEvent == 'string' && o.isDOM( oElem ))
 {
  var b = !!(document.createEvent),
     evt = b?document.createEvent("HTMLEvents"):document.createEventObject();
  if( b )    
  {  evt.initEvent(sEvent, true, true ); 
    return !oElem.dispatchEvent(evt);
  }
  return oElem.fireEvent('on'+sEvent,evt);
 }
 } catch(e) {}
 return false;
};


// Next you can do is (bIsMob etc you have to determine yourself):

   if( <<< bIsMob || bIsTab || bisTouch >>> )
   {
     $(document).on('mousedown', function(e)
     {
       gFireEvent(e.target,'mouseover' );
     }).on('mouseup', function(e)
     {
       gFireEvent(e.target,'mouseout' );
     });
   }

1
bilgiçlik tasladığım için özür dilerim ama jquery javacript
matpol

2
@matpol: jQuery javascript, ancak javascript jQuery değil. Size özel 'saf' kelimesini ekliyorum, saf javascript. Memnun musunuz efendim?
Codebeat

'saf' javascript kullanmadan jquery kullanamazsınız. Ben sadece bunu belirtiyorum çünkü SO'yu sık sık kullanan bazı insanlar bunu bilmiyor gibi görünüyor.
matpol

5
Yerel Javascript ve jQuery'nin bir karışımı, Memnun musunuz?
Codebeat

0

Bulduğum en kolay çözüm: İçlerinde: hover css kurallarına sahip bazı <span> etiketleri vardı. <A href = "javascript: void (0)"> ve voilà için geçiş yaptım. İOS'taki vurgulu stiller çalışmaya başladı.


0

CSS de kullanabilir, gizli bağlantıya odak ve aktif (IE7 ve altı için) ekleyin. Sınıf menüsüne sahip bir div içindeki ul menüsü örneği:

.menu ul ul {display:none; position:absolute; left:100%; top:0; padding:0;}
.menu ul ul ul {display:none; position:absolute; top:0; left:100%;}
.menu ul ul a, .menu ul ul a:focus, .menu ul ul a:active { width:170px; padding:4px 4%; background:#e77776; color:#fff; margin-left:-15px; }
.menu ul li:hover > ul { display:block; }
.menu ul li ul li {margin:0;}

Geç ve denenmemiş, çalışmalı ;-)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.