






















IOS模拟点击的时候发现没作用,怀疑是坐标不对,想找个工具来显示下我当前点击的位置,各种搜在线工具,都没有找到,结果把需求告诉ChatGPT让它帮我写,瞬间就写对了,一行代码都不需要改的,AI真的太强大了,记录一下,方便以后万一用到。
现有的功能有:JS捕获所有触摸、click、keyup和keyon等事件并打印坐标、按压时长等信息(里面还有一个输入框和登录框是我为了模拟真实环境写的)
我是在Appium+wda模拟点击safari加载的网页上的按钮没起作用,原因我一开始以为是JS像素点与触摸坐标转换问题,通过这个工具,我发现我获取到按钮的坐标传入后,点击的位置在按钮上面,瞬间想到有可能是顶部灵动岛高度问题,后来仔细研究发现:Appium+wda在webview下获取的控件位置是指浏览器可视区开始(不包括灵动岛),而模拟触摸方式的坐标是从手机屏幕的左上角开始,所以控件的高+灵动岛的高度44,就可以了准确点击到控件了
以下是代码,保存成.html文件,访问就可以看到效果
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>触摸行为监控</title>
<style>
body {
margin: 0;
font-family: Arial, sans-serif;
background: #111;
color: #0f0;
}
#log {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 160px;
overflow-y: auto;
background: rgba(0,0,0,0.9);
font-size: 12px;
padding: 8px;
z-index: 999;
}
#canvas {
position: absolute;
top: 160px;
left: 0;
}
#bottomBar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 60px;
background: #222;
display: flex;
align-items: center;
padding: 8px;
gap: 8px;
}
#input {
flex: 1;
height: 40px;
font-size: 16px;
padding: 0 8px;
}
#btn {
width: 100px;
height: 40px;
font-size: 16px;
}
#toast {
position: fixed;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
background: rgba(0,0,0,0.8);
color: #0f0;
padding: 10px 16px;
border-radius: 6px;
display: none;
z-index: 1000;
}
</style>
</head>
<body>
<div id="log"></div>
<canvas id="canvas"></canvas>
<div id="bottomBar">
<input id="input" placeholder="请输入内容" />
<button id="btn">登录</button>
</div>
<div id="toast">登录按钮已点击</div>
<script>
const logDiv = document.getElementById('log');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const toast = document.getElementById('toast');
const bottomBarHeight = 60;
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight - 160 - bottomBarHeight;
}
resize();
window.addEventListener('resize', resize);
let startTime = 0;
let path = [];
const keyDownMap = {};
function log(msg) {
const el = document.createElement('div');
el.innerText = msg;
logDiv.prepend(el);
}
function showToast(msg) {
toast.innerText = msg;
toast.style.display = 'block';
setTimeout(() => {
toast.style.display = 'none';
}, 1000);
}
function drawPath() {
if (path.length < 2) return;
ctx.beginPath();
ctx.moveTo(path[0].x, path[0].y);
for (let i = 1; i < path.length; i++) {
ctx.lineTo(path[i].x, path[i].y);
}
ctx.strokeStyle = 'lime';
ctx.lineWidth = 2;
ctx.stroke();
}
function drawPoint(x, y) {
ctx.beginPath();
ctx.arc(x, y, 6, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
}
function handleStart(e) {
const touch = e.touches ? e.touches[0] : e;
startTime = Date.now();
path = [];
ctx.clearRect(0, 0, canvas.width, canvas.height);
log(`START | type=${e.type} | x=${touch.clientX} | y=${touch.clientY}`);
drawPoint(touch.clientX, touch.clientY - 160);
}
function handleMove(e) {
const touch = e.touches ? e.touches[0] : e;
const x = touch.clientX;
const y = touch.clientY - 160;
path.push({ x, y });
ctx.clearRect(0, 0, canvas.width, canvas.height);
drawPath();
log(`MOVE | type=${e.type} | x=${touch.clientX} | y=${touch.clientY}`);
}
function handleEnd(e) {
const duration = Date.now() - startTime;
log(`END | type=${e.type} | duration=${duration}ms | points=${path.length}`);
}
function handleClick(e) {
log(`CLICK | x=${e.clientX} | y=${e.clientY}`);
drawPoint(e.clientX, e.clientY - 160);
}
function handleFocus(e) {
log(`FOCUS | target=${e.target.tagName}`);
}
function handleKeyDown(e) {
keyDownMap[e.code] = Date.now();
log(`KEYDOWN | key=${e.key} | code=${e.code}`);
}
function handleKeyUp(e) {
const now = Date.now();
const start = keyDownMap[e.code] || now;
const duration = now - start;
log(`KEYUP | key=${e.key} | code=${e.code} | duration=${duration}ms`);
}
function handleInput(e) {
log(`INPUT | value=${e.target.value}`);
}
// 登录按钮点击提示(核心新增)
document.getElementById('btn').addEventListener('click', function(e) {
const btn = document.getElementById('btn');
const input = document.getElementById('input');
const btnRect = btn.getBoundingClientRect();
const inputRect = input.getBoundingClientRect();
const msg = `LOGIN BUTTON CLICKED | BTN[x=${btnRect.left.toFixed(1)},y=${btnRect.top.toFixed(1)},w=${btnRect.width.toFixed(1)},h=${btnRect.height.toFixed(1)}] | INPUT[x=${inputRect.left.toFixed(1)},y=${inputRect.top.toFixed(1)},w=${inputRect.width.toFixed(1)},h=${inputRect.height.toFixed(1)}]`;
log(msg);
showToast(`按钮坐标:(${btnRect.left.toFixed(0)},${btnRect.top.toFixed(0)}) 输入框:(${inputRect.left.toFixed(0)},${inputRect.top.toFixed(0)})`);
// 在画布上标出按钮中心点
const btnCenterX = btnRect.left + btnRect.width / 2;
const btnCenterY = btnRect.top + btnRect.height / 2 - 160;
drawPoint(btnCenterX, btnCenterY);
});
// Touch
document.addEventListener('touchstart', handleStart);
document.addEventListener('touchmove', handleMove);
document.addEventListener('touchend', handleEnd);
// Mouse
document.addEventListener('mousedown', handleStart);
document.addEventListener('mousemove', handleMove);
document.addEventListener('mouseup', handleEnd);
// Click
document.addEventListener('click', handleClick);
// Focus
document.addEventListener('focus', handleFocus, true);
// Keyboard
document.addEventListener('keydown', handleKeyDown);
document.addEventListener('keyup', handleKeyUp);
// Input
document.getElementById('input').addEventListener('input', handleInput);
document.addEventListener('touchmove', function(e) {
if (e.target.id !== 'input') {
e.preventDefault();
}
}, { passive: false });
</script>
</body>
</html>
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。