You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

咨询点击屏幕底部上拖切换屏幕效果的名称及实现方法

鼠标拖拽式页面切换(Mouse-Drag Page Navigation)

Hey there! Let's break this down clearly for you:

What's this interaction called?

This effect is commonly referred to as Mouse-Drag Page Navigation (or sometimes Desktop Swipe Navigation, since it adapts mobile swipe gestures for mouse input). It lets users navigate between full-page sections by clicking, holding, and dragging upward (or other directions) instead of using scrollbars or buttons.

How to implement it

I'll cover two common scenarios: vanilla JavaScript (no frameworks) and Vue 3 (since it's widely used for interactive UIs).

Vanilla JavaScript Implementation

This example assumes you have full-height sections (<section> elements with height: 100vh) for each "screen":

  1. Set up your HTML structure
<div class="page-container">
  <section class="screen">Screen 1</section>
  <section class="screen">Screen 2</section>
  <section class="screen">Screen 3</section>
</div>
  1. Add basic CSS
body, html { margin: 0; padding: 0; overflow: hidden; }
.screen { height: 100vh; display: flex; align-items: center; justify-content: center; font-size: 2rem; }
.screen:nth-child(1) { background: #f0f0f0; }
.screen:nth-child(2) { background: #e0e0e0; }
.screen:nth-child(3) { background: #d0d0d0; }
  1. Add the JavaScript logic
const container = document.querySelector('.page-container');
const screens = document.querySelectorAll('.screen');
let isDragging = false;
let startY = 0;
const dragThreshold = 50; // Minimum distance to trigger navigation
const bottomZoneHeight = window.innerHeight * 0.2; // 20% of viewport height for the trigger zone

// Track mouse down event (only in bottom zone)
document.addEventListener('mousedown', (e) => {
  if (e.clientY > window.innerHeight - bottomZoneHeight) {
    isDragging = true;
    startY = e.clientY;
    // Prevent text selection during drag
    document.body.style.userSelect = 'none';
  }
});

// Track mouse movement to detect drag direction
document.addEventListener('mousemove', (e) => {
  if (!isDragging) return;
  
  const dragDistance = startY - e.clientY;
  // If user drags upward past threshold, switch to next screen
  if (dragDistance > dragThreshold) {
    const currentScreenIndex = Array.from(screens).findIndex(screen => screen.getBoundingClientRect().top <= 0);
    if (currentScreenIndex < screens.length - 1) {
      container.scrollTo({
        top: (currentScreenIndex + 1) * window.innerHeight,
        behavior: 'smooth'
      });
    }
    isDragging = false;
    document.body.style.userSelect = '';
  }
});

// End drag on mouse up
document.addEventListener('mouseup', () => {
  isDragging = false;
  document.body.style.userSelect = '';
});

Vue 3 Implementation (Composition API)

If you're using Vue, you can clean up the logic with reactive state:

  1. Template
<template>
  <div class="page-container" ref="container">
    <section class="screen" v-for="(screen, idx) in 3" :key="idx">
      Screen {{ idx + 1 }}
    </section>
  </div>
</template>
  1. Script
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';

const container = ref(null);
let isDragging = ref(false);
let startY = ref(0);
const dragThreshold = 50;
const bottomZoneHeight = window.innerHeight * 0.2;

const handleMouseDown = (e) => {
  if (e.clientY > window.innerHeight - bottomZoneHeight) {
    isDragging.value = true;
    startY.value = e.clientY;
    document.body.style.userSelect = 'none';
  }
};

const handleMouseMove = (e) => {
  if (!isDragging.value) return;
  
  const dragDistance = startY.value - e.clientY;
  if (dragDistance > dragThreshold) {
    const currentScrollTop = container.value.scrollTop;
    const screenHeight = window.innerHeight;
    const nextScreenTop = Math.ceil(currentScrollTop / screenHeight) * screenHeight + screenHeight;
    
    if (nextScreenTop <= container.value.scrollHeight) {
      container.value.scrollTo({
        top: nextScreenTop,
        behavior: 'smooth'
      });
    }
    isDragging.value = false;
    document.body.style.userSelect = '';
  }
};

const handleMouseUp = () => {
  isDragging.value = false;
  document.body.style.userSelect = '';
};

onMounted(() => {
  document.addEventListener('mousedown', handleMouseDown);
  document.addEventListener('mousemove', handleMouseMove);
  document.addEventListener('mouseup', handleMouseUp);
});

onUnmounted(() => {
  document.removeEventListener('mousedown', handleMouseDown);
  document.removeEventListener('mousemove', handleMouseMove);
  document.removeEventListener('mouseup', handleMouseUp);
});
</script>

<style scoped>
/* Same CSS as vanilla example, add scoped tag */
body, html { margin: 0; padding: 0; overflow: hidden; }
.screen { height: 100vh; display: flex; align-items: center; justify-content: center; font-size: 2rem; }
.screen:nth-child(1) { background: #f0f0f0; }
.screen:nth-child(2) { background: #e0e0e0; }
.screen:nth-child(3) { background: #d0d0d0; }
</style>

Key Notes

  • Adjust bottomZoneHeight to change how much of the bottom screen counts as the trigger area
  • Tweak dragThreshold to make the navigation more or less sensitive
  • Add visual feedback (like a cursor change or section preview) to make the interaction more intuitive

内容的提问来源于stack exchange,提问作者Jeremy Clarkson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:30:33