Skip to content

zhangjingwei/ViewportTracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Universal Exposure Tracker

一个轻量级、高性能的页面元素曝光追踪库,支持静态和动态元素的曝光检测。

特性

  • 🚀 高性能: 使用 Intersection Observer API,性能优异
  • 🎯 精确检测: 支持自定义曝光阈值和曝光时间
  • 🔄 动态支持: 自动检测动态添加的元素
  • 🛠️ 易于集成: 简单的 API 设计,支持多种框架
  • 📊 数据导出: 支持曝光数据的导出和分析
  • 🎨 可定制: 丰富的配置选项和回调函数
  • 🔧 ID 管理: 智能的 ID 冲突处理和自动生成
  • 📈 实时统计: 提供详细的统计信息和实时更新

文件结构

ViewportTracker/
├── src/
│   ├── exposure-tracker.js      # 核心追踪器类
│   ├── exposure-adapter.js      # 框架适配器
│   ├── exposure-tracker.d.ts    # TypeScript 类型定义
│   └── exposure-adapter.d.ts    # TypeScript 类型定义
├── tests/
│   ├── fixtures/
│   │   ├── merged-test.html     # 综合测试页面
│   │   └── base.css             # 测试页面样式
│   ├── unit/                    # 单元测试
│   ├── integration/             # 集成测试
│   └── e2e/                     # 端到端测试
├── scripts/                     # 构建和开发脚本
├── dist/                        # 构建输出目录
└── README.md                    # 项目说明文档

快速开始

1. 引入文件

<!-- 引入核心追踪器 -->
<script src="src/exposure-tracker.js"></script>

<!-- 可选:引入适配器 -->
<script src="src/exposure-adapter.js"></script>

2. 基础使用

// 创建追踪器实例
const tracker = new UniversalExposureTracker({
    threshold: 0.5,        // 50% 可见时触发(默认)
    minExposureTime: 1000, // 最小曝光时间 1000ms(默认)
    once: true,            // 只触发一次(默认)
    debug: false,          // 关闭调试模式(默认)
    autoObserve: true      // 自动观察新元素(默认)
});

// 设置曝光回调
tracker.setExposureCallback(function(exposureData) {
    console.log('元素曝光:', exposureData.elementId);
    console.log('曝光时间:', exposureData.exposureTime);
    console.log('元素类型:', exposureData.elementType);
});

// 设置统计更新回调
tracker.setStatsUpdateCallback(function(stats) {
    console.log('统计更新:', stats.totalObserved, stats.totalExposed);
});

// 开始观察元素
const element = document.getElementById('my-element');
tracker.observe('my-element', element);

3. 使用适配器(简化版)

// 初始化适配器
exposureTrack.init({
    threshold: 0.3,
    minExposureTime: 500
});

// 设置回调
exposureTrack.onExposure(function(data) {
    console.log('曝光事件:', data);
});

// 观察元素
exposureTrack.observe('element-id', document.getElementById('element-id'));

配置选项

基础配置

选项 类型 默认值 描述
threshold number 0.5 元素可见比例阈值
rootMargin string '0px' 根边距
minExposureTime number 1000 最小曝光时间(ms)
maxExposureTime number 30000 最大曝光时间(ms)
once boolean true 是否只触发一次
debug boolean false 是否开启调试模式
autoObserve boolean true 是否自动观察新元素
debounceTime number 100 防抖时间(ms)
observeHiddenElements boolean false 是否观察隐藏元素

统计配置

选项 类型 默认值 描述
autoUpdateStats boolean true 是否自动更新统计
statsUpdateDelay number 150 统计更新延迟(ms)
enableStatsCallbacks boolean true 是否启用统计回调

ID 管理配置

选项 类型 默认值 描述
enforceUniqueIds boolean true 是否强制唯一ID
idConflictStrategy string 'suffix' ID冲突处理策略
autoGenerateIds boolean true 是否自动生成ID

扩展配置

选项 类型 默认值 描述
visibilityCheckers Array [] 自定义可见性检查器
elementTypeDetectors Array [] 自定义元素类型检测器
exposureRules Array [] 自定义曝光规则
attributeWatchers Array [] 自定义属性监听器

高级功能

自定义可见性检查器

tracker.addVisibilityChecker('custom-check', (element) => {
    // 自定义可见性检查逻辑
    return element.offsetWidth > 0 && element.offsetHeight > 0;
});

自定义元素类型检测器

tracker.addElementTypeDetector('product-card', (element) => {
    if (element.classList.contains('product-card')) {
        return 'product_card';
    }
    return null;
});

自定义曝光规则

tracker.addExposureRule('product-rule', {
    shouldExpose: (element, intersectionRatio) => {
        if (element.classList.contains('product-card')) {
            return intersectionRatio >= 0.5; // 产品卡片需要50%可见
        }
        return intersectionRatio >= 0.3; // 其他元素30%可见
    },
    getExposureTime: (element) => {
        if (element.classList.contains('product-card')) {
            return 1000; // 产品卡片需要1秒曝光时间
        }
        return 500; // 其他元素500ms
    }
});

动态元素支持

<!-- 自动检测带有 data-exposure-track 属性的元素 -->
<div data-exposure-track="dynamic-element-1">
    动态内容
</div>

<!-- 自动生成ID的元素 -->
<div data-exposure-track>
    自动生成ID的元素
</div>
// 设置动态元素回调
tracker.setDynamicElementCallback(function(elementId, element) {
    console.log('检测到动态元素:', elementId);
    // 可以在这里添加自定义逻辑
});

统计信息

// 获取统计信息
const stats = tracker.getStats();
console.log('总观察元素:', stats.totalObserved);
console.log('已曝光元素:', stats.totalExposed);
console.log('曝光率:', stats.exposureRate + '%');
console.log('动态元素统计:', stats.dynamicStats);
console.log('观察元素详情:', stats.observedElements);
console.log('曝光数据:', stats.exposureData);

// 设置统计更新回调
tracker.setStatsUpdateCallback(function(stats) {
    // 实时更新统计显示
    updateStatsDisplay(stats);
});

统计数据结构

{
    totalObserved: 10,        // 总观察元素数
    totalExposed: 7,          // 已曝光元素数
    exposureRate: 70,         // 曝光率(百分比)
    dynamicStats: {           // 动态元素统计
        totalDynamic: 5,
        dynamicExposed: 3,
        dynamicExposureRate: 60
    },
    observedElements: [       // 观察元素详情
        {
            id: 'element-1',
            hasExposed: true,
            isDynamic: false,
            elementType: 'div'
        }
    ],
    exposureData: [           // 曝光数据详情
        {
            elementId: 'element-1',
            element: HTMLElement,
            isDynamic: false,
            elementType: 'div',
            exposureTime: 1500,
            timestamp: 1640995200000,
            pageUrl: 'https://example.com',
            userAgent: 'Mozilla/5.0...',
            viewport: { width: 1920, height: 1080 }
        }
    ],
    lastUpdated: 1640995200000
}

数据导出

// 导出所有曝光数据
const allData = tracker.getAllExposureData();
const exportData = {
    timestamp: new Date().toISOString(),
    pageUrl: window.location.href,
    exposureData: Array.from(allData.entries()).map(([id, data]) => ({
        elementId: id,
        ...data
    }))
};

// 下载为 JSON 文件
const dataStr = JSON.stringify(exportData, null, 2);
const dataBlob = new Blob([dataStr], { type: 'application/json' });
const url = URL.createObjectURL(dataBlob);
const link = document.createElement('a');
link.href = url;
link.download = `exposure-data-${Date.now()}.json`;
link.click();

测试页面

项目包含完整的测试套件:

  • tests/fixtures/merged-test.html: 综合测试页面,包含所有功能演示
  • tests/unit/: 单元测试,测试核心功能
  • tests/integration/: 集成测试,测试完整流程
  • tests/e2e/: 端到端测试,使用 Puppeteer 进行浏览器测试

运行测试

# 运行所有测试
npm test

# 运行单元测试
npm test -- tests/unit/

# 运行集成测试
npm test -- tests/integration/

# 运行端到端测试
npm test -- tests/e2e/

# 查看测试覆盖率
npm run test:coverage

手动测试

# 启动开发服务器
npm run dev

# 打开浏览器访问 http://localhost:8080/tests/fixtures/merged-test.html

API 参考

UniversalExposureTracker 类

构造函数

new UniversalExposureTracker(options)

主要方法

方法 参数 返回值 描述
observe(id, element, options) id: string, element: Element, options: Object boolean 开始观察元素
unobserve(element) element: Element void 停止观察元素
observeHiddenElement(id, element, options) id: string, element: Element, options: Object boolean 观察隐藏元素
setExposureCallback(callback) callback: Function void 设置曝光回调
setDynamicElementCallback(callback) callback: Function void 设置动态元素回调
setStatsUpdateCallback(callback) callback: Function void 设置统计更新回调
getStats() - Object 获取统计信息
getExposureData(id) id: string Object|null 获取指定元素曝光数据
getAllExposureData() - Map 获取所有曝光数据
getDynamicStats() - Object 获取动态元素统计
clearExposureData(id) id: string void 清除曝光数据
resetElementExposureStates() - void 重置元素曝光状态
destroy() - void 销毁追踪器

扩展方法

方法 参数 返回值 描述
addVisibilityChecker(name, checker) name: string, checker: Function void 添加可见性检查器
addElementTypeDetector(name, detector) name: string, detector: Function void 添加元素类型检测器
addExposureRule(name, rule) name: string, rule: Object void 添加曝光规则
addAttributeWatcher(name, watcher) name: string, watcher: Object void 添加属性监听器

ExposureTrackerAdapter 适配器

全局方法

方法 参数 返回值 描述
exposureTrack.init(options) options: Object Object 初始化追踪器
exposureTrack.observe(id, element, options) id: string, element: Element, options: Object void 观察元素
exposureTrack.unobserve(element) element: Element void 停止观察
exposureTrack.onExposure(callback) callback: Function void 设置曝光回调
exposureTrack.onStatsUpdate(callback) callback: Function void 设置统计回调
exposureTrack.getStats() - Object 获取统计信息
exposureTrack.clear() - void 清除数据
exposureTrack.destroy() - void 销毁追踪器

构建和开发

构建项目

# 构建生产版本
npm run build

# 构建压缩版本
npm run build:minify

开发模式

# 启动开发服务器
npm run dev

# 运行手动测试
npm run test:manual

浏览器兼容性

  • Chrome 51+
  • Firefox 55+
  • Safari 12.1+
  • Edge 15+

需要以下 API 支持:

  • Intersection Observer API
  • MutationObserver API
  • Map 和 Set(ES6)

许可证

MIT License

贡献

欢迎提交 Issue 和 Pull Request!

联系方式

如有问题或建议,请通过以下方式联系:

  • 提交 Issue
  • 发送邮件

Universal Exposure Tracker - 让页面元素曝光检测变得简单高效!

更新日志

v1.0.0

  • ✨ 初始版本发布
  • 🚀 支持基础曝光检测功能
  • 🔄 支持动态元素自动检测
  • 📊 提供完整的统计功能
  • 🛠️ 支持多种配置选项
  • 🎨 提供扩展接口
  • 📈 支持实时统计更新
  • 🔧 智能ID管理
  • 📝 完整的TypeScript类型定义
  • 🧪 完整的测试套件

About

Universal Exposure Tracker - Track element visibility in viewport

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published