draw - 屏幕绘制工具
更新: 2026/3/2 字数: 0 字 时长: 0 分钟
Stability: 2 - Stable
$draw 模块用于在手机屏幕上进行 悬浮叠加绘制,支持点、圆、矩形、十字准心、直线、路径、文字、日志、控件节点等多种图形绘制,并内置 YOLO 视觉检测结果的专属绘制能力。
所有绘制内容以悬浮层形式展示,默认开启触摸事件穿透,不会遮挡底层应用操作,适合用于自动化调试、视觉检测结果可视化、屏幕标记等场景。
使用该模块需要开启 悬浮窗权限/显示在其他应用的上层,华为手机另外需要开启后台弹窗权限。
通用说明
坐标单位
所有坐标与尺寸单位均为 像素(px),坐标原点为屏幕左上角。
颜色格式
所有颜色参数支持:
- 整数颜色(
colors.RED、colors.argb()) - 十六进制字符串(
#RRGGBB、#AARRGGBB) 透明度范围:00(全透明)-FF(不透明)
具体可参阅colors
配置对象(Object)
所有绘制 API 均支持使用 配置对象方式 作为最后一个参数,用于替代多参数传递。
$draw.point(300, 600, {
color: "#80FF00FF",
strokeWidth: 2,
radius: 20
});绘制点
$draw.point(x, y, [color, strokeWidth, radius])
x{number} 点的X坐标y{number} 点的Y坐标color{int|string} 点的颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认0radius{number} 点的半径,默认10
在屏幕指定坐标绘制点,支持实心/描边效果,由strokeWidth控制。
$draw.point(200, 300);
$draw.point(300, 300, "#FF0000");
$draw.point(400, 300, colors.BLUE, 2, 15);$draw.point(x, y, options)
x{number} 点的X坐标y{number} 点的Y坐标options{Object} 绘制配置选项color{int|string} 点的颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认0radius{number} 点的半径,默认10
通过配置对象方式在屏幕指定坐标绘制点。
$draw.point(300, 600, { color: "#80FF00FF", strokeWidth: 0, radius: 20 });
$draw.point(400, 600, { color: colors.MAGENTA, strokeWidth: 0, radius: 6 });绘制圆
$draw.circle(cx, cy, [color, strokeWidth, radius])
cx{number} 圆心X坐标cy{number} 圆心Y坐标color{int|string} 圆形颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2,最小值为1radius{number} 圆形半径,默认30
在屏幕指定圆心位置绘制圆形,strokeWidth为0时绘制实心圆。
$draw.circle(200, 400);
$draw.circle(300, 400, "#FF0000", 1, 40);$draw.circle(cx, cy, options)
cx{number} 圆心X坐标cy{number} 圆心Y坐标options{Object} 绘制配置选项color{int|string} 圆形颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2radius{number} 圆形半径,默认30
通过配置对象方式在屏幕指定圆心位置绘制圆形。
$draw.circle(400, 600, { color: colors.MAGENTA, strokeWidth: 30, radius: 50 });绘制矩形
$draw.rect(left, top, width, height, [color, strokeWidth, cornerRadius, fillColor])
left{number} 矩形左上角X坐标top{number} 矩形左上角Y坐标width{number} 矩形宽度height{number} 矩形高度color{int|string} 描边颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2cornerRadius{number} 矩形圆角半径,默认0fillColor{int|string} 填充颜色,默认 透明
在屏幕指定位置绘制矩形,支持圆角、描边、实心填充效果。
$draw.rect(100, 200, 80, 50);
$draw.rect(300, 200, 100, 60, colors.RED, 6, 12);
$draw.rect(500, 200, 100, 60, colors.BLUE, 4, 16, "#8000FFFF");$draw.rect(left, top, width, height, options)
left{number} 矩形左上角X坐标top{number} 矩形左上角Y坐标width{number} 矩形宽度height{number} 矩形高度options{Object} 绘制配置选项color{int|string} 描边颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2cornerRadius{number} 矩形圆角半径,默认0fillColor{int|string} 填充颜色,默认 透明
通过配置对象方式在屏幕指定位置绘制矩形。
$draw.rect(320, 580, 400, 660, {
color: colors.MAGENTA,
strokeWidth: 30,
cornerRadius: 50,
fillColor: "#80FFA500"
});$draw.rect(rect, [color, strokeWidth, cornerRadius, fillColor])
rect{Rect} Android原生Rect对象(left, top, right, bottom)color{int|string} 描边颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2cornerRadius{number} 矩形圆角半径,默认0fillColor{int|string} 填充颜色,默认 透明
通过Android原生Rect对象指定区域绘制矩形。
var r1 = new android.graphics.Rect(100, 400, 200, 450);
$draw.rect(r1, colors.CYAN, 6, 12);
var r2 = new android.graphics.Rect(220, 400, 320, 460);
$draw.rect(r2, "#80FF00FF", 4, 16, "#8000FFFF");$draw.rect(left, top, width, height, options)
rect{Rect} Android原生Rect对象(left, top, right, bottom)options{Object} 绘制配置选项color{int|string} 描边颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2cornerRadius{number} 矩形圆角半径,默认0fillColor{int|string} 填充颜色,默认 透明
通过Android原生Rect对象指定区域绘制矩形。
var r3 = new android.graphics.Rect(420, 400, 320, 460);
$draw.rect(320, 580, 400, 660, {
color: colors.MAGENTA,
strokeWidth: 30,
cornerRadius: 50,
fillColor: "#80FFA500"
});绘制十字准心
$draw.cross(x, y, [color, strokeWidth, length])
x{number} 十字准心中心X坐标y{number} 十字准心中心Y坐标color{int|string} 十字颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2length{number} 十字单臂长度,默认40
在屏幕指定坐标绘制十字准心,十字总长度为2*length。
$draw.cross(200, 500);
$draw.cross(300, 500, colors.RED);
$draw.cross(400, 500, colors.CYAN, 8);
$draw.cross(500, 500, colors.YELLOW, 8, 60);$draw.cross(x, y, options)
x{number} 十字准心中心X坐标y{number} 十字准心中心Y坐标options{Object} 绘制配置选项color{int|string} 十字颜色,默认colors.GREENstrokeWidth{number} 描边宽度,默认2length{number} 十字单臂长度,默认40
通过配置对象方式在屏幕指定坐标绘制十字准心。
$draw.cross(600, 580, {
color: colors.MAGENTA,
strokeWidth: 30,
length: 50,
});绘制线
$draw.line(x1, y1, x2, y2, [color, strokeWidth])
x1{number} 直线起点X坐标y1{number} 直线起点Y坐标x2{number} 直线终点X坐标y2{number} 直线终点Y坐标color{int|string} 直线颜色,默认colors.GREENstrokeWidth{number} 直线宽度,默认2
在屏幕指定两点之间绘制直线,支持水平线、竖直线、斜线。
$draw.line(100, 600, 400, 600);
$draw.line(200, 600, 500, 800, colors.CYAN);
$draw.line(300, 600, 500, 800, colors.RED, 5);$draw.line(x1, y1, x2, y2, options)
x1{number} 直线起点X坐标y1{number} 直线起点Y坐标x2{number} 直线终点X坐标y2{number} 直线终点Y坐标options{Object} 绘制配置选项color{int|string} 直线颜色,默认colors.GREENstrokeWidth{number} 直线宽度,默认2
通过配置对象方式在屏幕指定两点之间绘制直线。
$draw.line(400, 350, 400, 450, { color: "#FF00FF", strokeWidth: 4 });绘制路径
$draw.path(points, [color, strokeWidth])
points{Array<Array<number>>}路径坐标点集合,格式为[[x1,y1],[x2,y2],...]color{int|string} 路径颜色,默认colors.GREENstrokeWidth{number} 路径宽度,默认2
根据指定的坐标点集合绘制连续的路径线条。
var p = [[200,700],[260,650],[320,720]];
$draw.path(p, colors.RED, 6);$draw.path(points, options)
points{Array<Array<number>>}路径坐标点集合,格式为[[x1,y1],[x2,y2],...]options{Object} 绘制配置选项color{int|string} 路径颜色,默认colors.GREENstrokeWidth{number} 路径宽度,默认2
通过配置对象方式根据指定坐标点集合绘制连续路径线条。
var pathPoints = [[200,500],[260,450],[320,520],[380,470]];
$draw.path(pathPoints, { color: colors.MAGENTA, strokeWidth: 6 });绘制文字
$draw.text(text, x, y, [color, size, bgColor, cornerRadius, padding])
text{string} 要绘制的文字内容x{number} 文字绘制左上角X坐标y{number} 文字绘制左上角Y坐标color{int|string} 文字颜色,默认 白色size{number} 文字字号,默认12bgColor{int|string} 文字背景颜色,默认 透明cornerRadius{number} 背景圆角半径,默认0padding{number} 文字与背景的内边距,默认0
在屏幕指定位置绘制文字,支持文字背景、圆角、内边距效果。
$draw.text("测试文字", 100, 120);
$draw.text("彩色文字", 100, 170, colors.MAGENTA);
$draw.text("大文字", 100, 220, colors.RED, 22);
$draw.text("带背景文字", 100, 300, colors.WHITE, 16, colors.BLACK, 4, 2);$draw.text(text, x, y, options)
text{string} 要绘制的文字内容x{number} 文字绘制左上角X坐标y{number} 文字绘制左上角Y坐标options{Object} 绘制配置选项color{int|string} 文字颜色,默认 白色size{number} 文字字号,默认12bgColor{int|string} 文字背景颜色,默认 透明cornerRadius{number} 背景圆角半径,默认0padding{number} 文字与背景的内边距,默认0
通过配置对象方式在屏幕指定位置绘制文字。
$draw.text("配置对象文字", 100, 270, {
color: "#FFFFFF",
size: 18,
bgColor: "#80FF0000",
cornerRadius: 6,
padding: 4
});绘制日志
$draw.log(text, [x, y, size])
$draw.l(text, [x, y, size])
text{string} 普通日志文字内容x{number} 日志绘制X坐标,可选y{number} 日志绘制Y坐标,可选size{number} 日志字号,可选
绘制普通日志文字,默认白色字体,适用于常规信息输出。
$draw.log("这是普通日志");
sleep(2000)
$draw.l("普通日志带坐标", 100, 400, 24);$draw.verbose(text, [x, y, size])
$draw.v(text, [x, y, size])
text{string} 详细日志文字内容x{number} 日志绘制X坐标,可选y{number} 日志绘制Y坐标,可选size{number} 日志字号,可选
绘制详细日志文字,默认灰色字体,适用于调试细节信息输出。
$draw.verbose("这是详细日志");
sleep(2000)
$draw.v("详细日志带坐标", 120, 250, 20);$draw.debug(text, [x, y, size])
$draw.d(text, [x, y, size])
text{string} 调试日志文字内容x{number} 日志绘制X坐标,可选y{number} 日志绘制Y坐标,可选size{number} 日志字号,可选
绘制调试日志文字,默认青色字体,适用于开发调试信息输出。
$draw.debug("这是调试日志");
sleep(2000)
$draw.d("调试日志带坐标", 140, 300, 22);$draw.info(text, [x, y, size])
$draw.i(text, [x, y, size])
text{string} 信息日志文字内容x{number} 日志绘制X坐标,可选y{number} 日志绘制Y坐标,可选size{number} 日志字号,可选
绘制信息日志文字,默认绿色字体,适用于成功、提示类信息输出。
$draw.info("操作成功");
sleep(2000)
$draw.i("信息日志带坐标", 160, 350, 24);$draw.warn(text, [x, y, size])
$draw.w(text, [x, y, size])
text{string} 警告日志文字内容x{number} 日志绘制X坐标,可选y{number} 日志绘制Y坐标,可选size{number} 日志字号,可选
绘制警告日志文字,默认黄色字体,适用于警告、提醒类信息输出。
$draw.warn("数据异常警告");
sleep(2000)
$draw.w("警告日志带坐标", 180, 400, 26);$draw.error(text, [x, y, size])
$draw.e(text, [x, y, size])
text{string} 错误日志文字内容x{number} 日志绘制X坐标,可选y{number} 日志绘制Y坐标,可选size{number} 日志字号,可选
绘制错误日志文字,默认红色字体,适用于错误、异常类信息输出。
$draw.error("接口请求失败");
sleep(2000)
$draw.e("错误日志带坐标", 200, 450, 28);绘制YOLOResults
$draw.yolo(yoloResults, [image])
yoloResults{Array<Object>}— YOLO 检测结果集合,每个对象可包含以下类型信息:- 目标检测 (Detection):包含
class(类别)、box(矩形框[x, y, w, h])、confidence(置信度) - 旋转框检测 (Rotated Detection):包含
class、box(旋转矩形[x, y, w, h, angle])、confidence(置信度) - 分割 (Segment / Mask):包含
class、mask(二值或多边形掩码)、confidence - 分类 (Classify):包含
class、confidence - 姿态估计 (Pose / Keypoints):包含
keypoints(关键点数组[x, y, confidence])
- 目标检测 (Detection):包含
image{Bitmap|Image} 检测的原始图片对象,可选,如果传入,会在该图片上绘制,否则则在屏幕上绘制
绘制 YOLO 模型的检测结果,支持以下功能:
- 自动绘制目标检测矩形框,并显示类别和置信度
- 支持旋转框绘制,自动旋转显示目标方向
- 支持目标分割(Mask/Polygon)绘制,显示半透明覆盖区域
- 支持分类结果标注
- 支持姿态估计绘制,包括关键点和骨架连线
无需手动计算坐标或处理样式,即可快速在屏幕或指定图片上可视化 YOLO 检测结果。
// 在屏幕上绘制 YOLO 检测结果
$draw.yolo(yoloResults);
// 在指定图片上绘制 YOLO 检测结果
$draw.yolo(yoloResults, originalImage);控件节点绘制
将查找控件得到的UiObject对象到屏幕指定区域,暂时通过$draw.rect{绘制矩形区域函数}实现,后期考虑增加直接传入UiObject或UiCollection进行绘制。
var b = text("Bot.js").findOne().bounds();
toastLog("控件在屏幕上的范围为" + b);
$draw.rect(b, "#80FF00FF");图片绘制
$draw.image(image, left, top, width, height)
image{Bitmap|Image} 图片对象,可为原生Bitmap或images模块读取的Image对象left{number} 绘制区域左上角X坐标top{number} 绘制区域左上角Y坐标width{number} 图片绘制宽度height{number} 图片绘制高度
将图片绘制到屏幕指定区域,支持缩放适配绘制尺寸。
var img = images.read("./a.png");
$draw.image(img, 100, 100, 300, 200);$draw.image(image, rect)
image{Bitmap|Image} 图片对象,可为原生Bitmap或images模块读取的Image对象rect{Rect} Android原生Rect对象,指定绘制的区域(left, top, right, bottom)
通过Android原生Rect对象指定区域,将图片绘制到屏幕对应位置。
var img = images.read("./a.png");
var rect = new android.graphics.Rect(100, 100, 400, 300);
$draw.image(img, rect);清理绘制
$draw.clear([delay])
delay{number} 延迟清理时间,单位:毫秒,可选,默认立即清理 (异步执行)
异步清理当前屏幕上所有绘制内容,包含图形、图片、文字、日志等所有绘制对象,不阻塞脚本执行。
// 立即清理所有绘制
$draw.clear();
// 延迟2秒后清理所有绘制
$draw.clear(2000);$draw.clearSync()
同步清理当前屏幕上所有绘制内容,阻塞脚本执行,直到绘制内容完全清理完成后再继续后续代码。
// 同步清理全部绘制,确保清理完成后执行后续操作
$draw.clearSync();$draw.clearText([delay])
delay{number} 延迟清理时间,单位:毫秒,可选,默认立即清理 (异步执行)
异步仅清理屏幕上所有文本类型的绘制内容,包含$draw.text和所有日志绘制,保留图形、图片等绘制内容。
// 立即清理所有文本绘制
$draw.clearText();
// 延迟1秒后清理所有文本绘制
$draw.clearText(1000);$draw.clearTextSync()
同步仅清理屏幕上所有文本类型的绘制内容,阻塞脚本执行,直到文本绘制内容完全清理完成。
// 同步清理文本绘制,保留其他图形绘制
$draw.clearTextSync();资源释放
$draw.release()
释放当前绘制模块的所有资源,停止屏幕绘制服务,关闭绘制连接通道,回收Bitmap、绘制缓存等系统资源。
脚本不再需要绘制操作时建议主动调用,避免长期占用内存和系统资源,防止绘制服务残留导致异常。
// 脚本结束前释放绘制资源
$draw.release();注意事项
- 使用$draw模块必须先为应用开启悬浮窗权限/显示在其他应用的上层,华为手机另外需要开启后台弹窗权限,否则无法进行绘制
- 绘制悬浮层默认开启触摸事件穿透,不会影响底层应用的操作
- 实时循环绘制前建议先调用$draw.clear(),避免绘制内容叠加导致视觉混乱
- 脚本执行完毕或不再需要绘制时,务必调用$draw.release()释放资源
- 绘制坐标为屏幕像素坐标,需注意不同设备的分辨率适配问题
示例
// ==================== $draw 一页式完整示例 ====================
// 1️⃣ 清理绘制,保证初始状态
$draw.clear();
sleep(500);
// ==================== 点绘制 ====================
$draw.point(200, 300, colors.BLACK);
$draw.point(300, 300, colors.RED);
$draw.point(400, 300, "#00FF00");
$draw.point(200, 400, colors.BLUE, 2);
$draw.point(300, 400, "#FFA500", 5);
$draw.point(200, 500, colors.MAGENTA, 2, 20);
$draw.point(300, 500, "#80FF00FF", 5, 25);
$draw.point(300, 600, { color: "#80FF00FF", strokeWidth: 0, radius: 20 });
// ==================== 圆形绘制 ====================
$draw.circle(200, 300, colors.GREEN);
$draw.circle(300, 300, colors.RED);
$draw.circle(400, 300, "#00FF00");
$draw.circle(200, 400, colors.BLUE, 2);
$draw.circle(300, 400, "#FFA500", 10);
$draw.circle(200, 500, colors.MAGENTA, 2, 20);
$draw.circle(300, 500, "#80FF00FF", 10, 25);
$draw.circle(400, 600, { color: colors.MAGENTA, strokeWidth: 30, radius: 50 });
// ==================== 矩形绘制 ====================
$draw.rect(100, 200, 80, 50);
$draw.rect(300, 200, 100, 60, colors.RED, 6, 12);
$draw.rect(500, 200, 100, 60, colors.BLUE, 4, 16, "#8000FFFF");
$draw.rect(320, 580, 400, 660, { color: colors.MAGENTA, strokeWidth: 30, cornerRadius: 50, fillColor: "#80FFA500" });
// ==================== 十字准心 ====================
$draw.cross(200, 100);
$draw.cross(200, 200, colors.GREEN);
$draw.cross(300, 200, "#00FF00");
$draw.cross(400, 200, colors.RED, 4);
$draw.cross(200, 300, "#80FFA500", 6);
$draw.cross(300, 300, colors.BLUE, 4, 40);
$draw.cross(400, 300, "#FF00FFFF", 6, 50);
$draw.cross(200, 380, colors.MAGENTA, 2, 20);
$draw.cross(300, 380, "#8000FF00", 8, 60);
$draw.cross(320, 580, { color: colors.MAGENTA, strokeWidth: 30, length: 50 });
// ==================== 直线绘制 ====================
$draw.line(100, 100, 400, 100);
$draw.line(100, 150, 400, 150, colors.RED);
$draw.line(100, 200, 400, 200, "#00FF00");
$draw.line(100, 250, 400, 250, colors.BLUE, 6);
$draw.line(100, 300, 400, 300, "#80FFA500", 8);
$draw.line(100, 350, 400, 450, "#FF00FF", 4);
$draw.line(500, 100, 500, 400, colors.CYAN, 5);
// ==================== 路径绘制 ====================
$draw.path([[50,100],[150,130],[250,110],[350,140]], colors.RED);
$draw.path([[450,100],[550,160],[650,120],[750,180]], "#80FFA500");
$draw.path([[50,300],[120,360],[200,330],[280,390],[360,350]], colors.BLUE, 8);
$draw.path([[450,300],[520,340],[600,320],[680,380],[760,360]], "#80FF00FF", 12);
$draw.path([[200,500],[260,450],[320,520],[380,470],[440,540],[500,490]], colors.GREEN, 6);
// ==================== 文字绘制 ====================
$draw.text("Text-1 默认 size & 默认颜色", 100, 120);
$draw.text("Text-2 指定 size = 18", 100, 170, colors.BLUE, 18);
$draw.text("Text-3 size=22 + RED", 100, 230, colors.RED, 22);
$draw.text("Text-4 size=26 + #00FF00", 100, 300, "#00FF00", 26);
$draw.text("Text-5 半透明橙色 #80FFA500", 100, 380, "#80FFA500", 30);
$draw.text("Text-6 size=36 + #80FF00FF", 100, 470, "#80FF00FF", 36);
// ==================== 日志绘制 ====================
$draw.l("普通日志");
$draw.d("调试日志");
$draw.i("信息日志");
$draw.w("警告日志");
$draw.e("错误日志");
// 日志带坐标与大小
$draw.l("日志带坐标和大小", 100, 200, 24);
$draw.d("调试日志带坐标和大小", 140, 300, 22);
$draw.i("信息日志带坐标和大小", 160, 350, 24);
$draw.w("警告日志带坐标和大小", 180, 400, 26);
$draw.e("错误日志带坐标和大小", 200, 450, 28);
// ==================== 图片绘制 ====================
var img = images.read("./a.png");
$draw.image(img, 100, 100, 300, 200);
$draw.image(img, new android.graphics.Rect(400, 100, 600, 300));
// ==================== YOLO 绘制 ====================
$draw.yolo(yoloResults);//yoloResults是推理后的结果
// ==================== 清理绘制 ====================
$draw.clearText();
$draw.clearTextSync();
$draw.clear();
$draw.clearSync();
// ==================== 释放绘制资源 ====================
$draw.release();