yjz-web-sdk 1.0.10 → 1.0.11-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +90 -0
- package/lib/ScreenControlUtil-D4-BTCo9.js +5230 -0
- package/lib/components/RemotePlayer/index.vue.d.ts +1 -73
- package/lib/composables/useCursorStyle.d.ts +1 -1
- package/lib/composables/useKeyboardControl.d.ts +5 -1
- package/lib/composables/useMouseTouchControl.d.ts +5 -4
- package/lib/composables/useRemoteVideo.d.ts +8 -25
- package/lib/composables/useResizeObserver.d.ts +1 -1
- package/lib/core/WebRTCSdk.d.ts +3 -0
- package/lib/core/data/WebRtcError.d.ts +3 -3
- package/lib/core/data/WebrtcDataType.d.ts +1 -11
- package/lib/core/groupctrl/SdkController.d.ts +2 -2
- package/lib/core/rtc/WebRTCClient.d.ts +13 -3
- package/lib/core/rtc/WebRTCConfig.d.ts +3 -1
- package/lib/core/rtc/WebRtcNegotiate.d.ts +3 -3
- package/lib/core/signal/SignalingClient.d.ts +1 -1
- package/lib/core/util/KeyCodeUtil.d.ts +6 -0
- package/lib/core/util/TurnTestUtil.d.ts +4 -4
- package/lib/index.d.ts +3 -3
- package/lib/uni/KeyboardControl.d.ts +53 -0
- package/lib/uni/Logger.d.ts +13 -0
- package/lib/uni/MouseTouchControl.d.ts +56 -0
- package/lib/uni/RemoteCanvasController.d.ts +11 -0
- package/lib/uni/RemoteController.d.ts +23 -0
- package/lib/uni/RemoteVideoController.d.ts +38 -0
- package/lib/uni/WebRTCWrapper.d.ts +57 -0
- package/lib/uni/constants.d.ts +42 -0
- package/lib/uni/index.d.ts +110 -0
- package/lib/{components/RemotePlayer → uni}/type.d.ts +1 -0
- package/lib/uni-sdk.js +1263 -0
- package/lib/yjz-web-sdk.js +312 -5955
- package/package.json +10 -20
- package/lib/core/data/TurnType.d.ts +0 -21
- package/lib/core/util/MapCache.d.ts +0 -20
- package/lib/render/Canvas2DRenderer.d.ts +0 -10
- package/lib/render/WebGLRenderer.d.ts +0 -16
- package/lib/render/WebGPURenderer.d.ts +0 -18
- package/lib/types/index.d.ts +0 -13
- package/lib/util/WasmUtil.d.ts +0 -17
- package/lib/worker/worker.d.ts +0 -1
- package/src/assets/icon/circle.svg +0 -1
- package/src/assets/icon/triangle.svg +0 -1
- package/src/assets/wasm/h264-atomic.wasm +0 -0
- package/src/assets/wasm/h264-simd.wasm +0 -0
- package/src/components/RemotePlayer/index.vue +0 -170
- package/src/components/RemotePlayer/type.ts +0 -11
- package/src/composables/useCursorStyle.ts +0 -15
- package/src/composables/useKeyboardControl.ts +0 -32
- package/src/composables/useMouseTouchControl.ts +0 -158
- package/src/composables/useRemoteVideo.ts +0 -248
- package/src/composables/useResizeObserver.ts +0 -27
- package/src/core/WebRTCSdk.ts +0 -561
- package/src/core/data/MessageType.ts +0 -70
- package/src/core/data/TurnType.ts +0 -25
- package/src/core/data/WebRtcError.ts +0 -93
- package/src/core/data/WebrtcDataType.ts +0 -354
- package/src/core/groupctrl/GroupCtrlSocketManager.ts +0 -94
- package/src/core/groupctrl/SdkController.ts +0 -96
- package/src/core/rtc/WebRTCClient.ts +0 -862
- package/src/core/rtc/WebRTCConfig.ts +0 -86
- package/src/core/rtc/WebRtcNegotiate.ts +0 -164
- package/src/core/signal/SignalingClient.ts +0 -221
- package/src/core/util/FileTypeUtils.ts +0 -75
- package/src/core/util/KeyCodeUtil.ts +0 -162
- package/src/core/util/Logger.ts +0 -83
- package/src/core/util/MapCache.ts +0 -135
- package/src/core/util/ScreenControlUtil.ts +0 -174
- package/src/core/util/TurnTestUtil.ts +0 -123
- package/src/env.d.ts +0 -30
- package/src/index.ts +0 -61
- package/src/render/Canvas2DRenderer.ts +0 -38
- package/src/render/WebGLRenderer.ts +0 -150
- package/src/render/WebGPURenderer.ts +0 -194
- package/src/types/index.ts +0 -15
- package/src/types/webgpu.d.ts +0 -1158
- package/src/util/WasmUtil.ts +0 -291
- package/src/worker/worker.ts +0 -292
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yjz-web-sdk",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.0.10",
|
|
4
|
+
"version": "1.0.11-beta.10",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "针对于亚矩阵项目的云手机投屏和屏幕控制",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -11,19 +11,17 @@
|
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
13
|
"import": "./lib/yjz-web-sdk.js",
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
"types": "./lib/index.d.ts"
|
|
15
|
+
},
|
|
16
|
+
"./uni-sdk": {
|
|
17
|
+
"import": "./lib/uni-sdk.js",
|
|
18
|
+
"types": "./lib/uni/index.d.ts"
|
|
18
19
|
}
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
21
22
|
"package.json",
|
|
22
23
|
"README.md",
|
|
23
|
-
"lib"
|
|
24
|
-
"dist",
|
|
25
|
-
"src",
|
|
26
|
-
"types"
|
|
24
|
+
"lib"
|
|
27
25
|
],
|
|
28
26
|
"publishConfig": {
|
|
29
27
|
"registry": "https://registry.npmjs.org",
|
|
@@ -35,13 +33,6 @@
|
|
|
35
33
|
"preview": "vite preview"
|
|
36
34
|
},
|
|
37
35
|
"dependencies": {
|
|
38
|
-
"@libmedia/avcodec": "1.0.1",
|
|
39
|
-
"@libmedia/avformat": "1.0.1",
|
|
40
|
-
"@libmedia/avnetwork": "1.0.1",
|
|
41
|
-
"@libmedia/avrender": "1.0.1",
|
|
42
|
-
"@libmedia/avutil": "1.0.1",
|
|
43
|
-
"@libmedia/cheap": "~1.0.2",
|
|
44
|
-
"@libmedia/common": "~2.0.1",
|
|
45
36
|
"element-plus": "^2.10.5",
|
|
46
37
|
"eventemitter3": "^5.0.1",
|
|
47
38
|
"terser": "^5.39.0",
|
|
@@ -49,12 +40,11 @@
|
|
|
49
40
|
"webrtc-adapter": "^9.0.1"
|
|
50
41
|
},
|
|
51
42
|
"devDependencies": {
|
|
52
|
-
"@libmedia/rollup-plugin-typescript": "^12.2.4",
|
|
53
43
|
"@types/node": "^22.14.1",
|
|
54
|
-
"@vitejs/plugin-vue": "^
|
|
44
|
+
"@vitejs/plugin-vue": "^5.2.1",
|
|
55
45
|
"@vue/tsconfig": "^0.7.0",
|
|
56
|
-
"
|
|
57
|
-
"typescript": "~5.
|
|
46
|
+
"rollup-plugin-visualizer": "5.9.3",
|
|
47
|
+
"typescript": "~5.7.2",
|
|
58
48
|
"vite": "^6.2.0",
|
|
59
49
|
"vite-plugin-css-injected-by-js": "3.3.1",
|
|
60
50
|
"vite-plugin-dts": "3.6.3",
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export type TurnServerConfig = {
|
|
2
|
-
urls: string;
|
|
3
|
-
username?: string;
|
|
4
|
-
credential?: string;
|
|
5
|
-
};
|
|
6
|
-
export interface TurnTestResult extends TurnServerConfig {
|
|
7
|
-
rtt: number;
|
|
8
|
-
}
|
|
9
|
-
export type PublicTurnTestResult = {
|
|
10
|
-
urls: string;
|
|
11
|
-
rtt: number;
|
|
12
|
-
};
|
|
13
|
-
export type TurnTestSummary = {
|
|
14
|
-
best?: PublicTurnTestResult;
|
|
15
|
-
all: PublicTurnTestResult[];
|
|
16
|
-
};
|
|
17
|
-
export interface TurnSelectionResult {
|
|
18
|
-
url?: string;
|
|
19
|
-
rtt?: number;
|
|
20
|
-
error?: string;
|
|
21
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare class MapCache {
|
|
2
|
-
private key;
|
|
3
|
-
private maxSize;
|
|
4
|
-
private defaultExpire;
|
|
5
|
-
constructor(key: string, maxSize?: number, expireMs?: number);
|
|
6
|
-
/** 从 localStorage 读取 Map(自动清理过期的 item) */
|
|
7
|
-
getMap(): Map<string, any>;
|
|
8
|
-
/** 保存 Map(每个值都有独立的 timestamp/expire) */
|
|
9
|
-
private saveMap;
|
|
10
|
-
/** 设置值(支持单项自定义过期时间) */
|
|
11
|
-
set(key: string, value: any, expireMs?: number): void;
|
|
12
|
-
/** 获取值(单项过期会自动清除) */
|
|
13
|
-
get(key: string): any;
|
|
14
|
-
/** 检查是否存在且未过期 */
|
|
15
|
-
has(key: string): boolean;
|
|
16
|
-
/** 删除 */
|
|
17
|
-
delete(key: string): void;
|
|
18
|
-
/** 清空 */
|
|
19
|
-
clear(): void;
|
|
20
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export declare class WebGLRenderer {
|
|
2
|
-
private canvas;
|
|
3
|
-
private ctx;
|
|
4
|
-
private program;
|
|
5
|
-
private texture;
|
|
6
|
-
private vertexBuffer;
|
|
7
|
-
static vertexShaderSource: string;
|
|
8
|
-
static fragmentShaderSource: string;
|
|
9
|
-
constructor(type: "webgl" | "webgl2", canvas: HTMLCanvasElement | OffscreenCanvas);
|
|
10
|
-
private createProgram;
|
|
11
|
-
render(frame: VideoFrame): void;
|
|
12
|
-
/** 清空画布,但不销毁资源 */
|
|
13
|
-
clear(): void;
|
|
14
|
-
/** 销毁 WebGLRenderer,释放所有资源 */
|
|
15
|
-
destroy(): void;
|
|
16
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export declare class WebGPURenderer {
|
|
2
|
-
private canvas;
|
|
3
|
-
private ctx;
|
|
4
|
-
private started;
|
|
5
|
-
private format;
|
|
6
|
-
private device;
|
|
7
|
-
private pipeline;
|
|
8
|
-
private sampler;
|
|
9
|
-
static vertexShaderSource: string;
|
|
10
|
-
static fragmentShaderSource: string;
|
|
11
|
-
constructor(canvas: HTMLCanvasElement | OffscreenCanvas);
|
|
12
|
-
start(): Promise<void>;
|
|
13
|
-
render(frame: VideoFrame | HTMLVideoElement | HTMLCanvasElement | HTMLImageElement): Promise<void>;
|
|
14
|
-
/** 清空画布 */
|
|
15
|
-
clear(): Promise<void>;
|
|
16
|
-
/** 销毁 WebGPURenderer,释放所有 GPU 资源 */
|
|
17
|
-
destroy(): void;
|
|
18
|
-
}
|
package/lib/types/index.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export interface RenderingCapabilities {
|
|
2
|
-
webgpu: boolean;
|
|
3
|
-
webgl2: boolean;
|
|
4
|
-
webgl1: boolean;
|
|
5
|
-
canvas2d: boolean;
|
|
6
|
-
best: RendererType;
|
|
7
|
-
}
|
|
8
|
-
export type RendererType = 'webgpu' | 'webgl2' | 'webgl1' | 'canvas2d' | 'none';
|
|
9
|
-
export interface DecoderSupportResult {
|
|
10
|
-
supported: boolean;
|
|
11
|
-
hardware: boolean;
|
|
12
|
-
software: boolean;
|
|
13
|
-
}
|
package/lib/util/WasmUtil.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { AVCodecID } from "@libmedia/avutil";
|
|
2
|
-
import { DecoderSupportResult, RenderingCapabilities } from "../types";
|
|
3
|
-
export declare function getWasm(codecId?: AVCodecID): string;
|
|
4
|
-
export declare enum VideoCodecType {
|
|
5
|
-
H264 = "h264",
|
|
6
|
-
H265 = "h265",
|
|
7
|
-
VP8 = "vp8",
|
|
8
|
-
VP9 = "vp9",
|
|
9
|
-
AV1 = "av1"
|
|
10
|
-
}
|
|
11
|
-
export declare function checkDecoderSupport(codec: VideoCodecType): Promise<DecoderSupportResult>;
|
|
12
|
-
export declare function isEncoderSupported(codec: VideoCodecType): Promise<boolean>;
|
|
13
|
-
export declare const isWebGPUSupported: () => Promise<boolean>;
|
|
14
|
-
export declare const isWebGL2Supported: (canvas?: HTMLCanvasElement) => boolean;
|
|
15
|
-
export declare const isWebGL1Supported: (canvas?: HTMLCanvasElement) => boolean;
|
|
16
|
-
export declare const isCanvas2DSupported: (canvas?: HTMLCanvasElement) => boolean;
|
|
17
|
-
export declare const detectRenderingCapabilities: () => Promise<RenderingCapabilities>;
|
package/lib/worker/worker.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><circle cx="12" cy="12" r="12" fill="#fff" opacity=".6"/><circle cx="12" cy="12" r="10" fill="#000" opacity=".6"/></svg>
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="22" height="22"><path d="M143.832313 5.834982H143.686438A108.676545 108.676545 0 0 0 5.834982 143.686438l34.499333-11.815839-34.499333 11.815839 0.072938 0.218812 0.145874 0.437624 0.583498 1.750494 2.333993 6.71023 8.752474 25.528047L49.232663 269.867929a2254749.467572 2254749.467572 0 0 1 223.917444 652.351017l9.335972 27.205605 2.552804 7.585476 0.729373 2.188119a72.572592 72.572592 0 0 0 126.181491 40.844876 72.134968 72.134968 0 0 0 14.076895-18.963693c3.282178-6.41848 5.689108-13.639271 8.023101-20.3495l0.072937-0.291749 72.572592-209.329989 47.409231-136.830334 15.53564-44.710551 0.145874-0.364687 0.510561-0.145874 45.002301-15.900327 137.486769-48.649165c99.340573-35.228705 202.984445-71.989094 209.913487-74.906584l3.355115-1.312871c8.023101-3.136303 22.391744-8.606599 33.915834-20.130689a72.499655 72.499655 0 0 0 0-102.549813L999.240712 304.877823c-1.823432-1.969307-7.293728-7.731351-13.274585-11.961714a89.056417 89.056417 0 0 0-27.205605-12.3264h-0.145874l-2.552805-0.875247L948.184617 277.161657l-27.86204-9.263034-94.672588-31.800653A405018.007245 405018.007245 0 0 1 268.919745 48.138604L178.039896 17.504947 152.657723 8.752473 145.874556 6.637292 144.196999 5.90792 143.832313 5.834982z" fill="#000000" opacity=".7"></path></svg>
|
|
Binary file
|
|
Binary file
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
<script setup lang="ts">
|
|
2
|
-
import {ref, onMounted, toRefs, onBeforeUnmount} from 'vue'
|
|
3
|
-
|
|
4
|
-
import useCursorStyle from '../../composables/useCursorStyle'
|
|
5
|
-
import useResizeObserver from '../../composables/useResizeObserver'
|
|
6
|
-
import useRemoteVideo from '../../composables/useRemoteVideo'
|
|
7
|
-
import useMouseTouchControl from '../../composables/useMouseTouchControl'
|
|
8
|
-
import useKeyboardControl from '../../composables/useKeyboardControl'
|
|
9
|
-
import type {Dimension} from "./type";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const emit = defineEmits(['channelEvent', "groupControlEvent", 'loadedSuccess', 'loadedFailure']);
|
|
14
|
-
|
|
15
|
-
interface Props {
|
|
16
|
-
streamAngle?: number
|
|
17
|
-
videoAngle?: number
|
|
18
|
-
cursorType?: number
|
|
19
|
-
cloudDeviceSize?: Dimension
|
|
20
|
-
disabled?: boolean,
|
|
21
|
-
bgColor?: string,
|
|
22
|
-
isGroup?: boolean,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const props = withDefaults(defineProps<Props>(), {
|
|
26
|
-
streamAngle: 0,
|
|
27
|
-
videoAngle: 0,
|
|
28
|
-
cursorType: 0,
|
|
29
|
-
cloudDeviceSize: () => ({ width: 0, height: 0 }),
|
|
30
|
-
disabled: true,
|
|
31
|
-
bgColor: 'transparent',
|
|
32
|
-
isGroup: false
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
const { streamAngle, videoAngle, cursorType, cloudDeviceSize, disabled, bgColor, isGroup } = toRefs(props)
|
|
36
|
-
|
|
37
|
-
const videoContainer = ref<HTMLElement | null>(null)
|
|
38
|
-
const remoteVideoElement = ref<HTMLCanvasElement | null>(null)
|
|
39
|
-
const audioElement = ref<HTMLAudioElement | null>(null)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const cursorClass = useCursorStyle(cursorType)
|
|
43
|
-
|
|
44
|
-
const {
|
|
45
|
-
videoSize,
|
|
46
|
-
dimensions,
|
|
47
|
-
widthRadio,
|
|
48
|
-
initVideoContainer,
|
|
49
|
-
startDecode,
|
|
50
|
-
stopPlay,
|
|
51
|
-
startPlay
|
|
52
|
-
} = useRemoteVideo(videoContainer, remoteVideoElement, audioElement, videoAngle, emit)
|
|
53
|
-
|
|
54
|
-
const {
|
|
55
|
-
handleMouseDown,
|
|
56
|
-
handleMouseMove,
|
|
57
|
-
handleMouseEnter,
|
|
58
|
-
handleMouseUp,
|
|
59
|
-
handleMouseLeave,
|
|
60
|
-
handleWheel
|
|
61
|
-
} = useMouseTouchControl({
|
|
62
|
-
remoteVideoElement,
|
|
63
|
-
cloudDeviceSize,
|
|
64
|
-
streamAngle,
|
|
65
|
-
videoAngle,
|
|
66
|
-
widthRadio,
|
|
67
|
-
isGroup,
|
|
68
|
-
emit
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
const {
|
|
72
|
-
startListening,
|
|
73
|
-
stopListening
|
|
74
|
-
} = useKeyboardControl(disabled, emit)
|
|
75
|
-
|
|
76
|
-
useResizeObserver(videoContainer, dimensions)
|
|
77
|
-
|
|
78
|
-
const handleClick = () => {
|
|
79
|
-
if (audioElement.value) {
|
|
80
|
-
audioElement.value.muted = false;
|
|
81
|
-
audioElement.value.play().catch(()=>{});
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
onMounted(() => {
|
|
86
|
-
document.addEventListener("click", handleClick);
|
|
87
|
-
initVideoContainer()
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
onBeforeUnmount(() => {
|
|
93
|
-
document.removeEventListener("click", handleClick);
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
defineExpose({ startDecode, stopPlay, remoteVideoElement, startPlay })
|
|
97
|
-
</script>
|
|
98
|
-
|
|
99
|
-
<template>
|
|
100
|
-
<div ref="videoContainer" class="flex flex-1 items-center justify-center" style="width:100%;height: 100%;position:relative;overflow:hidden">
|
|
101
|
-
<div ref="keyboardArea" @pointerenter="startListening" @pointerleave="stopListening"
|
|
102
|
-
class="vContainer"
|
|
103
|
-
:style="{height: videoSize.height + 'px', width: videoSize.width + 'px', transform: `rotate(${videoAngle}deg)`}" style="position: relative;overflow:hidden">
|
|
104
|
-
<canvas ref="remoteVideoElement"
|
|
105
|
-
class="canvas-control"
|
|
106
|
-
:width="cloudDeviceSize.width"
|
|
107
|
-
:height="cloudDeviceSize.height"
|
|
108
|
-
:class="[cursorClass, { 'no-events': disabled }]"
|
|
109
|
-
@pointerenter="handleMouseEnter"
|
|
110
|
-
@pointerdown="handleMouseDown"
|
|
111
|
-
@pointermove="handleMouseMove"
|
|
112
|
-
@pointerup="handleMouseUp"
|
|
113
|
-
@pointerleave="handleMouseLeave"
|
|
114
|
-
@wheel="handleWheel"
|
|
115
|
-
hidden="hidden"
|
|
116
|
-
:style="{backgroundColor: `${bgColor}`}"></canvas>
|
|
117
|
-
<audio ref="audioElement" autoplay playsinline muted style="display: none"></audio>
|
|
118
|
-
</div>
|
|
119
|
-
</div>
|
|
120
|
-
</template>
|
|
121
|
-
|
|
122
|
-
<style scoped>
|
|
123
|
-
.vContainer {
|
|
124
|
-
transition: transform 0.2s linear;
|
|
125
|
-
transform-origin: center center;
|
|
126
|
-
margin: 0; /* 清除外边距 */
|
|
127
|
-
overflow: hidden;
|
|
128
|
-
/* 对频繁旋转或缩放使用 translateZ(0) 强制 GPU 合成 */
|
|
129
|
-
transform: translateZ(0);
|
|
130
|
-
will-change: transform; /* 告诉浏览器只关注 transform 变化 */
|
|
131
|
-
}
|
|
132
|
-
.flex {
|
|
133
|
-
display: flex;
|
|
134
|
-
}
|
|
135
|
-
.flex-1 {
|
|
136
|
-
flex: 1 1 0;
|
|
137
|
-
}
|
|
138
|
-
.items-center {
|
|
139
|
-
align-items: center;
|
|
140
|
-
}
|
|
141
|
-
.justify-center {
|
|
142
|
-
justify-content: center;
|
|
143
|
-
}
|
|
144
|
-
.canvas-control {
|
|
145
|
-
width: 100%;
|
|
146
|
-
height: 100%;
|
|
147
|
-
display: block;
|
|
148
|
-
user-select: none;
|
|
149
|
-
-webkit-user-drag: none;
|
|
150
|
-
touch-action: none;
|
|
151
|
-
|
|
152
|
-
object-fit: cover;
|
|
153
|
-
|
|
154
|
-
backface-visibility: hidden;
|
|
155
|
-
transform: translateZ(0);
|
|
156
|
-
clip-path: inset(0 1px);
|
|
157
|
-
}
|
|
158
|
-
.circle-cursor {
|
|
159
|
-
cursor: url('../../assets/icon/circle.svg') 12 12, auto;
|
|
160
|
-
}
|
|
161
|
-
.triangle-cursor {
|
|
162
|
-
cursor: url('../../assets/icon/triangle.svg') 1 1, auto;
|
|
163
|
-
}
|
|
164
|
-
.default-cursor {
|
|
165
|
-
cursor: default;
|
|
166
|
-
}
|
|
167
|
-
.no-events {
|
|
168
|
-
pointer-events: none !important;
|
|
169
|
-
}
|
|
170
|
-
</style>
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type {Ref} from 'vue'
|
|
2
|
-
import {computed} from 'vue'
|
|
3
|
-
|
|
4
|
-
export default function useCursorStyle(cursorType: Ref<number>) {
|
|
5
|
-
return computed(() => {
|
|
6
|
-
switch (cursorType.value) {
|
|
7
|
-
case 1:
|
|
8
|
-
return 'circle-cursor'
|
|
9
|
-
case 2:
|
|
10
|
-
return 'triangle-cursor'
|
|
11
|
-
default:
|
|
12
|
-
return 'default-cursor'
|
|
13
|
-
}
|
|
14
|
-
})
|
|
15
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import {ChannelDataType, KeyEventData} from "../core/data/WebrtcDataType";
|
|
2
|
-
import {getKeyEventData} from "../core/util/KeyCodeUtil";
|
|
3
|
-
import {type Ref, ref} from "vue";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export default function useKeyboardControl(
|
|
7
|
-
disabled:Ref<boolean>,
|
|
8
|
-
emit: (event: 'channelEvent', payload: ChannelDataType, data:any) => void
|
|
9
|
-
) {
|
|
10
|
-
const listening = ref(false)
|
|
11
|
-
const handleKeyDown = (e: KeyboardEvent) => {
|
|
12
|
-
const data: KeyEventData = getKeyEventData(e)
|
|
13
|
-
emit('channelEvent', ChannelDataType.ActionInput, data)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const startListening = () => {
|
|
17
|
-
if (!disabled){return}
|
|
18
|
-
listening.value = true;
|
|
19
|
-
document.addEventListener('keydown', handleKeyDown);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const stopListening = () => {
|
|
23
|
-
if (!disabled){return}
|
|
24
|
-
listening.value = false;
|
|
25
|
-
document.removeEventListener('keydown', handleKeyDown);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return {
|
|
29
|
-
startListening,
|
|
30
|
-
stopListening
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import type {Ref} from 'vue'
|
|
2
|
-
import {ref} from 'vue'
|
|
3
|
-
import {ActionType, ChannelDataType, TouchData, WheelData} from "../core/data/WebrtcDataType";
|
|
4
|
-
import {transformCoordinate, valueToPercentage} from "../core/util/ScreenControlUtil";
|
|
5
|
-
import type {Dimension, TouchEventData} from "../components/RemotePlayer/type";
|
|
6
|
-
|
|
7
|
-
interface MouseTouchControlOptions {
|
|
8
|
-
remoteVideoElement: Ref<HTMLCanvasElement | null>
|
|
9
|
-
cloudDeviceSize:Ref<Dimension>
|
|
10
|
-
streamAngle: Ref<number>
|
|
11
|
-
videoAngle: Ref<number>
|
|
12
|
-
widthRadio: Ref<number>
|
|
13
|
-
isGroup: Ref<boolean>
|
|
14
|
-
emit: (event: 'channelEvent', payload: ChannelDataType, data: any) => void
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export default function useMouseTouchControl(options: MouseTouchControlOptions) {
|
|
18
|
-
const {
|
|
19
|
-
remoteVideoElement,
|
|
20
|
-
cloudDeviceSize,
|
|
21
|
-
streamAngle,
|
|
22
|
-
videoAngle,
|
|
23
|
-
widthRadio,
|
|
24
|
-
isGroup,
|
|
25
|
-
emit
|
|
26
|
-
} = options
|
|
27
|
-
|
|
28
|
-
const isPointerDown = ref(false)
|
|
29
|
-
const bound = ref(0)
|
|
30
|
-
const pointerList = ref<number[]>(new Array(20).fill(0));
|
|
31
|
-
const pointerDownTime = ref<number[]>(new Array(10).fill(0));
|
|
32
|
-
const index = ref<number>(0)
|
|
33
|
-
const groupIndex = ref<number>(0)
|
|
34
|
-
|
|
35
|
-
const handlePointerEvent = (event: PointerEvent | TouchEventData, action: ActionType) => {
|
|
36
|
-
if (!remoteVideoElement.value) return;
|
|
37
|
-
const offsetTime = Math.trunc((event.timeStamp - pointerDownTime.value[0]));
|
|
38
|
-
const rect = remoteVideoElement.value.getBoundingClientRect();
|
|
39
|
-
|
|
40
|
-
let x = event.clientX - rect.left;
|
|
41
|
-
let y = event.clientY - rect.top;
|
|
42
|
-
|
|
43
|
-
const cloudWidth = cloudDeviceSize.value.width;
|
|
44
|
-
const cloudHeight = cloudDeviceSize.value.height;
|
|
45
|
-
const result = transformCoordinate(
|
|
46
|
-
rect.width, rect.height, cloudWidth, cloudHeight,
|
|
47
|
-
videoAngle.value, streamAngle.value, x, y
|
|
48
|
-
);
|
|
49
|
-
if (!result || result.length < 2) return;
|
|
50
|
-
x = result[0];
|
|
51
|
-
y = result[1];
|
|
52
|
-
|
|
53
|
-
if (action === ActionType.ACTION_MOVE) {
|
|
54
|
-
const flipY = pointerList.value[10] - y;
|
|
55
|
-
const flipX = pointerList.value[0] - x;
|
|
56
|
-
if (Math.abs(flipY) < bound.value && Math.abs(flipX) < bound.value) return;
|
|
57
|
-
}
|
|
58
|
-
if (isGroup.value) {
|
|
59
|
-
if(action === ActionType.ACTION_DOWN){
|
|
60
|
-
index.value = 0
|
|
61
|
-
groupIndex.value ++
|
|
62
|
-
}else if(action === ActionType.ACTION_UP || action === ActionType.ACTION_MOVE){
|
|
63
|
-
index.value ++
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
// 更新最后一次位置
|
|
67
|
-
pointerList.value[0] = x
|
|
68
|
-
pointerList.value[10] = y
|
|
69
|
-
|
|
70
|
-
// 转换为百分比坐标
|
|
71
|
-
const [px, py] = valueToPercentage(
|
|
72
|
-
rect.width, rect.height, cloudWidth, cloudHeight,
|
|
73
|
-
videoAngle.value, streamAngle.value, x, y
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
// 构造发送数据
|
|
77
|
-
const touchData = isGroup.value
|
|
78
|
-
? new TouchData(action, 0, px, py, offsetTime, "web", index.value, groupIndex.value)
|
|
79
|
-
: new TouchData(action, 0, px, py, offsetTime, "web")
|
|
80
|
-
|
|
81
|
-
emit('channelEvent', ChannelDataType.ClickData, touchData)
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const handleMouseDown = (event: PointerEvent) => {
|
|
86
|
-
// 标记按下状态
|
|
87
|
-
isPointerDown.value = true
|
|
88
|
-
if(remoteVideoElement.value){
|
|
89
|
-
remoteVideoElement.value.setPointerCapture(event.pointerId)
|
|
90
|
-
}
|
|
91
|
-
pointerDownTime.value[0] = event.timeStamp;
|
|
92
|
-
bound.value = Math.trunc(6 / widthRadio.value);
|
|
93
|
-
// 群控模式下新一轮点击重置 index
|
|
94
|
-
handlePointerEvent(event, ActionType.ACTION_DOWN)
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const handleMouseMove = (event: PointerEvent) => {
|
|
98
|
-
if (!isPointerDown.value) return;
|
|
99
|
-
handlePointerEvent(event, ActionType.ACTION_MOVE)
|
|
100
|
-
if(!remoteVideoElement.value){
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const rect = remoteVideoElement.value.getBoundingClientRect();
|
|
104
|
-
const { clientX: x, clientY: y } = event;
|
|
105
|
-
if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) {
|
|
106
|
-
handleMouseUp(event)
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const handleMouseUp = (event: PointerEvent) => {
|
|
111
|
-
if (!isPointerDown.value) return;
|
|
112
|
-
isPointerDown.value = false
|
|
113
|
-
handlePointerEvent(event, ActionType.ACTION_UP)
|
|
114
|
-
// 释放指针捕获 & 清除长按
|
|
115
|
-
if(remoteVideoElement.value){
|
|
116
|
-
remoteVideoElement.value.releasePointerCapture(event.pointerId)
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const handleMouseEnter = (event: PointerEvent) => {
|
|
121
|
-
// 如果左键已按下且尚未标记为 down,就补发一次 down
|
|
122
|
-
if (event.buttons === 1 && !isPointerDown.value) {
|
|
123
|
-
isPointerDown.value = true
|
|
124
|
-
if(remoteVideoElement.value){
|
|
125
|
-
remoteVideoElement.value.setPointerCapture(event.pointerId)
|
|
126
|
-
}
|
|
127
|
-
pointerDownTime.value[0] = event.timeStamp;
|
|
128
|
-
bound.value = Math.trunc(6 / widthRadio.value);
|
|
129
|
-
|
|
130
|
-
handlePointerEvent(event, ActionType.ACTION_DOWN)
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
const handleMouseLeave = (event: PointerEvent) => {
|
|
134
|
-
if (isPointerDown.value) {
|
|
135
|
-
handlePointerEvent(event, ActionType.ACTION_UP);
|
|
136
|
-
isPointerDown.value = false
|
|
137
|
-
if(remoteVideoElement.value){
|
|
138
|
-
remoteVideoElement.value.releasePointerCapture(event.pointerId)
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
const handleWheel = (e: WheelEvent) => {
|
|
144
|
-
const delta = Math.sign(e.deltaY) * -1;
|
|
145
|
-
const wheelData = new WheelData(delta);
|
|
146
|
-
emit('channelEvent', ChannelDataType.ActionWheel,wheelData)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return {
|
|
150
|
-
isPointerDown,
|
|
151
|
-
handleMouseDown,
|
|
152
|
-
handleMouseMove,
|
|
153
|
-
handleMouseEnter,
|
|
154
|
-
handleMouseUp,
|
|
155
|
-
handleMouseLeave,
|
|
156
|
-
handleWheel
|
|
157
|
-
}
|
|
158
|
-
}
|