Files
tkAiPage/src/composables/useCanvasPointer.js
2025-08-14 19:52:34 +08:00

79 lines
3.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/composables/useCanvasPointer.js
import { ref } from "vue";
/**
* @param {{ phone, toBuffer, getWs: (index:number)=>WebSocket|null }} deps
* 依赖项对象包含手机信息、缓冲转换和WebSocket获取函数
*/
export function useCanvasPointer(deps) {
const { phone, toBuffer, getWs } = deps;
const canvasRef = ref({}); // { [udid]: HTMLCanvasElement } - 存储设备ID到Canvas元素的映射
const frameMeta = ref({}); // { [udid]: { w,h, rotation? } } - 存储设备ID到帧元数据的映射
/**
* 初始化画布
* @param {string} udid - 设备唯一标识符
*/
function initCanvas(udid) {
const canvas = canvasRef.value[udid];
if (!canvas) return;
const dpr = window.devicePixelRatio || 1; // 获取设备像素比
// 设置画布样式尺寸
canvas.style.width = `${phone.value.width * 1.4}px`;
canvas.style.height = `${phone.value.height * 1.4}px`;
// 设置画布实际像素尺寸
canvas.width = phone.value.width * 1.4 * dpr;
canvas.height = phone.value.height * 1.4 * dpr;
const ctx = canvas.getContext("2d");
ctx.scale(dpr, dpr);
// 可选:参考网格(已设为透明)
ctx.strokeStyle = "#ffffff00";
for (let x = 0; x <= phone.value.width; x += 100) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, phone.value.height);
ctx.stroke();
}
}
function getCanvasCoordinate(event, udid) {
const canvas = canvasRef.value[udid];
const rect = canvas.getBoundingClientRect();
const rx = (event.clientX - rect.left) / rect.width;
const ry = (event.clientY - rect.top) / rect.height;
const meta = frameMeta.value[udid] || { w: 320, h: 720, rotation: 0 };
let x = rx * meta.w;
let y = ry * meta.h;
switch (meta.rotation ?? 0) {
case 90: [x, y] = [meta.w - y, x]; break;
case 180: [x, y] = [meta.w - x, meta.h - y]; break;
case 270: [x, y] = [y, meta.h - x]; break;
}
x = Math.max(0, Math.min(meta.w - 1, x));
y = Math.max(0, Math.min(meta.h - 1, y));
return { x: Math.round(x), y: Math.round(y), w: meta.w, h: meta.h };
}
// 统一发包point 用帧坐标screenSize 用帧宽高
function sendPointer(udid, index, action /* 0 down,1 up,2 move */, x, y) {
const meta = frameMeta.value[udid] || { w: 320, h: 720, rotation: 0 };
const payload = {
type: 2,
action,
pointerId: 0,
position: { point: { x, y }, screenSize: { width: meta.w, height: meta.h } },
pressure: action === 1 ? 0 : 1,
buttons: action === 1 ? 0 : 1,
};
const ws = getWs(index);
if (ws && ws.readyState === WebSocket.OPEN) {
ws.send(toBuffer(payload));
}
}
return { canvasRef, frameMeta, initCanvas, getCanvasCoordinate, sendPointer };
}