在 OpenClaw 中,横竖屏适配通常通过以下几种方式实现

openclaw openclaw中文博客 1

CSS 媒体查询适配

基础方向检测

/* 竖屏样式 */
@media screen and (orientation: portrait) {
  .container {
    flex-direction: column;
    padding: 20px;
  }
}
/* 横屏样式 */
@media screen and (orientation: landscape) {
  .container {
    flex-direction: row;
    padding: 10px;
  }
}

结合宽高比适配

/* 移动端竖屏 */
@media screen and (max-aspect-ratio: 3/4) {
  /* 窄屏样式 */
}
/* 平板/横屏 */
@media screen and (min-aspect-ratio: 4/3) {
  /* 宽屏样式 */
}

JavaScript 方向检测

监听方向变化

// 检测方向变化
function handleOrientationChange() {
  if (window.matchMedia("(orientation: portrait)").matches) {
    console.log("竖屏模式");
    // 执行竖屏逻辑
  } else {
    console.log("横屏模式");
    // 执行横屏逻辑
  }
}
// 初始化检测
handleOrientationChange();
// 添加监听
window.addEventListener('resize', handleOrientationChange);
window.addEventListener('orientationchange', handleOrientationChange);

获取详细方向信息

// 获取屏幕方向
const getOrientation = () => {
  const angle = window.orientation;
  switch(angle) {
    case 0:
    case 180:
      return 'portrait';
    case 90:
    case -90:
      return 'landscape';
    default:
      return window.innerWidth > window.innerHeight ? 'landscape' : 'portrait';
  }
};

React 组件适配

自定义 Hook

import { useState, useEffect } from 'react';
function useOrientation() {
  const [orientation, setOrientation] = useState(
    window.innerWidth > window.innerHeight ? 'landscape' : 'portrait'
  );
  useEffect(() => {
    const handleResize = () => {
      setOrientation(
        window.innerWidth > window.innerHeight ? 'landscape' : 'portrait'
      );
    };
    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);
  return orientation;
}
// 使用示例
function MyComponent() {
  const orientation = useOrientation();
  return (
    <div className={orientation === 'landscape' ? 'horizontal-layout' : 'vertical-layout'}>
      {/* 内容 */}
    </div>
  );
}

方向敏感组件

function ResponsiveLayout({ children }) {
  const isLandscape = window.innerWidth > window.innerHeight;
  return (
    <div className={`layout ${isLandscape ? 'landscape' : 'portrait'}`}>
      {isLandscape ? (
        <div className="side-by-side">
          <div className="left-panel">{children[0]}</div>
          <div className="right-panel">{children[1]}</div>
        </div>
      ) : (
        <div className="stacked">
          <div className="top-section">{children[0]}</div>
          <div className="bottom-section">{children[1]}</div>
        </div>
      )}
    </div>
  );
}

实用 CSS 适配方案

响应式布局容器

/* 基础容器 */
.responsive-container {
  display: flex;
  transition: all 0.3s ease;
}
/* 竖屏:垂直排列 */
@media (orientation: portrait) {
  .responsive-container {
    flex-direction: column;
    min-height: 100vh;
  }
  .content {
    padding: 1rem;
  }
}
/* 横屏:水平排列 */
@media (orientation: landscape) {
  .responsive-container {
    flex-direction: row;
    min-height: auto;
    height: 100vh;
  }
  .sidebar {
    width: 250px;
    flex-shrink: 0;
  }
  .content {
    flex: 1;
    padding: 2rem;
  }
}

字体大小适配

:root {
  --base-font-size: 16px;
}
@media (orientation: landscape) {
  :root {
    --base-font-size: 14px;
  }
  h1 {
    font-size: calc(var(--base-font-size) * 2.5);
  }
}
@media (orientation: portrait) {
  :root {
    --base-font-size: 18px;
  }
  h1 {
    font-size: calc(var(--base-font-size) * 2);
  }
}

完整示例

// OrientationManager.js
class OrientationManager {
  constructor() {
    this.orientation = this.getOrientation();
    this.listeners = new Set();
    window.addEventListener('resize', this.handleResize.bind(this));
    window.addEventListener('orientationchange', this.handleOrientationChange.bind(this));
  }
  getOrientation() {
    return window.innerWidth > window.innerHeight ? 'landscape' : 'portrait';
  }
  handleResize() {
    const newOrientation = this.getOrientation();
    if (newOrientation !== this.orientation) {
      this.orientation = newOrientation;
      this.notifyListeners();
    }
  }
  handleOrientationChange() {
    setTimeout(() => {
      this.handleResize();
    }, 100);
  }
  addListener(callback) {
    this.listeners.add(callback);
    return () => this.listeners.delete(callback);
  }
  notifyListeners() {
    this.listeners.forEach(callback => callback(this.orientation));
  }
  isLandscape() {
    return this.orientation === 'landscape';
  }
  isPortrait() {
    return this.orientation === 'portrait';
  }
}
// 创建单例
export default new OrientationManager();

最佳实践建议

  1. 移动端优先:先设计竖屏布局,再适配横屏
  2. 渐进增强:基础功能在两种方向都能使用,横屏提供增强体验
  3. 避免锁定方向:除非必要(如游戏、视频播放器),不要强制锁定屏幕方向
  4. 测试多设备:在不同尺寸和分辨率的设备上测试
  5. 性能考虑:避免在方向变化时进行大量DOM操作

这些方法可以帮助你在 OpenClaw 项目中实现良好的横竖屏适配体验。

在 OpenClaw 中,横竖屏适配通常通过以下几种方式实现-第1张图片-OpenClaw 中文版 - 真正能做事的 AI

抱歉,评论功能暂时关闭!