ฉันจะจำลองโฮเวอร์ด้วยเบราว์เซอร์ที่เปิดใช้งาน Touch in Touch ได้อย่างไร


120

ด้วย HTML บางอย่างเช่นนี้:

<p>Some Text</p>

จากนั้น CSS บางส่วนเช่นนี้:

p {
  color:black;
}

p:hover {
  color:red;
}

ฉันจะอนุญาตให้อุปกรณ์ที่เปิดใช้งานระบบสัมผัสเป็นเวลานานเพื่อจำลองโฮเวอร์ซ้ำได้อย่างไร ฉันสามารถเปลี่ยนมาร์กอัป / ใช้ JS ฯลฯ ได้ แต่คิดวิธีง่ายๆในการทำเช่นนี้ไม่ได้


ฉันคิดถึง iPhone OS โดยเฉพาะ - มันเป็นตัวอย่างของแอนิเมชั่น CSS ซึ่งสำหรับหลาย ๆ คนมันง่ายที่จะใช้โฮเวอร์แทนที่จะคลิกเพื่อเริ่ม
Rich Bradshaw

คำตอบ:


172

ตกลงฉันได้ผลแล้ว! มันเกี่ยวข้องกับการเปลี่ยน CSS เล็กน้อยและเพิ่ม JS บางส่วน

ใช้ jQuery เพื่อให้ง่าย:

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

ในภาษาอังกฤษ: เมื่อคุณเริ่มหรือสิ้นสุดการสัมผัสให้เปิดhover_effectหรือปิดชั้นเรียน

จากนั้นใน HTML ของคุณให้เพิ่มโฮเวอร์ชั้นเรียนลงในสิ่งที่คุณต้องการให้ใช้งานได้ ใน CSS ของคุณให้แทนที่อินสแตนซ์ของ:

element:hover {
    rule:properties;
}

กับ

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

และเพื่อประโยชน์เพิ่มเติมให้เพิ่มสิ่งนี้ใน CSS ของคุณด้วย:

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

หากต้องการหยุดเบราว์เซอร์ขอให้คุณคัดลอก / บันทึก / เลือกรูปภาพหรืออะไรก็ตาม

ง่าย!


นี่มันเยี่ยมมาก ฉันแยกฟังก์ชั่น domready ออกเพราะtoggleจะทำให้เกิดความสับสนหากผู้ใช้แตะองค์ประกอบหนึ่งและลากไปยังอีกองค์ประกอบหนึ่ง (เช่นหากพวกเขาแตะรายการที่ไม่ถูกต้องและพยายามยกเลิกการสัมผัส)
Jacksonkr

ฉันลบออกtouchendและpreventDefault()ในเว็บไซต์ของฉันและมันใช้งานได้ดี แต่ตอนนี้เมนูไม่ได้ปิดโดยอัตโนมัติเมื่อแตะออกจากเป้าหมาย
ДаниилПронин

ฉันต้องการคำแนะนำเกี่ยวกับวิธีปิดเมนูดังกล่าวเมื่อผู้ใช้แตะที่อื่นหรือเริ่มเลื่อน ฉันเดาว่าอาจมีtouchstartผู้ฟังคนอื่นอยู่ในร่างกาย (หรือคล้ายกัน) แต่ฉันสงสัยว่ามีวิธีที่ดีกว่านี้หรือไม่ ขอบคุณ!
Darryl Young

2
มีการละเว้นท่าทางการเลื่อนหรือไม่? นี่เป็นสิ่งที่ฉันต้องการ แต่ตอนนี้ฉันไม่สามารถเลื่อนขึ้นและลงเนื้อหาที่มีเอฟเฟกต์นี้ได้
alsobubbly

1
ฉันลบ PreventDefault ออกเนื่องจากฉันต้องการให้การเลื่อนพร้อมใช้งาน แต่ขอขอบคุณสำหรับคำแนะนำในการเริ่มต้นระบบสัมผัสและการสัมผัส! พระเจ้าส่งนี่เป็นคำตอบเดียวที่ใช้งานได้อย่างน่าเชื่อถือในทุกเบราว์เซอร์
Petraeus

54

สิ่งที่คุณต้องทำคือผูกการเริ่มต้นระบบสัมผัสกับผู้ปกครอง สิ่งนี้จะได้ผล:

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

คุณไม่จำเป็นต้องทำอะไรในฟังก์ชันปล่อยให้ว่างไว้ สิ่งนี้จะเพียงพอสำหรับการวางเมาส์เหนือการสัมผัสดังนั้นการสัมผัสจึงมีลักษณะเหมือน: วางเมาส์เหนือและไม่ชอบ: ใช้งานอยู่ ความมหัศจรรย์ของ iOS


2
โซลูชันนี้อนุญาตให้ลิงก์ดำเนินการในการแตะครั้งที่สองหรือไม่
samuelkobe

1
ไม่ได้ทำให้เกิดการคลิกเมื่อสัมผัสแรกยังคงอยู่ ฉันเพิ่งทดสอบมัน
แจ็ค

ทางออกที่ยอดเยี่ยม! ง่ายและรวดเร็ว
Hunter Turner

41

ลองสิ่งนี้:

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

และใน CSS ของคุณ:

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*/
}

ด้วยรหัสนี้คุณไม่จำเป็นต้องมีคลาสพิเศษใด ๆ !


1
สิ่งนี้ใช้ได้กับฉัน .. สิ่งอื่น ๆ ที่อาจช่วยได้มากกว่านี้คือแทนที่จะเพิ่ม javascript ให้ทำดังนี้ <body ontouchstart = ""> จากนั้นเพิ่มตัวจับเวลาขนาดเล็กใน css: active event: tr: active {background-color : # 118aab; การเปลี่ยนแปลง: .2s เชิงเส้นทั้งหมด; -webkit-tap-highlight-color: rgba (0,0,0,0); -webkit-user-select: ไม่มี; -webkit-touch-callout: none}
Kozy

ทำงานให้ฉัน ขอบคุณ ... สิ่งเดียว - มันล่าช้าไปหน่อย ... ฉันหมายถึง - หลังจากที่คุณกดแล้วมันจะไม่โหลดทันที
Roman Losev

ใช้ fastclick.js เพื่อลบความล่าช้า
Anselm

25

เพื่อตอบคำถามหลักของคุณ: “ ฉันจะจำลองการวางเมาส์ด้วยเบราว์เซอร์ที่เปิดใช้งาน Touch in Touch ได้อย่างไร”

เพียงแค่อนุญาตให้ 'คลิก' องค์ประกอบ (โดยการแตะที่หน้าจอ) จากนั้นทริกเกอร์hoverเหตุการณ์โดยใช้ JavaScript

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

สิ่งนี้ควรใช้งานได้ตราบเท่าที่มีhoverเหตุการณ์บนอุปกรณ์ของคุณ (แม้ว่าโดยปกติจะไม่ได้ใช้ก็ตาม)

อัปเดต:ฉันเพิ่งทดสอบเทคนิคนี้บน iPhone และดูเหมือนว่าจะใช้งานได้ดี ลองใช้งานได้ที่นี่: http://jsfiddle.net/mathias/YS7ft/show/light/

หากคุณต้องการใช้ 'สัมผัสยาว' เพื่อทริกเกอร์โฮเวอร์แทนคุณสามารถใช้ข้อมูลโค้ดด้านบนเป็นจุดเริ่มต้นและสนุกไปกับตัวจับเวลาและสิ่งต่างๆ;)


ฉันไม่รู้เกี่ยวกับเรื่องนั้น onhover.call (p) บิตมันค่อนข้างดี ไม่มีการเลื่อนลอยออกไป ...
Rich Bradshaw

คุณได้ทดสอบสิ่งนี้กับหลายองค์ประกอบและสัมผัสที่ยาวนานหรือไม่? หมายความว่าผู้ใช้เลื่อนนิ้วไปรอบ ๆ หน้าจอและแสดงลักษณะการวางเมาส์สำหรับแต่ละองค์ประกอบหรือไม่
Marcus

ดูเหมือนว่าถ้าคุณใช้ jQuery อยู่แล้วคุณอาจสามารถเรียกใช้งานโฮเวอร์ได้ด้วย jQuery เช่น jQuery.hover (); ไม่แน่ใจว่า api รองรับสิ่งนั้นแม้ว่า
Kzqai

อ๊ะนั่นเป็นความคิดเห็นที่เกี่ยวข้องกับโพสต์ด้านบนที่ใช้ jQuery จริงๆขออภัย
Kzqai

คุณจำเป็นต้องมีสคริปต์พิเศษหรือเรียกใช้ฟังก์ชันนี้หรือไม่? มันใช้ได้กับฉัน แต่มีเพียงหน้าเดียวและฉันไม่รู้ว่าความแตกต่างคืออะไร
Richard Young

13

โซลูชันที่ปรับปรุงเพิ่มเติม

ก่อนอื่นฉันใช้แนวทางของ Rich Bradshawแต่แล้วปัญหาก็เริ่มปรากฏขึ้น ด้วยการทำe.preventDefault ()ในเหตุการณ์'touchstart'หน้าจะไม่เลื่อนอีกต่อไปและการกดแบบยาวจะไม่สามารถเปิดเมนูตัวเลือกหรือดับเบิลคลิกซูมก็ไม่สามารถดำเนินการให้เสร็จสิ้นได้

วิธีการแก้ปัญหาอาจจะค้นหาออกที่เหตุการณ์จะถูกเรียกและเพียงe.preventDefault ()ในภายหลังหนึ่ง'touchend' เนื่องจาก'touchmove'ของ scroll มาก่อน'touchend'มันจะยังคงอยู่ตามค่าเริ่มต้นและ'click'ก็จะถูกป้องกันเช่นกันเนื่องจากมันมาจากคำตามหลังในห่วงโซ่เหตุการณ์ที่ใช้กับมือถือดังนี้:

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

แต่เมื่อเมนูตัวเลือกปรากฏขึ้นมันจะไม่ยิง'การสัมผัส' ที่รับผิดชอบในการสลับชั้นเรียนอีกต่อไปและในครั้งต่อไปพฤติกรรมการวางเมาส์จะเป็นไปในทางอื่นโดยสิ้นเชิง

จากนั้นวิธีแก้ปัญหาจะเป็นอีกครั้งโดยมีเงื่อนไขว่าเราอยู่ในเหตุการณ์ใดหรือเพียงแค่ทำสิ่งที่แยกจากกันและใช้addClass ()และremoveClass ()ตามลำดับใน'touchstart'และ'touchend'เพื่อให้แน่ใจว่ามันเริ่มต้นและสิ้นสุดโดยเสมอ ตามลำดับการเพิ่มและลบแทนที่จะตัดสินใจตามเงื่อนไข ในการดำเนินการให้เสร็จสิ้นเราจะผูกการเรียกกลับการลบเข้ากับประเภทเหตุการณ์'โฟกัสเอาต์'โดยยังคงรับผิดชอบในการล้างคลาสโฮเวอร์ของลิงก์ใด ๆ ที่อาจยังคงอยู่และไม่กลับมาเยี่ยมชมอีกเช่น:

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

ข้อควรระวัง:ข้อบกพร่องบางอย่างยังคงเกิดขึ้นในสองโซลูชันก่อนหน้านี้และคิดว่า (ยังไม่ได้ทดสอบ) การซูมดับเบิลคลิกก็ยังล้มเหลวเช่นกัน

เป็นระเบียบเรียบร้อยและหวังว่าจะไม่มีข้อผิดพลาด (ไม่ใช่ :)) โซลูชัน Javascript

ตอนนี้เป็นเวลาวินาทีที่สะอาดกว่าเป็นระเบียบและตอบสนองเพียงแค่ใช้จาวาสคริปต์ (ไม่มีการผสมผสานระหว่าง. hover class และ pseudo: hover) และจากที่ที่คุณสามารถเรียกพฤติกรรม ajax ของคุณได้โดยตรงบนเหตุการณ์'click'สากล (มือถือและเดสก์ท็อป) ฉันพบคำถามที่ตอบได้ค่อนข้างดีซึ่งในที่สุดฉันก็เข้าใจว่าฉันสามารถผสมผสานเหตุการณ์การสัมผัสและเมาส์เข้าด้วยกันได้อย่างไรโดยไม่มีการเรียกกลับหลายเหตุการณ์อย่างหลีกเลี่ยงไม่ได้ที่จะเปลี่ยนเหตุการณ์ของกันและกันในห่วงโซ่เหตุการณ์ วิธีการมีดังนี้

$('.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

hoverไม่สามารถใช้เอฟเฟกต์เมาส์ในอุปกรณ์สัมผัสได้ เมื่อฉันปรากฏตัวด้วยสถานการณ์เดียวกันในsafari iosฉันใช้:activecss เพื่อสร้างเอฟเฟกต์

กล่าวคือ

p:active {
  color:red;
}

ในกรณีของฉันมันใช้งานได้อาจเป็นกรณีนี้ที่สามารถใช้งานได้โดยไม่ต้องใช้จาวาสคริปต์ ลองดูสิ


2

เพิ่มรหัสนี้จากนั้นตั้งค่าคลาส "tapHover" ให้กับองค์ประกอบที่คุณต้องการทำงานในลักษณะนี้ ครั้งแรกที่คุณแตะองค์ประกอบจะได้รับ pseudoclass ": hover" และ class "tapped" เหตุการณ์การคลิกจะถูกป้องกัน ครั้งที่สองที่คุณแตะองค์ประกอบเดียวกันเหตุการณ์การคลิกจะเริ่มทำงาน

// 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

หากไม่มีอุปกรณ์ (หรือมากกว่าเบราว์เซอร์) เฉพาะ JS ฉันค่อนข้างมั่นใจว่าคุณโชคไม่ดี

แก้ไข: คิดว่าคุณต้องการหลีกเลี่ยงสิ่งนั้นจนกว่าฉันจะอ่านคำถามของคุณซ้ำ ในกรณีของ Mobile Safari คุณสามารถลงทะเบียนเพื่อรับกิจกรรมสัมผัสทั้งหมดที่คล้ายกับสิ่งที่คุณทำได้กับ UIView-s ดั้งเดิม ไม่พบเอกสารในขณะนี้จะพยายามทำ


1

วิธีหนึ่งที่ทำได้คือทำเอฟเฟกต์โฮเวอร์เมื่อการสัมผัสเริ่มต้นจากนั้นจึงลบเอฟเฟกต์โฮเวอร์เมื่อการสัมผัสเคลื่อนที่หรือสิ้นสุด

นี่คือสิ่งที่ Apple พูดเกี่ยวกับการจัดการระบบสัมผัสโดยทั่วไปเนื่องจากคุณพูดถึง iPhone


ตอนนี้เนื้อหาลิงก์ยังเกี่ยวข้องอยู่ไหม
Flavien Volken

1

รสนิยมส่วนตัวของฉันคือการกำหนด:hoverสไตล์ให้เข้ากับ:focusรัฐเช่นกัน:

p {
    color: red;
}

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

จากนั้นใช้ HTML ต่อไปนี้:

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

และ 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

แก้ไขแล้ว 2019 - วางเมาส์บน Touch

ตอนนี้ดูเหมือนว่าดีที่สุดที่จะหลีกเลี่ยงการใช้โฮเวอร์ร่วมกับ ios หรือสัมผัสโดยทั่วไป โค้ดด้านล่างนี้ใช้ css ของคุณตราบเท่าที่ยังคงสัมผัสและไม่มี ios flyouts อื่น ๆ ทำเช่นนี้;

  1. เพิ่ม Jquery: $ ("p"). on ("touchstart", function (e) {$ (this) .focus (); e.preventDefault ();});

  2. CSS: แทนที่ p: hover ด้วย p: focus และเพิ่ม p: active

ตัวเลือก;

  • แทนที่ jquery p selector ด้วยคลาสใดก็ได้เป็นต้น

  • เพื่อให้เอฟเฟกต์ยังคงอยู่ให้วาง p: hover ไว้ด้วยและเพิ่ม body {cursor: ponter;} ดังนั้นแตะที่ใดก็ได้สิ้นสุด

  • ลองคลิกและวางเมาส์โอเวอร์เหตุการณ์รวมทั้งทัชสตาร์ตในรหัสเดียวกัน (แต่ไม่ได้ทดสอบ)

  • ลบ e.preventDefault (); เพื่อให้ผู้ใช้สามารถใช้ ios flyouts เช่น copy

หมายเหตุ

  • ทดสอบเฉพาะสำหรับองค์ประกอบข้อความ ios อาจถือว่าอินพุตและอื่น ๆ แตกต่างกัน

  • ทดสอบเฉพาะบน iphone XR ios 12.1.12 และ ipad 3 ios 9.3.5 โดยใช้ Safari หรือ Chrome


0

การผสมผสานระหว่าง Javascript ดั้งเดิมและ jQuery:

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
ขออภัยที่ต้องอวดรู้ แต่ jquery เป็น javacript
matpol

2
@matpol: jQuery เป็น javascript แต่ javascript ไม่ใช่ jQuery พิเศษสำหรับคุณฉันเพิ่มคำว่า 'บริสุทธิ์' จาวาสคริปต์บริสุทธิ์ พอใจครับ?
Codebeat

คุณไม่สามารถใช้ jquery โดยไม่ใช้จาวาสคริปต์ 'บริสุทธิ์' ฉันแค่ทำให้ประเด็นเพราะบางคนที่มักจะไม่ทราบเรื่องนี้
matpol

5
การผสมผสานระหว่าง Javascript ดั้งเดิมและ jQuery พอใจหรือไม่
Codebeat

0

ทางออกที่ง่ายที่สุดที่ฉันพบ: ฉันมีแท็ก <span> ที่มี: hover css rules อยู่ในนั้น ฉันเปลี่ยนเป็น <a href = "javascript: void (0)"> และvoilà รูปแบบโฮเวอร์ใน iOS เริ่มทำงาน


0

การใช้งานสามารถใช้ CSS ได้เช่นกันเพิ่มโฟกัสและแอ็คทีฟ (สำหรับ IE7 และต่ำกว่า) ไปยังลิงก์ที่ซ่อนอยู่ ตัวอย่างเมนู ul ภายใน div พร้อมเมนูคลาส:

.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;}

มันสายและยังไม่ทดสอบควรใช้งานได้ ;-)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.