@ray-js/robot-map 0.0.2-beta-3 → 0.0.2-beta-5

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.
@@ -0,0 +1,230 @@
1
+ import "core-js/modules/esnext.iterator.constructor.js";
2
+ import "core-js/modules/esnext.iterator.for-each.js";
3
+ import "core-js/modules/esnext.iterator.map.js";
4
+ import "core-js/modules/web.dom-collections.iterator.js";
5
+ /* eslint-disable func-names */
6
+ import Render from './index.rjs';
7
+ import { MAP_API_METHODS, MAP_CALLBACK_METHODS } from '@ray-js/robot-map-sdk';
8
+ const componentOptions = {
9
+ options: {
10
+ pureDataPattern: /^init$/
11
+ },
12
+ data: {
13
+ initialized: false,
14
+ mapApi: null
15
+ },
16
+ properties: {
17
+ path: {
18
+ type: String,
19
+ observer: function (newValue, oldValue) {
20
+ if (newValue !== oldValue && this.data.initialized && this.render) {
21
+ this.render.onReceivePath(newValue);
22
+ }
23
+ }
24
+ },
25
+ map: {
26
+ type: String,
27
+ observer: function (newValue, oldValue) {
28
+ if (newValue !== oldValue && this.data.initialized && this.render) {
29
+ this.render.onReceiveMap(newValue);
30
+ }
31
+ }
32
+ },
33
+ roomProperties: {
34
+ type: Array,
35
+ observer: function (newValue, oldValue) {
36
+ if (newValue !== oldValue && this.data.initialized && this.render) {
37
+ this.render.onReceiveRoomProperties(newValue);
38
+ }
39
+ }
40
+ },
41
+ forbiddenSweepZones: {
42
+ type: Array,
43
+ observer: function (newValue, oldValue) {
44
+ if (newValue !== oldValue && this.data.initialized && this.render) {
45
+ this.render.onReceiveForbiddenSweepZones(newValue);
46
+ }
47
+ }
48
+ },
49
+ forbiddenMopZones: {
50
+ type: Array,
51
+ observer: function (newValue, oldValue) {
52
+ if (newValue !== oldValue && this.data.initialized && this.render) {
53
+ this.render.onReceiveForbiddenMopZones(newValue);
54
+ }
55
+ }
56
+ },
57
+ cleanZones: {
58
+ type: Array,
59
+ observer: function (newValue, oldValue) {
60
+ if (newValue !== oldValue && this.data.initialized && this.render) {
61
+ this.render.onReceiveCleanZones(newValue);
62
+ }
63
+ }
64
+ },
65
+ spots: {
66
+ type: Array,
67
+ observer: function (newValue, oldValue) {
68
+ if (newValue !== oldValue && this.data.initialized && this.render) {
69
+ this.render.onReceiveSpots(newValue);
70
+ }
71
+ }
72
+ },
73
+ virtualWalls: {
74
+ type: Array,
75
+ observer: function (newValue, oldValue) {
76
+ if (newValue !== oldValue && this.data.initialized && this.render) {
77
+ this.render.onReceiveVirtualWalls(newValue);
78
+ }
79
+ }
80
+ },
81
+ detectedObjects: {
82
+ type: Array,
83
+ observer: function (newValue, oldValue) {
84
+ if (newValue !== oldValue && this.data.initialized && this.render) {
85
+ this.render.onReceiveDetectedObjects(newValue);
86
+ }
87
+ }
88
+ },
89
+ customElements: {
90
+ type: Array,
91
+ observer: function (newValue, oldValue) {
92
+ if (newValue !== oldValue && this.data.initialized && this.render) {
93
+ this.render.onReceiveCustomElements(newValue);
94
+ }
95
+ }
96
+ },
97
+ config: {
98
+ type: Object,
99
+ observer: function () {
100
+ // config在初始化时设置,不需要动态更新
101
+ }
102
+ },
103
+ runtime: {
104
+ type: Object,
105
+ observer: function (newValue, oldValue) {
106
+ if (newValue !== oldValue && this.data.initialized && this.render) {
107
+ this.render.onUpdateRuntime(newValue);
108
+ }
109
+ }
110
+ }
111
+ },
112
+ lifetimes: {
113
+ created() {
114
+ this.render = new Render(this);
115
+ this.mapApi = null;
116
+ },
117
+ async ready() {
118
+ const config = this.properties.config || {};
119
+ await this.render.initialize(config);
120
+ this.setData({
121
+ initialized: true
122
+ });
123
+ if (this.data.map) {
124
+ this.render.onReceiveMap(this.data.map);
125
+ }
126
+ if (this.data.path) {
127
+ this.render.onReceivePath(this.data.path);
128
+ }
129
+ if (this.data.roomProperties) {
130
+ this.render.onReceiveRoomProperties(this.data.roomProperties);
131
+ }
132
+ if (this.data.forbiddenSweepZones) {
133
+ this.render.onReceiveForbiddenSweepZones(this.data.forbiddenSweepZones);
134
+ }
135
+ if (this.data.forbiddenMopZones) {
136
+ this.render.onReceiveForbiddenMopZones(this.data.forbiddenMopZones);
137
+ }
138
+ if (this.data.cleanZones) {
139
+ this.render.onReceiveCleanZones(this.data.cleanZones);
140
+ }
141
+ if (this.data.virtualWalls) {
142
+ this.render.onReceiveVirtualWalls(this.data.virtualWalls);
143
+ }
144
+ if (this.data.spots) {
145
+ this.render.onReceiveSpots(this.data.spots);
146
+ }
147
+ if (this.data.detectedObjects) {
148
+ this.render.onReceiveDetectedObjects(this.data.detectedObjects);
149
+ }
150
+ if (this.data.customElements) {
151
+ this.render.onReceiveCustomElements(this.data.customElements);
152
+ }
153
+ if (this.data.runtime) {
154
+ this.render.onUpdateRuntime(this.data.runtime);
155
+ }
156
+ },
157
+ detached() {
158
+ if (this.render) {
159
+ this.render.destroy();
160
+ }
161
+ }
162
+ },
163
+ pageLifetimes: {},
164
+ methods: {
165
+ // 为 render 对象动态添加 API 代理方法
166
+ setupApiProxyMethods() {
167
+ const {
168
+ render
169
+ } = this;
170
+ if (!render) {
171
+ return;
172
+ }
173
+
174
+ // 如果已经设置过,不重复设置(使用标记避免重复执行)
175
+ if (render.__apiProxyMethodsSetup) {
176
+ return;
177
+ }
178
+ MAP_API_METHODS.forEach(methodName => {
179
+ // 为 this.render 添加代理方法,通过 callMapInstanceMethod 来间接调用
180
+ // 因为 render.mapInstance 在外部无法访问(封装的私有属性)
181
+ render[methodName] = function () {
182
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
183
+ args[_key] = arguments[_key];
184
+ }
185
+ return render.callMapInstanceMethod(methodName, ...args);
186
+ };
187
+ });
188
+
189
+ // 标记已设置,避免重复执行
190
+ render.__apiProxyMethodsSetup = true;
191
+ },
192
+ // 创建MapApi对象,将rjs方法映射为API
193
+ createMapApi() {
194
+ if (!this.render) {
195
+ return null;
196
+ }
197
+ const mapApi = {};
198
+ MAP_API_METHODS.forEach(methodName => {
199
+ // 将方法绑定到 this.render,这样调用时会通过 render 代理到 mapInstance
200
+ if (typeof this.render[methodName] === 'function') {
201
+ mapApi[methodName] = this.render[methodName].bind(this.render);
202
+ }
203
+ });
204
+ return mapApi;
205
+ },
206
+ // 处理rjs回调事件
207
+ onInitialized() {
208
+ // 确保代理方法已设置(防止时序问题)
209
+ this.setupApiProxyMethods();
210
+ this.mapApi = this.createMapApi();
211
+ this.setData({
212
+ mapApi: this.mapApi
213
+ });
214
+ this.triggerEvent('onInitialized', this.mapApi);
215
+ }
216
+ }
217
+ };
218
+
219
+ // 动态添加所有 MAP_CALLBACK_METHODS 中定义的回调方法
220
+ MAP_CALLBACK_METHODS.forEach(methodName => {
221
+ componentOptions.methods[methodName] = function () {
222
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
223
+ args[_key2] = arguments[_key2];
224
+ }
225
+ this.triggerEvent(methodName, ...args);
226
+ };
227
+ });
228
+
229
+ // eslint-disable-next-line no-undef
230
+ Component(componentOptions);
@@ -0,0 +1,4 @@
1
+ {
2
+ "component": true,
3
+ "usingComponents": {}
4
+ }
@@ -0,0 +1,144 @@
1
+ import { MapApplication, MAP_API_METHODS, MAP_CALLBACK_METHODS } from "@ray-js/robot-map-sdk";
2
+ import { decodeMap, decodeMapStructured, decodePath } from '@ray-js/robot-protocol'
3
+
4
+ export default Render({
5
+ mapInstance: null,
6
+ initialized: false,
7
+
8
+ async initialize(config = {}) {
9
+ const { mapInstance } = this;
10
+
11
+ if (mapInstance) {
12
+ console.warn('Map instance already initialized')
13
+ return
14
+ }
15
+
16
+ this.mapInstance = new MapApplication()
17
+ const containerElement = document.getElementById('container')
18
+
19
+ console.log('=====================containerElement', containerElement)
20
+
21
+ // 定义事件处理器
22
+ const events = {}
23
+
24
+ // 使用从SDK导入的回调方法
25
+ MAP_CALLBACK_METHODS.forEach(methodName => {
26
+ events[methodName] = (...args) => {
27
+ // 通过callMethod与ts通信
28
+ this.callMethod(methodName, ...args)
29
+ }
30
+ })
31
+
32
+ await this.mapInstance.initialize({
33
+ resizeTo: containerElement ?? window,
34
+ events,
35
+ config,
36
+ })
37
+
38
+ if (containerElement) {
39
+ containerElement.appendChild(this.mapInstance.canvas)
40
+ } else {
41
+ document.body.appendChild(this.mapInstance.canvas)
42
+ }
43
+
44
+ this.initialized = true
45
+ this.callMethod('onInitialized')
46
+ },
47
+
48
+ // 接收地图数据
49
+ onReceiveMap(map) {
50
+ if (!this.mapInstance || !map) return
51
+
52
+ if (map.startsWith('7b22')) {
53
+ // 结构化协议地图数据
54
+ this.mapInstance.drawMap(decodeMapStructured(map))
55
+ } else {
56
+ // 点云结构地图数据
57
+ const rasterMapData = decodeMap(map)
58
+ if (rasterMapData) {
59
+ this.mapInstance.drawRasterMap(rasterMapData)
60
+ } else {
61
+ console.error('Failed to decode raster map data')
62
+ }
63
+ }
64
+ },
65
+
66
+ // 接收路径数据
67
+ onReceivePath(path) {
68
+ if (!this.mapInstance || !path) return
69
+ this.mapInstance.drawPath(decodePath(path))
70
+ },
71
+
72
+ // 接收房间属性
73
+ onReceiveRoomProperties(roomProperties) {
74
+ if (!this.mapInstance || !roomProperties) return
75
+ this.mapInstance.drawRoomProperty(roomProperties)
76
+ },
77
+
78
+ // 接收禁扫区域
79
+ onReceiveForbiddenSweepZones(zones) {
80
+ if (!this.mapInstance || !zones) return
81
+ this.mapInstance.drawForbiddenSweepZones(zones)
82
+ },
83
+
84
+ // 接收禁拖区域
85
+ onReceiveForbiddenMopZones(zones) {
86
+ if (!this.mapInstance || !zones) return
87
+ this.mapInstance.drawForbiddenMopZones(zones)
88
+ },
89
+
90
+ // 接收清洁区域
91
+ onReceiveCleanZones(zones) {
92
+ if (!this.mapInstance || !zones) return
93
+ this.mapInstance.drawCleanZones(zones)
94
+ },
95
+
96
+ // 接收虚拟墙
97
+ onReceiveVirtualWalls(walls) {
98
+ if (!this.mapInstance || !walls) return
99
+ this.mapInstance.drawVirtualWalls(walls)
100
+ },
101
+
102
+ // 接收定点清扫
103
+ onReceiveSpots(spots) {
104
+ if (!this.mapInstance || !spots) return
105
+ this.mapInstance.drawSpots(spots)
106
+ },
107
+
108
+ // 接收检测对象
109
+ onReceiveDetectedObjects(objects) {
110
+ if (!this.mapInstance || !objects) return
111
+ this.mapInstance.drawDetectedObjects(objects)
112
+ },
113
+
114
+ // 接收自定义元素
115
+ onReceiveCustomElements(elements) {
116
+ if (!this.mapInstance || !elements) return
117
+ this.mapInstance.drawCustomElements(elements)
118
+ },
119
+
120
+ // 更新运行时配置
121
+ onUpdateRuntime(runtime) {
122
+ if (!this.mapInstance || !runtime) return
123
+ this.mapInstance.updateRuntime(runtime)
124
+ },
125
+
126
+ // 销毁地图实例
127
+ destroy() {
128
+ if (this.mapInstance) {
129
+ this.mapInstance.destroy()
130
+ this.mapInstance = null
131
+ this.initialized = false
132
+ }
133
+ },
134
+
135
+ // 通用的 API 调用方法,用于代理所有 mapInstance 上的方法
136
+ // 因为外部无法直接访问 this.mapInstance,所以提供这个方法来间接调用
137
+ callMapInstanceMethod(methodName, ...args) {
138
+ if (this.mapInstance && typeof this.mapInstance[methodName] === 'function') {
139
+ return this.mapInstance[methodName](...args)
140
+ }
141
+ console.warn(`Method ${methodName} not available on mapInstance`)
142
+ return null
143
+ }
144
+ })
@@ -0,0 +1 @@
1
+ <view id="container" />
@@ -0,0 +1,5 @@
1
+ #container {
2
+ position: absolute;
3
+ width: 100%;
4
+ height: 100%;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { FC } from 'react';
2
+ import { AppOptions } from '@ray-js/robot-map-sdk';
3
+ import { RobotMapProps } from './props';
4
+ declare const RjsRobotMap: FC<RobotMapProps & AppOptions['events']>;
5
+ export default RjsRobotMap;
@@ -0,0 +1,98 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
+ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
4
+ const _excluded = ["map", "path", "roomProperties", "forbiddenSweepZones", "forbiddenMopZones", "cleanZones", "virtualWalls", "spots", "detectedObjects", "customElements", "config", "runtime", "onMapReady"];
5
+ import "core-js/modules/esnext.iterator.constructor.js";
6
+ import "core-js/modules/esnext.iterator.for-each.js";
7
+ import "core-js/modules/esnext.iterator.map.js";
8
+ import "core-js/modules/esnext.iterator.reduce.js";
9
+ import "core-js/modules/web.dom-collections.iterator.js";
10
+ import React, { useCallback, useEffect, useRef, useMemo } from 'react';
11
+ import { MAP_CALLBACK_METHODS } from '@ray-js/robot-map-sdk';
12
+ import RjsComponent from './RjsComponent';
13
+ import { robotMapDefaultProps } from './props';
14
+
15
+ // 回调名到事件名的映射
16
+ const CALLBACK_TO_EVENT_MAP = _objectSpread({
17
+ onInitialized: 'onInitialized'
18
+ }, MAP_CALLBACK_METHODS.reduce((acc, methodName) => {
19
+ acc[methodName] = methodName;
20
+ return acc;
21
+ }, {}));
22
+ const RjsRobotMap = _ref => {
23
+ let {
24
+ map,
25
+ path,
26
+ roomProperties,
27
+ forbiddenSweepZones,
28
+ forbiddenMopZones,
29
+ cleanZones,
30
+ virtualWalls,
31
+ spots,
32
+ detectedObjects,
33
+ customElements,
34
+ config,
35
+ runtime,
36
+ onMapReady
37
+ } = _ref,
38
+ callbacks = _objectWithoutProperties(_ref, _excluded);
39
+ const componentRef = useRef(null);
40
+ const callbacksRef = useRef(callbacks);
41
+
42
+ // 更新回调引用
43
+ useEffect(() => {
44
+ callbacksRef.current = callbacks;
45
+ });
46
+
47
+ // 事件分发函数 - 这个函数是稳定的,不会随渲染变化
48
+ const eventDispatcher = useCallback(function (eventName) {
49
+ const propName = CALLBACK_TO_EVENT_MAP[eventName];
50
+ if (propName && callbacksRef.current[propName]) {
51
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
52
+ args[_key - 1] = arguments[_key];
53
+ }
54
+ // 调用最新的prop回调
55
+ callbacksRef.current[propName](...args);
56
+ }
57
+ }, []);
58
+
59
+ // 处理初始化完成事件
60
+ const handleInitialized = useCallback(event => {
61
+ const api = event.detail;
62
+ onMapReady === null || onMapReady === void 0 || onMapReady(api);
63
+ eventDispatcher('onInitialized', api);
64
+ }, [onMapReady, eventDispatcher]);
65
+
66
+ // 动态生成所有回调处理函数的绑定属性
67
+ const eventBindings = useMemo(() => {
68
+ const bindings = {
69
+ bindonInitialized: handleInitialized
70
+ };
71
+
72
+ // 为 MAP_CALLBACK_METHODS 中的每个方法创建绑定
73
+ MAP_CALLBACK_METHODS.forEach(methodName => {
74
+ bindings["bind".concat(methodName)] = event => {
75
+ eventDispatcher(methodName, event.detail);
76
+ };
77
+ });
78
+ return bindings;
79
+ }, [handleInitialized, eventDispatcher]);
80
+ return /*#__PURE__*/React.createElement(RjsComponent, _extends({
81
+ ref: componentRef,
82
+ map: map,
83
+ path: path,
84
+ roomProperties: roomProperties,
85
+ forbiddenSweepZones: forbiddenSweepZones,
86
+ forbiddenMopZones: forbiddenMopZones,
87
+ cleanZones: cleanZones,
88
+ virtualWalls: virtualWalls,
89
+ spots: spots,
90
+ detectedObjects: detectedObjects,
91
+ customElements: customElements,
92
+ config: config,
93
+ runtime: runtime
94
+ }, eventBindings));
95
+ };
96
+ RjsRobotMap.defaultProps = robotMapDefaultProps;
97
+ RjsRobotMap.displayName = 'RjsRobotMap';
98
+ export default RjsRobotMap;
package/lib/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default as RobotMap } from './RobotMap';
2
+ export { default as RjsRobotMap } from './RjsRobotMap';
2
3
  export * from '@ray-js/robot-map-sdk';
package/lib/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { default as RobotMap } from './RobotMap';
2
+ export { default as RjsRobotMap } from './RjsRobotMap';
2
3
  export * from '@ray-js/robot-map-sdk';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ray-js/robot-map",
3
- "version": "0.0.2-beta-3",
3
+ "version": "0.0.2-beta-5",
4
4
  "description": "机器人地图组件",
5
5
  "main": "lib/index",
6
6
  "files": [
@@ -32,7 +32,7 @@
32
32
  "@ray-js/ray": "^1.7.39"
33
33
  },
34
34
  "dependencies": {
35
- "@ray-js/robot-map-sdk": "0.0.2",
35
+ "@ray-js/robot-map-sdk": "0.0.3-beta-3",
36
36
  "clsx": "^1.2.1",
37
37
  "nanoid": "^5.1.6"
38
38
  },