B2B网络软件
标题:
无障碍方式双指向中间滑动放大缩小完整示例
[打印本页]
作者:
YYPOST群发软件
时间:
2 小时前
标题:
无障碍方式双指向中间滑动放大缩小完整示例
无障碍方式双指向中间滑动放大缩小完整示例
2.png
(2.16 MB, 下载次数: 0)
下载附件
2 小时前
上传
/**
* ============================================================
* AIWROK - 双指向中间滑动(捏合手势)完整示例【无碍模式】
* ============================================================
* 核心功能:
* 1. auto.dispatchGesture([path1, path2]) —— 同时执行多条路径,实现多点触控
* 2. new path() + setDurTime() + addPoint() —— 构建单根手指的滑动轨迹
*
* 手势说明:
* - 捏合(缩小):左指向右滑 + 右指向左滑,两指同时向中间靠拢
* - 放大(张开):左指向左滑 + 右指向右滑,两指同时向外分开(附带示例)
*
* 无碍模式特性:
* 1. 环境自检:运行前自动检查 path / auto.dispatchGesture 是否可用
* 2. 安全封装:创建路径、执行手势全部走 try-catch,任何一步失败都不崩溃
* 3. 参数校验:百分比参数越界自动纠正到合法范围
* 4. 单个手势失败不影响后续手势继续执行
* 5. 失败降级:返回 false 并给出排查建议,方便上层逻辑做备选方案
*
* 【重要】本文件仅适配"无碍模式"(无障碍服务)运行:
* - 手势一律使用 auto.dispatchGesture([path1, path2]) + new path()
* - 运行前请确认已开启 AIWROK 无障碍服务权限
* ============================================================
*/
// =====================================================
// 0. 环境自检(脚本运行时会自动执行一次)
// =====================================================
var _GESTURE_OK = true;
(function _gestureSelfCheck() {
var msg = "【自检】捏合手势运行环境:\n";
try {
if (typeof path === 'undefined') {
msg += " × path 对象不可用(无法创建手势路径)\n";
_GESTURE_OK = false;
} else {
msg += " ✓ path 对象可用\n";
}
if (typeof auto === 'undefined' || typeof auto.dispatchGesture !== 'function') {
msg += " × auto.dispatchGesture 不可用(无法执行手势)\n";
_GESTURE_OK = false;
} else {
msg += " ✓ auto.dispatchGesture 可用\n";
}
// 屏幕尺寸检测(可选,失败可用默认值)
try {
if (typeof screen !== 'undefined'
&& typeof screen.getScreenWidth === 'function'
&& typeof screen.getScreenHeight === 'function') {
msg += " ✓ screen 尺寸可用: " + screen.getScreenWidth() + " x " + screen.getScreenHeight() + "\n";
} else if (typeof device !== 'undefined' && typeof device.width === 'number') {
msg += " ✓ device 尺寸可用: " + device.width + " x " + device.height + "\n";
} else {
msg += " ⚠ 尺寸获取不可用,将回退 1080 x 1920\n";
}
} catch (e) {
msg += " ⚠ 尺寸读取异常: " + e + ",将回退 1080 x 1920\n";
}
if (_GESTURE_OK) {
msg += " ✓ 自检通过,可以正常执行捏合手势";
} else {
msg += " ✗ 自检未通过!请检查是否已开启 AIWROK 无障碍服务权限";
}
} catch (e) {
msg += " ✗ 自检过程异常: " + e + "\n";
_GESTURE_OK = false;
}
_log(msg);
})();
// =====================================================
// 1. 安全工具函数
// =====================================================
/**
* 安全获取屏幕尺寸(任何异常都回退默认值)
*/
function _gestureGetScreen() {
var w = 1080, h = 1920;
try {
if (typeof screen !== 'undefined') {
if (typeof screen.getScreenWidth === 'function') w = screen.getScreenWidth();
if (typeof screen.getScreenHeight === 'function') h = screen.getScreenHeight();
} else if (typeof device !== 'undefined') {
if (typeof device.width === 'number') w = device.width;
if (typeof device.height === 'number') h = device.height;
}
// 防脏数据:尺寸为 0 或非数字时回退默认
w = (typeof w === 'number' && w > 0) ? w : 1080;
h = (typeof h === 'number' && h > 0) ? h : 1920;
} catch (e) {
_log("⚠ 获取屏幕尺寸异常,使用默认值: " + e);
}
return { w: w, h: h };
}
/**
* 参数校验:把百分比约束到 0~1 之间(防止越界导致手势报错)
*/
function _clampPercent(v, fallback) {
try {
v = parseFloat(v);
if (isNaN(v)) return fallback;
if (v < 0) return 0;
if (v > 1) return 1;
return v;
} catch (e) {
return fallback;
}
}
/**
* 安全创建单指路径
* @param points 坐标点数组,如 [[x1,y1],[x2,y2]]
* @param duration 时长(毫秒)
* @return path 对象;创建失败返回 null
*/
function _safeCreatePath(points, duration) {
try {
if (typeof path === 'undefined') {
_log("✗ path 对象不可用,无法创建路径");
return null;
}
if (!points || points.length < 2) {
_log("✗ 路径点不足(至少需要 2 个点)");
return null;
}
var p = new path();
p.setDurTime(duration > 0 ? duration : 600);
for (var i = 0; i < points.length; i++) {
var pt = points[i];
if (!pt || typeof pt[0] !== 'number' || typeof pt[1] !== 'number') {
_log("✗ 路径点[" + i + "]非法,跳过该点: " + JSON.stringify(pt));
continue;
}
p.addPoint(pt[0], pt[1]);
}
return p;
} catch (e) {
_log("✗ 创建路径异常: " + e);
return null;
}
}
/**
* 安全执行手势(无碍核心:任何情况都不抛出异常)
* @param paths path 对象数组
* @return true/false
*/
function _safeDispatchGesture(paths) {
try {
if (!_GESTURE_OK) {
_log("✗ 环境自检未通过(path/dispatchGesture 不可用),跳过手势");
return false;
}
if (!paths || paths.length === 0) {
_log("✗ 手势路径数组为空,不执行");
return false;
}
if (typeof auto === 'undefined' || typeof auto.dispatchGesture !== 'function') {
_log("✗ auto.dispatchGesture 不可用,无法执行手势");
return false;
}
// 过滤掉创建失败(null)的路径,至少要有一条有效路径
var valid = [];
for (var i = 0; i < paths.length; i++) {
if (paths[i]) valid.push(paths[i]);
}
if (valid.length === 0) {
_log("✗ 没有有效的路径对象,不执行手势");
return false;
}
var result = auto.dispatchGesture(valid);
if (result === true || result === 1) {
return true;
}
_log("✗ dispatchGesture 返回失败(可能是权限不足或当前界面不支持手势)");
return false;
} catch (e) {
_log("✗ 执行手势异常: " + e);
return false;
}
}
/**
* 手势失败时的排查提示(无碍模式:失败不静默,给线索)
*/
function _gestureFailHint() {
_log(" └─ 排查建议:");
_log(" 1. 确认已开启 AIWROK 的【无障碍服务】权限");
_log(" 2. 确认当前处于支持双指捏合的界面(如看图/地图,桌面可能没反应)");
_log(" 3. 确认无障碍服务没有与其他应用冲突");
}
/**
* 日志工具:兼容 print.log / console.log
*/
function _log(msg) {
try {
if (typeof print !== 'undefined' && typeof print.log === 'function') {
print.log(msg);
} else if (typeof console !== 'undefined' && typeof console.log === 'function') {
console.log(msg);
}
} catch (e) {
// 日志失败直接忽略,不影响主体功能
}
}
// =====================================================
// 2. 无碍模式捏合工具函数(可直接复用)
// =====================================================
/**
* 水平捏合(左指向右 + 右指向左 → 向中间滑动)
* @param leftStartXPercent 左指起点 X 百分比 0~1
* @param rightStartXPercent 右指起点 X 百分比 0~1
* @param yPercent 捏合中心线 Y 百分比 0~1
* @param convergePercent 向中间收敛位置(0.5 = 正中心)
* @param duration 时长(毫秒)
*/
function pinchHorizontal(leftStartXPercent, rightStartXPercent, yPercent, convergePercent, duration) {
try {
leftStartXPercent = _clampPercent(leftStartXPercent, 0.25);
rightStartXPercent = _clampPercent(rightStartXPercent, 0.75);
yPercent = _clampPercent(yPercent, 0.5);
convergePercent = _clampPercent(convergePercent, 0.5);
duration = (typeof duration === 'number' && duration > 0) ? duration : 600;
var s = _gestureGetScreen();
var y = s.h * yPercent;
var cx = s.w * convergePercent;
var gap = s.w * 0.05;
// 左指:起点 → 中心左侧(留间距不撞车)
var pL = _safeCreatePath([
[s.w * leftStartXPercent, y],
[cx - gap, y]
], duration);
// 右指:起点 → 中心右侧
var pR = _safeCreatePath([
[s.w * rightStartXPercent, y],
[cx + gap, y]
], duration);
_log("水平捏合: 左 " + (leftStartXPercent * 100).toFixed(0) + "% → 中心左"
+ ",右 " + (rightStartXPercent * 100).toFixed(0) + "% → 中心右"
+ ",Y=" + (yPercent * 100).toFixed(0) + "%,时长 " + duration + "ms");
var ok = _safeDispatchGesture([pL, pR]);
_log(ok ? "✓ 水平捏合执行成功" : "✗ 水平捏合执行失败");
if (!ok) _gestureFailHint();
return ok;
} catch (e) {
_log("✗ 水平捏合函数异常: " + e);
return false;
}
}
/**
* 垂直捏合(上指下滑 + 下指上滑 → 向中间)
* @param topStartYPercent 上指起点 Y 百分比 0~1
* @param bottomStartYPercent 下指起点 Y 百分比 0~1
* @param xPercent 捏合中心线 X 百分比 0~1
* @param convergePercent 向中间收敛位置(0.5 = 正中心)
* @param duration 时长(毫秒)
*/
function pinchVertical(topStartYPercent, bottomStartYPercent, xPercent, convergePercent, duration) {
try {
topStartYPercent = _clampPercent(topStartYPercent, 0.25);
bottomStartYPercent = _clampPercent(bottomStartYPercent, 0.75);
xPercent = _clampPercent(xPercent, 0.5);
convergePercent = _clampPercent(convergePercent, 0.5);
duration = (typeof duration === 'number' && duration > 0) ? duration : 600;
var s = _gestureGetScreen();
var x = s.w * xPercent;
var cy = s.h * convergePercent;
var gap = s.h * 0.05;
// 上指:顶部 → 中心上方
var pT = _safeCreatePath([
[x, s.h * topStartYPercent],
[x, cy - gap]
], duration);
// 下指:底部 → 中心下方
var pB = _safeCreatePath([
[x, s.h * bottomStartYPercent],
[x, cy + gap]
], duration);
_log("垂直捏合: 上 " + (topStartYPercent * 100).toFixed(0) + "% + 下 "
+ (bottomStartYPercent * 100).toFixed(0) + "% → 中心,X="
+ (xPercent * 100).toFixed(0) + "%,时长 " + duration + "ms");
var ok = _safeDispatchGesture([pT, pB]);
_log(ok ? "✓ 垂直捏合执行成功" : "✗ 垂直捏合执行失败");
if (!ok) _gestureFailHint();
return ok;
} catch (e) {
_log("✗ 垂直捏合函数异常: " + e);
return false;
}
}
/**
* 对角线捏合(左上 + 右下 → 中心,看图缩小最常用)
* @param duration 时长(毫秒)
*/
function pinchDiagonal(duration) {
try {
duration = (typeof duration === 'number' && duration > 0) ? duration : 700;
var s = _gestureGetScreen();
var cx = s.w * 0.5, cy = s.h * 0.5;
var gx = s.w * 0.05, gy = s.h * 0.05;
var p1 = _safeCreatePath([
[s.w * 0.15, s.h * 0.20],
[cx - gx, cy - gy]
], duration);
var p2 = _safeCreatePath([
[s.w * 0.85, s.h * 0.80],
[cx + gx, cy + gy]
], duration);
_log("对角线捏合: 左上(15%,20%) + 右下(85%,80%) → 中心,时长 " + duration + "ms");
var ok = _safeDispatchGesture([p1, p2]);
_log(ok ? "✓ 对角线捏合执行成功" : "✗ 对角线捏合执行失败");
if (!ok) _gestureFailHint();
return ok;
} catch (e) {
_log("✗ 对角线捏合函数异常: " + e);
return false;
}
}
/**
* 通用双指捏合(任意起点 + 指定收敛中心)
* @param start1 起点1 {x:0~1, y:0~1}
* @param start2 起点2 {x:0~1, y:0~1}
* @param center 收敛中心 {x:0~1, y:0~1}
* @param duration 时长(毫秒)
*/
function pinchGeneric(start1, start2, center, duration) {
try {
if (!start1 || !start2 || typeof start1.x !== 'number' || typeof start2.x !== 'number') {
_log("✗ pinchGeneric 参数错误:start1/start2 必填且必须含 x/y 百分比");
return false;
}
var s = _gestureGetScreen();
center = center || { x: 0.5, y: 0.5 };
duration = (typeof duration === 'number' && duration > 0) ? duration : 700;
var ratio = 0.85; // 向中心靠近比例(留间距避免两指重合被识别成单指)
var cx = s.w * _clampPercent(center.x, 0.5);
var cy = s.h * _clampPercent(center.y, 0.5);
var p1 = _safeCreatePath([
[s.w * _clampPercent(start1.x, 0.25), s.h * _clampPercent(start1.y, 0.25)],
[s.w * _clampPercent(start1.x, 0.25) + (cx - s.w * _clampPercent(start1.x, 0.25)) * ratio,
s.h * _clampPercent(start1.y, 0.25) + (cy - s.h * _clampPercent(start1.y, 0.25)) * ratio]
], duration);
var p2 = _safeCreatePath([
[s.w * _clampPercent(start2.x, 0.75), s.h * _clampPercent(start2.y, 0.75)],
[s.w * _clampPercent(start2.x, 0.75) + (cx - s.w * _clampPercent(start2.x, 0.75)) * ratio,
s.h * _clampPercent(start2.y, 0.75) + (cy - s.h * _clampPercent(start2.y, 0.75)) * ratio]
], duration);
_log("通用捏合: (" + start1.x + "," + start1.y + ") + (" + start2.x + "," + start2.y
+ ") → 中心(" + center.x + "," + center.y + "),时长 " + duration + "ms");
var ok = _safeDispatchGesture([p1, p2]);
_log(ok ? "✓ 通用捏合执行成功" : "✗ 通用捏合执行失败");
if (!ok) _gestureFailHint();
return ok;
} catch (e) {
_log("✗ 通用捏合函数异常: " + e);
return false;
}
}
/**
* 水平放大(与捏合相反,双指向外分开)
* @param duration 时长(毫秒)
*/
function zoomHorizontal(duration) {
try {
duration = (typeof duration === 'number' && duration > 0) ? duration : 600;
var s = _gestureGetScreen();
var y = s.h * 0.5;
var gap = s.w * 0.05;
var pL = _safeCreatePath([
[s.w * 0.5 - gap, y],
[s.w * 0.20, y]
], duration);
var pR = _safeCreatePath([
[s.w * 0.5 + gap, y],
[s.w * 0.80, y]
], duration);
_log("水平放大: 中间 → 左右张开,时长 " + duration + "ms");
var ok = _safeDispatchGesture([pL, pR]);
_log(ok ? "✓ 水平放大执行成功" : "✗ 水平放大执行失败");
if (!ok) _gestureFailHint();
return ok;
} catch (e) {
_log("✗ 水平放大函数异常: " + e);
return false;
}
}
// =====================================================
// 3. 主流程(无碍模式:每个示例独立 try-catch,互不影响)
// =====================================================
function main() {
_log("========== 双指向中间滑动(捏合手势)示例【无碍模式】 ==========");
if (!_GESTURE_OK) {
_log("✗ 环境自检未通过,跳过所有手势执行(请先开启无障碍服务权限)");
return;
}
var s = _gestureGetScreen();
var screenW = s.w, screenH = s.h;
_log("屏幕尺寸: " + screenW + " x " + screenH);
// ---------- 示例 1:水平方向双指捏合(向中间滑动,缩小图片用) ----------
_log("\n--- 示例1: 水平捏合(向中间滑动,缩小)---");
try {
var pathLeft1 = new path();
pathLeft1.setDurTime(600);
pathLeft1.addPoint(screenW * 0.25, screenH * 0.5);
pathLeft1.addPoint(screenW * 0.45, screenH * 0.5);
var pathRight1 = new path();
pathRight1.setDurTime(600);
pathRight1.addPoint(screenW * 0.75, screenH * 0.5);
pathRight1.addPoint(screenW * 0.55, screenH * 0.5);
var ok1 = _safeDispatchGesture([pathLeft1, pathRight1]);
_log(ok1 ? "✓ 水平捏合执行成功" : "✗ 水平捏合执行失败");
if (!ok1) _gestureFailHint();
} catch (e) {
_log("✗ 示例1 异常: " + e);
}
try { sleep.second(1); } catch (e) {}
// ---------- 示例 2:垂直方向双指捏合(上指下滑 + 下指上滑 → 向中间) ----------
_log("\n--- 示例2: 垂直捏合(向中间滑动)---");
try {
var pathTop = new path();
pathTop.setDurTime(600);
pathTop.addPoint(screenW * 0.5, screenH * 0.25);
pathTop.addPoint(screenW * 0.5, screenH * 0.45);
var pathBottom = new path();
pathBottom.setDurTime(600);
pathBottom.addPoint(screenW * 0.5, screenH * 0.75);
pathBottom.addPoint(screenW * 0.5, screenH * 0.55);
var ok2 = _safeDispatchGesture([pathTop, pathBottom]);
_log(ok2 ? "✓ 垂直捏合执行成功" : "✗ 垂直捏合执行失败");
if (!ok2) _gestureFailHint();
} catch (e) {
_log("✗ 示例2 异常: " + e);
}
try { sleep.second(1); } catch (e) {}
// ---------- 示例 3:对角线捏合(左上+右下同时向中心靠拢) ----------
_log("\n--- 示例3: 对角线捏合(左上+右下 → 中心)---");
try {
var pathLT = new path();
pathLT.setDurTime(700);
pathLT.addPoint(screenW * 0.15, screenH * 0.2);
pathLT.addPoint(screenW * 0.42, screenH * 0.46);
var pathRB = new path();
pathRB.setDurTime(700);
pathRB.addPoint(screenW * 0.85, screenH * 0.8);
pathRB.addPoint(screenW * 0.58, screenH * 0.54);
var ok3 = _safeDispatchGesture([pathLT, pathRB]);
_log(ok3 ? "✓ 对角线捏合执行成功" : "✗ 对角线捏合执行失败");
if (!ok3) _gestureFailHint();
} catch (e) {
_log("✗ 示例3 异常: " + e);
}
try { sleep.second(1); } catch (e) {}
// ---------- 示例 4:放大手势(与捏合相反,双指向外分开) ----------
_log("\n--- 示例4: 水平放大(双指向外分开)---");
try {
var pathLeft4 = new path();
pathLeft4.setDurTime(600);
pathLeft4.addPoint(screenW * 0.45, screenH * 0.5);
pathLeft4.addPoint(screenW * 0.20, screenH * 0.5);
var pathRight4 = new path();
pathRight4.setDurTime(600);
pathRight4.addPoint(screenW * 0.55, screenH * 0.5);
pathRight4.addPoint(screenW * 0.80, screenH * 0.5);
var ok4 = _safeDispatchGesture([pathLeft4, pathRight4]);
_log(ok4 ? "✓ 水平放大执行成功" : "✗ 水平放大执行失败");
if (!ok4) _gestureFailHint();
} catch (e) {
_log("✗ 示例4 异常: " + e);
}
try { sleep.second(1); } catch (e) {}
// ---------- 示例 5:调用封装函数 ----------
_log("\n--- 示例5: 调用封装函数 pinchHorizontal() ---");
try {
var ok5 = pinchHorizontal(0.2, 0.8, 0.5, 0.5, 800);
_log(ok5 ? "✓ 封装函数调用成功" : "✗ 封装函数调用失败(不影响脚本继续)");
} catch (e) {
_log("✗ 示例5 异常: " + e);
}
try { sleep.second(1); } catch (e) {}
// ---------- 示例 6:封装函数集合演示(垂直/对角线/放大/通用) ----------
_log("\n--- 示例6: 封装函数集合演示 ---");
try {
pinchVertical(0.2, 0.8, 0.5, 0.5, 700);
try { sleep.second(1); } catch (e) {}
pinchDiagonal(800);
try { sleep.second(1); } catch (e) {}
zoomHorizontal(700);
try { sleep.second(1); } catch (e) {}
pinchGeneric({x: 0.1, y: 0.1}, {x: 0.9, y: 0.9}, {x: 0.5, y: 0.5}, 800);
} catch (e) {
_log("✗ 示例6 异常: " + e);
}
_log("\n========== 示例全部执行完成(无碍模式) ==========");
}
// 执行主函数
main();
复制代码
欢迎光临 B2B网络软件 (http://bbs.niubt.cn/)
Powered by Discuz! X3.2