屏幕自动点击器, 屏幕连点器,手机自动点击器【autojs】

简介: 提供三种点击模式:固定坐标点击、随机区域点击和录制回放功能

文章附件下载:https://www.pan38.com/dow/share.php?code=JCnzE 提取密码:8035

代码功能说明:
提供三种点击模式:固定坐标点击、随机区域点击和录制回放功能
可自定义点击次数、间隔时间和点击持续时间
支持实时坐标选取功能,可视化选择屏幕点击位置
录制功能可记录多个点击点并保存为文件
状态实时显示,包含运行进度和操作反馈
完整的开始/停止控制,可随时中断运行
采用多线程处理,避免UI卡顿
包含错误处理和参数校验机制

// 屏幕自动点击器 v2.0
// 功能:支持随机点击、固定坐标点击、录制回放三种模式

"ui";
ui.layout(



    <card cardCornerRadius="8" cardElevation="4" margin="0 0 16 0">
        <vertical padding="8">
            <text text="点击设置" textSize="18" textColor="#333"/>
            <horizontal>
                <text text="点击次数:" layout_weight="1"/>
                <input id="click_count" text="100" inputType="number" layout_weight="2"/>
            </horizontal>
            <horizontal>
                <text text="间隔(ms):" layout_weight="1"/>
                <input id="interval" text="500" inputType="number" layout_weight="2"/>
            </horizontal>
            <horizontal>
                <text text="点击时长(ms):" layout_weight="1"/>
                <input id="duration" text="50" inputType="number" layout_weight="2"/>
            </horizontal>
        </vertical>
    </card>

    <card id="fixed_card" cardCornerRadius="8" cardElevation="4" margin="0 0 16 0">
        <vertical padding="8">
            <text text="固定坐标设置" textSize="18" textColor="#333"/>
            <horizontal>
                <text text="X坐标:" layout_weight="1"/>
                <input id="x_pos" text="500" inputType="number" layout_weight="2"/>
            </horizontal>
            <horizontal>
                <text text="Y坐标:" layout_weight="1"/>
                <input id="y_pos" text="800" inputType="number" layout_weight="2"/>
            </horizontal>
            <button id="pick_pos" text="选取坐标" layout_weight="1"/>
        </vertical>
    </card>

    <card id="random_card" visibility="gone" cardCornerRadius="8" cardElevation="4" margin="0 0 16 0">
        <vertical padding="8">
            <text text="随机区域设置" textSize="18" textColor="#333"/>
            <horizontal>
                <text text="左上X:" layout_weight="1"/>
                <input id="left_x" text="100" inputType="number" layout_weight="2"/>
            </horizontal>
            <horizontal>
                <text text="左上Y:" layout_weight="1"/>
                <input id="top_y" text="200" inputType="number" layout_weight="2"/>
            </horizontal>
            <horizontal>
                <text text="右下X:" layout_weight="1"/>
                <input id="right_x" text="900" inputType="number" layout_weight="2"/>
            </horizontal>
            <horizontal>
                <text text="右下Y:" layout_weight="1"/>
                <input id="bottom_y" text="1600" inputType="number" layout_weight="2"/>
            </horizontal>
        </vertical>
    </card>

    <card id="record_card" visibility="gone" cardCornerRadius="8" cardElevation="4" margin="0 0 16 0">
        <vertical padding="8">
            <text text="录制回放" textSize="18" textColor="#333"/>
            <horizontal>
                <button id="record_btn" text="开始录制" layout_weight="1"/>
                <button id="save_btn" text="保存记录" layout_weight="1"/>
                <button id="load_btn" text="加载记录" layout_weight="1"/>
            </horizontal>
        </vertical>
    </card>

    <text id="status" text="状态: 待命" textSize="16" textColor="#666" gravity="center"/>
</vertical>

);

let running = false;
let mode = "fixed"; // fixed/random/record
let recordPoints = [];
let clickThread = null;

// 模式切换
ui.mode_btn.click(() => {
if (mode === "fixed") {
mode = "random";
ui.mode_btn.text("模式: 随机区域");
ui.fixed_card.setVisibility(View.GONE);
ui.random_card.setVisibility(View.VISIBLE);
ui.record_card.setVisibility(View.GONE);
} else if (mode === "random") {
mode = "record";
ui.mode_btn.text("模式: 录制回放");
ui.fixed_card.setVisibility(View.GONE);
ui.random_card.setVisibility(View.GONE);
ui.record_card.setVisibility(View.VISIBLE);
} else {
mode = "fixed";
ui.mode_btn.text("模式: 固定坐标");
ui.fixed_card.setVisibility(View.VISIBLE);
ui.random_card.setVisibility(View.GONE);
ui.record_card.setVisibility(View.GONE);
}
});

// 坐标选取
ui.pick_pos.click(() => {
toast("请在屏幕上点击选取坐标");
threads.start(function() {
let point = captureScreenAndPickPoint();
if (point) {
ui.run(() => {
ui.x_pos.text(point.x);
ui.y_pos.text(point.y);
});
}
});
});

// 开始点击
ui.start_btn.click(() => {
if (running) return;

running = true;
ui.status.text("状态: 运行中");
ui.start_btn.enabled = false;
ui.stop_btn.enabled = true;

let count = parseInt(ui.click_count.text()) || 100;
let interval = parseInt(ui.interval.text()) || 500;
let duration = parseInt(ui.duration.text()) || 50;

clickThread = threads.start(function() {
    if (mode === "fixed") {
        let x = parseInt(ui.x_pos.text()) || 500;
        let y = parseInt(ui.y_pos.text()) || 800;
        fixedClick(x, y, count, interval, duration);
    } else if (mode === "random") {
        let leftX = parseInt(ui.left_x.text()) || 100;
        let topY = parseInt(ui.top_y.text()) || 200;
        let rightX = parseInt(ui.right_x.text()) || 900;
        let bottomY = parseInt(ui.bottom_y.text()) || 1600;
        randomClick(leftX, topY, rightX, bottomY, count, interval, duration);
    } else if (mode === "record" && recordPoints.length > 0) {
        replayRecord(count, interval);
    }

    ui.run(() => {
        running = false;
        ui.status.text("状态: 已完成");
        ui.start_btn.enabled = true;
        ui.stop_btn.enabled = false;
    });
});

});

// 停止点击
ui.stop_btn.click(() => {
if (clickThread) {
clickThread.interrupt();
}
running = false;
ui.status.text("状态: 已停止");
ui.start_btn.enabled = true;
ui.stop_btn.enabled = false;
});

// 录制功能
ui.record_btn.click(() => {
if (ui.record_btn.text() === "开始录制") {
ui.record_btn.text("停止录制");
recordPoints = [];
toast("开始录制,点击屏幕记录坐标");
threads.start(function() {
while (ui.record_btn.text() === "停止录制") {
let point = captureScreenAndPickPoint(true);
if (point) {
recordPoints.push(point);
ui.run(() => {
ui.status.text("已记录: " + recordPoints.length + "个点");
});
}
sleep(100);
}
});
} else {
ui.record_btn.text("开始录制");
toast("录制停止,共记录" + recordPoints.length + "个点");
}
});

// 保存记录
ui.save_btn.click(() => {
if (recordPoints.length === 0) {
toast("没有录制数据");
return;
}

let filename = "click_record_" + new Date().getTime() + ".json";
files.write(filename, JSON.stringify(recordPoints));
toast("已保存到: " + filename);

});

// 加载记录
ui.load_btn.click(() => {
let path = files.path("");
let filesList = files.listDir(path, function(name) {
return name.endsWith(".json");
});

dialogs.select("选择记录文件", filesList)
    .then(file => {
        if (file) {
            let content = files.read(path + "/" + file);
            recordPoints = JSON.parse(content);
            toast("已加载" + recordPoints.length + "个点");
            ui.status.text("已加载: " + recordPoints.length + "个点");
        }
    });

});

// 固定坐标点击
function fixedClick(x, y, count, interval, duration) {
for (let i = 0; i < count && running; i++) {
press(x, y, duration);
sleep(interval);
ui.run(() => {
ui.status.text("状态: 运行中 (" + (i + 1) + "/" + count + ")");
});
}
}

// 随机区域点击
function randomClick(leftX, topY, rightX, bottomY, count, interval, duration) {
for (let i = 0; i < count && running; i++) {
let x = random(leftX, rightX);
let y = random(topY, bottomY);
press(x, y, duration);
sleep(interval);
ui.run(() => {
ui.status.text("状态: 运行中 (" + (i + 1) + "/" + count + ")");
});
}
}

// 回放录制
function replayRecord(count, interval) {
for (let i = 0; i < count && running; i++) {
for (let j = 0; j < recordPoints.length && running; j++) {
let point = recordPoints[j];
press(point.x, point.y, point.duration || 50);
sleep(interval);
ui.run(() => {
ui.status.text("回放: " + (i + 1) + "/" + count + " 点: " + (j + 1) + "/" + recordPoints.length);
});
}
}
}

// 屏幕取点
function captureScreenAndPickPoint(isRecording) {
let img = captureScreen();
let window = floaty.window(



);

let point = null;
window.img.setOnTouchListener(function(view, event) {
    if (event.getAction() === MotionEvent.ACTION_DOWN) {
        point = {
            x: event.getRawX(),
            y: event.getRawY(),
            duration: isRecording ? parseInt(ui.duration.text()) || 50 : null
        };
        window.close();
    }
    return true;
});

// 等待窗口关闭
while (window && window.getWindow() && window.getWindow().isShowing()) {
    sleep(200);
}
return point;

}

// 生成随机数
function random(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

相关文章
|
安全 数据安全/隐私保护
屏幕自动点击器, 手机自动点击器, 自动连点器屏幕【autojs】
完整UI界面:包含悬浮窗控制面板,支持拖动位置调整 核心功能:单点/连续点击、位置记录、任务执行与停止
|
人工智能 编解码 芯片
告别低效沟通|让技术提问不再头疼-这套高效AI提问模板来帮你
不会向ai提问,不知道怎么提问的 可以看看
21516 1
告别低效沟通|让技术提问不再头疼-这套高效AI提问模板来帮你
|
安全 数据安全/隐私保护
屏幕连点器, 自动连点器,手机自动点击器【autojs】
提供四种点击模式:单点、长按、滑动和随机区域点击
|
存储 弹性计算 固态存储
阿里云服务器收费价格参考,2核16G、4核32G、8核64G配置收费标准
阿里云服务器2核16G、4核32G、8核64G配置最新租用价格更新,2核16G配置按量收费最低收费标准为0.596元/小时,按月租用标准收费标准为286.2元/1月。4核32G配置的阿里云服务器按量收费标准最低为1.192元/小时。8核64G配置的阿里云服务器按量收费标准最低为2.385元/小时。云服务器实例规格的地域和实例规格不同,收费标准不一样,下面是2025年阿里云服务器2核16G、4核32G、8核64G配置的最新租用收费标准。
2564 55
|
12月前
|
NoSQL IDE MongoDB
Studio 3T 2025.17 (macOS, Linux, Windows) - MongoDB 的终极 GUI、IDE 和 客户端
Studio 3T 2025.17 (macOS, Linux, Windows) - MongoDB 的终极 GUI、IDE 和 客户端
612 1
Studio 3T 2025.17 (macOS, Linux, Windows) - MongoDB 的终极 GUI、IDE 和 客户端
|
XML JSON Java
Spring Boot添加消息转换器HttpMessageConverter
spring boot添加消息转换器HttpMessageConverter
3723 0
Spring Boot添加消息转换器HttpMessageConverter
|
NoSQL Redis Docker
Docker 安装 Redis
Docker 安装 Redis
547 2
|
数据采集 JSON 前端开发
设计稿转代码利器:Design2Code
【2月更文挑战第13天】设计稿转代码利器:Design2Code
1781 2
设计稿转代码利器:Design2Code