Qualtrics嵌入iframe内鼠标点击计数及坐标采集故障求助
问题概述
在Qualtrics调研平台中嵌入iframe形式的视频游戏,需实现两个核心功能:
- 基于改编代码每10ms采集鼠标x/y坐标
- 统计参与者的鼠标点击次数(包含iframe内的点击)
当前存在的问题:
- 仅能统计iframe外的点击,无法捕获iframe内的点击操作
- 数据输出中点击数始终为0
- 原有的鼠标坐标采集功能完全失效
问题排查与分析
- iframe点击事件绑定时机错误:代码在iframe未加载完成时直接尝试访问
iframeContent并绑定事件,此时iframeContent未定义,触发报错导致后续代码无法执行。 - addclick函数逻辑颠倒:函数内部嵌套iframe的load事件监听,导致点击事件触发时才去绑定load事件,完全无法实现计数逻辑。
- 鼠标追踪初始化时机错误:
document.onload = doTimer();写法错误(应赋值函数而非直接执行),且未结合Qualtrics的页面生命周期函数启动计时器,导致DOM未就绪时执行初始化。 - 变量作用域混乱:部分变量暴露在全局作用域,易在Qualtrics环境中被污染或无法正常访问。
修复后的代码
Qualtrics JavaScript代码
Qualtrics.SurveyEngine.addOnload(function() { // 初始化所有变量,封装在函数作用域内避免污染 var delayedXPos = []; var delayedYPos = []; var delayedTime = []; var xPos = []; var yPos = []; var initTime = new Date().getTime(); var timer_is_on = 0; var t; const dt = 10; let numberOfClicks = 0; let mp_called = 0; const iframe = document.getElementById('myFrame'); // 鼠标移动坐标采集逻辑 function getMousePosition(mp) { const divPos = getPosition(document.getElementById("Questions")); xPos.push(mp.pageX - divPos[0]); yPos.push(mp.pageY - divPos[1]); mp_called = 1; return true; } // 点击计数逻辑 function addclick() { numberOfClicks++; // 若页面有显示点击数的元素,更新显示(可选) const clicksEl = document.getElementById('clicks'); if (clicksEl) clicksEl.innerHTML = numberOfClicks; } // 定时保存坐标数据 function timedCount() { if (mp_called) { delayedXPos.push(xPos[xPos.length - 1]); delayedYPos.push(yPos[yPos.length - 1]); const timeInSec = (new Date().getTime() - initTime) / 1000.; delayedTime.push(timeInSec); } t = setTimeout(timedCount, dt); } // 启动坐标采集计时器 function doTimer() { if (!timer_is_on) { initTime = new Date().getTime(); timer_is_on = 1; timedCount(); } } // 获取元素相对页面的位置 function getPosition(obj) { let topValue = 0, leftValue = 0; while (obj) { leftValue += obj.offsetLeft; topValue += obj.offsetTop; obj = obj.offsetParent; } return [leftValue, topValue]; } // 绑定全局鼠标移动事件 document.addEventListener('mousemove', getMousePosition); // 等待iframe加载完成后绑定内部点击事件 iframe.addEventListener('load', function() { const iframeContent = iframe.contentDocument || iframe.contentWindow.document; // 绑定iframe内部文档的点击事件 iframeContent.addEventListener("click", addclick); // 额外绑定iframe元素本身的点击事件,覆盖边缘场景 iframe.addEventListener("click", addclick); }); // 页面提交时保存所有采集数据到嵌入字段 Qualtrics.SurveyEngine.addOnPageSubmit(function(type) { if (type == "next") { Qualtrics.SurveyEngine.setEmbeddedData("xPos", delayedXPos.join()); Qualtrics.SurveyEngine.setEmbeddedData("yPos", delayedYPos.join()); Qualtrics.SurveyEngine.setEmbeddedData("time", delayedTime.join()); Qualtrics.SurveyEngine.setEmbeddedData("click", numberOfClicks); } }); }); Qualtrics.SurveyEngine.addOnReady(function() { // 页面完全渲染后启动坐标采集 doTimer(); }); Qualtrics.SurveyEngine.addOnUnload(function() { // 页面卸载时清理计时器,避免内存泄漏 clearTimeout(t); });
嵌入游戏的HTML代码
<iframe id="myFrame" src="https://minmaxia.com/c2/" width="1024" height="800" style="border:1px solid black;" title="clickpocalypse 2"></iframe>
修复说明
- 修正iframe点击绑定逻辑:等待iframe加载完成后再获取内部文档并绑定点击事件,同时绑定iframe元素本身的点击事件,确保所有点击场景都被捕获。
- 重构addclick函数:移除嵌套的load事件监听,直接执行计数操作,保证点击触发时立即统计。
- 调整计时器启动时机:将
doTimer()移至addOnReady函数中,确保DOM完全就绪后启动坐标采集。 - 优化变量作用域:所有变量封装在
addOnload函数内部,避免全局作用域污染,适配Qualtrics执行环境。 - 添加资源清理:在
addOnUnload中清理计时器,防止页面卸载后计时器持续运行导致内存泄漏。 - 规范事件绑定方式:使用
addEventListener替代直接赋值事件属性,避免覆盖其他事件监听,符合现代JS开发规范。
内容的提问来源于stack exchange,提问作者Veljon
相关产品推荐
相关产品推荐

