仅使用CSS能否检测用户未离开触摸屏的持续触摸状态?
示例代码
CSS 代码
:root { font-family: Avenir, Helvetica, Arial, sans-serif; --form: 300px; --half: 150px; --size: 60px; --pad: 8px; --top: calc((var(--half) - var(--size)) / 2 - var(--pad)); --left: calc((var(--form) - var(--size)) / 2 - var(--pad)); --end: 10px; --gap: 4px; --line: 1px; --white: #fff; --light: #ddd; --dark: #222; --btn: #060; --bg: #030; --red: #f33; --lava: #600; --deep: #300; --brdr: #fff6; /* button-color-agnostic border color */ --time: 10s; } /* Place main in the center */ body { margin: 0; padding: 0; min-height: 100vh; display: flex; justify-content: center; align-items: center; color: var(--light); background-color: var(--dark); } /* Style both the Start and Play Again buttons */ button, .button { border: var(--line) outset var(--brdr); border-radius: var(--pad); padding: var(--pad); cursor: pointer; background-color: var(--btn); } button { --bg: var(--deep); background-color: transparent; color: inherit; } button:hover, .button:hover { color: var(--white); } button:hover:active, .button:hover:active { border-style: inset; background-color: var(--bg); } /* Make form the default size for an iframe */ form { position: relative; width: var(--form); height: var(--half); border: var(--line) solid var(--white); border-radius: var(--pad); box-sizing: border-box; overflow: hidden; } /* Take the checkbox out of the flow of the page * and show it in front of the .lava younger sibling * so that it will be a safe place for the mouse. */ input { position: absolute; z-index: 2; } /* Fill the form element with .lava */ .lava { position: absolute; width: 100%; height: 100%; background: var(--bg); /* <<<< No eruption yet */ /* Style the "You Lost" span and the link... */ display: flex; flex-direction: column; justify-content: center; align-items: center; p { font-size: var(--size); margin: 0; color: var(--red); } /* ... but hide them and make them inactive */ * { opacity: 0; pointer-events: none; } } /* Place a round Start button in the center with an invisible * .blocker in front of it. Move them both in front of the lava. */ .blocker, .start { position: absolute; z-index: 1; top: var(--top); left: var(--left); width: var(--size); height: var(--size); line-height: var(--size); border-radius: var(--size); text-align: center; } .start::after { content: "Start"; } /* Make the .blocker invisible and inactive at the start */ .blocker { opacity: 0; pointer-events: none; } /* When the game starts, shrink both the .start button * and the .blocker, and move them together towards * the input element in the top left corner. */ label:has(:checked) { .start, & ~ .blocker { top: var(--gap); left: var(--gap); width: var(--end); height: var(--end); padding: 0px; font-size: 0px; line-height: var(--end); transition: all var(--time); } } input:checked ~ .start::after { content: "Panic!"; } /* When the game starts, make the .lava active */ label:has(input:checked) { & ~ .lava { background-color: var(--lava); &:hover { z-index:2; * { opacity: 1; pointer-events: all; } } } /* Prevent .start button from toggling the input */ & ~ .blocker { pointer-events: all; } } /* Show the GitHub logo */ a.github { width: 0; height: 0; img { position: absolute; right: 3px; bottom: 3px; width: 32px; height: 32px; filter: grayscale(1); opacity: 0.25; &:hover { opacity: 1; } } }
HTML 代码
<form> <label> <input type="checkbox"> <span class="start button"></span> </label> <span class="blocker button"></span> <div class="lava"> <p>You Lost!</p> <button type="reset">Play again</button> </div> <a class="github" href="https://github.com/MERNCraft/lava"> <img src="github.svg" alt="github"> </a> </form>
问题背景
用JavaScript可以检测touch事件的结束,但在CSS里,用户触摸屏幕时,浏览器会为被触摸元素及其所有父元素添加:hover伪类(至少作用于<html>元素),而且在Android版Chrome中,即使用户停止触摸,这些元素上的:hover伪类也会保留。
浏览器还会生成:active伪类,用户停止触摸时这个伪类会消失;鼠标用户松开按键时,:active同样会消失,哪怕鼠标还停在元素上处于hover状态。
我正在做一款迷宫游戏,要求玩家沿路径移动且不能越线。用鼠标时可以通过检测持续hover路径来判断,但触摸屏用户只要抬起手指再点击终点就能完成游戏,这不符合规则。
问题
仅使用CSS能否检测玩家的手指从起点到终点全程未离开屏幕?
回答
仅靠纯CSS无法实现这种检测。
原因如下:
- CSS的
:hover伪类在触摸后会持续保留,无法区分用户是一直触摸还是已经抬起手指; :active伪类仅在触摸按压期间生效,但一旦手指滑动到其他元素上,原元素的:active会消失,无法追踪整个触摸路径的连续性;- CSS没有原生机制追踪触摸事件的完整生命周期(从按下到持续滑动再到抬起的全程状态),也无法判断触摸点是否始终保持在指定路径范围内。
要实现这种需求,必须结合JavaScript监听touchstart、touchmove、touchend等事件,实时追踪触摸位置是否始终在合法路径上,一旦触摸离开路径或抬起手指,就判定游戏失败。
内容的提问来源于stack exchange,提问作者James Newton
相关产品推荐
相关产品推荐

