 | |  |  | 无障碍方式双指向中间滑动放大缩小完整示例
- /**
- * ============================================================
- * 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();
复制代码
| |  | |  |
|