@midscene/visualizer 1.5.2 → 1.5.3-beta-20260305031559.0
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/dist/es/component/blackboard/index.css +82 -4
- package/dist/es/component/blackboard/index.mjs +73 -301
- package/dist/es/component/player/index.css +144 -119
- package/dist/es/component/player/index.mjs +468 -830
- package/dist/es/component/player/remotion/StepScene.mjs +190 -0
- package/dist/es/component/player/remotion/derive-frame-state.mjs +207 -0
- package/dist/es/component/player/remotion/export-branded-video.mjs +210 -0
- package/dist/es/component/player/remotion/frame-calculator.mjs +149 -0
- package/dist/es/component/player/use-frame-player.mjs +88 -0
- package/dist/es/component/universal-playground/index.mjs +14 -1
- package/dist/es/hooks/usePlaygroundExecution.mjs +11 -7
- package/dist/es/store/store.mjs +9 -0
- package/dist/es/utils/replay-scripts.mjs +2 -1
- package/dist/lib/component/blackboard/index.css +82 -4
- package/dist/lib/component/blackboard/index.js +73 -307
- package/dist/lib/component/player/index.css +144 -119
- package/dist/lib/component/player/index.js +466 -828
- package/dist/lib/component/player/remotion/StepScene.js +224 -0
- package/dist/lib/component/player/remotion/derive-frame-state.js +241 -0
- package/dist/lib/component/player/remotion/export-branded-video.js +244 -0
- package/dist/lib/component/player/remotion/frame-calculator.js +186 -0
- package/dist/lib/component/player/use-frame-player.js +122 -0
- package/dist/lib/component/universal-playground/index.js +14 -1
- package/dist/lib/hooks/usePlaygroundExecution.js +11 -7
- package/dist/lib/store/store.js +9 -0
- package/dist/lib/utils/replay-scripts.js +2 -1
- package/dist/types/component/blackboard/index.d.ts +0 -4
- package/dist/types/component/player/index.d.ts +0 -1
- package/dist/types/component/player/remotion/StepScene.d.ts +9 -0
- package/dist/types/component/player/remotion/derive-frame-state.d.ts +38 -0
- package/dist/types/component/player/remotion/export-branded-video.d.ts +2 -0
- package/dist/types/component/player/remotion/frame-calculator.d.ts +35 -0
- package/dist/types/component/player/use-frame-player.d.ts +17 -0
- package/dist/types/hooks/usePlaygroundExecution.d.ts +15 -1
- package/dist/types/store/store.d.ts +2 -0
- package/dist/types/utils/replay-scripts.d.ts +1 -0
- package/package.json +5 -8
- package/dist/es/utils/pixi-loader.mjs +0 -42
- package/dist/lib/utils/pixi-loader.js +0 -82
- package/dist/types/utils/pixi-loader.d.ts +0 -5
|
@@ -21,21 +21,99 @@
|
|
|
21
21
|
max-width: 500px;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
.blackboard-
|
|
25
|
-
|
|
24
|
+
.blackboard-main-content {
|
|
25
|
+
position: relative;
|
|
26
|
+
overflow: hidden;
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
.blackboard-
|
|
29
|
+
.blackboard-screenshot {
|
|
29
30
|
box-sizing: border-box;
|
|
30
31
|
border: 1px solid #888;
|
|
31
32
|
width: 100%;
|
|
33
|
+
display: block;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.blackboard-overlay {
|
|
37
|
+
pointer-events: none;
|
|
38
|
+
width: 100%;
|
|
39
|
+
position: absolute;
|
|
40
|
+
top: 0;
|
|
41
|
+
left: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.blackboard-rect {
|
|
45
|
+
box-sizing: border-box;
|
|
46
|
+
pointer-events: none;
|
|
47
|
+
position: absolute;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.blackboard-rect-label {
|
|
51
|
+
white-space: nowrap;
|
|
52
|
+
padding: 1px 4px;
|
|
53
|
+
font-size: 14px;
|
|
54
|
+
font-weight: 600;
|
|
55
|
+
line-height: 1.4;
|
|
56
|
+
position: absolute;
|
|
57
|
+
bottom: 100%;
|
|
58
|
+
left: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.blackboard-rect-search {
|
|
62
|
+
background: rgba(2, 131, 145, .4);
|
|
63
|
+
border: 1px solid #028391;
|
|
64
|
+
box-shadow: 4px 4px 2px rgba(51, 51, 51, .4);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.blackboard-rect-search .blackboard-rect-label {
|
|
68
|
+
color: #028391;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.blackboard-rect-highlight {
|
|
72
|
+
background: rgba(253, 89, 7, .4);
|
|
73
|
+
border: 1px solid #fd5907;
|
|
74
|
+
animation: 1.2s ease-in-out infinite blackboard-pulse;
|
|
75
|
+
box-shadow: 4px 4px 2px rgba(51, 51, 51, .4);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.blackboard-rect-highlight .blackboard-rect-label {
|
|
79
|
+
color: #000;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.blackboard-point {
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
background: rgba(253, 89, 7, .4);
|
|
85
|
+
border: 1px solid #fd5907;
|
|
86
|
+
border-radius: 50%;
|
|
87
|
+
width: 20px;
|
|
88
|
+
height: 20px;
|
|
89
|
+
margin-top: -10px;
|
|
90
|
+
margin-left: -10px;
|
|
91
|
+
animation: 1.2s ease-in-out infinite blackboard-pulse;
|
|
92
|
+
position: absolute;
|
|
93
|
+
box-shadow: 0 0 8px rgba(253, 89, 7, .5);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@keyframes blackboard-pulse {
|
|
97
|
+
0%, 100% {
|
|
98
|
+
opacity: .4;
|
|
99
|
+
box-shadow: 4px 4px 2px rgba(51, 51, 51, .4);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
50% {
|
|
103
|
+
opacity: 1;
|
|
104
|
+
box-shadow: 4px 4px 2px rgba(51, 51, 51, .4), 0 0 16px rgba(253, 89, 7, .5);
|
|
105
|
+
}
|
|
32
106
|
}
|
|
33
107
|
|
|
34
108
|
[data-theme="dark"] .blackboard .footer, [data-theme="dark"] .blackboard .bottom-tip-item {
|
|
35
109
|
color: rgba(255, 255, 255, .45);
|
|
36
110
|
}
|
|
37
111
|
|
|
38
|
-
[data-theme="dark"] .blackboard-
|
|
112
|
+
[data-theme="dark"] .blackboard-screenshot {
|
|
39
113
|
border-color: rgba(255, 255, 255, .12);
|
|
40
114
|
}
|
|
41
115
|
|
|
116
|
+
[data-theme="dark"] .blackboard-rect-highlight .blackboard-rect-label {
|
|
117
|
+
color: #fff;
|
|
118
|
+
}
|
|
119
|
+
|
|
@@ -1,91 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import "
|
|
4
|
-
import { Application, Container, Graphics, Rectangle, Sprite, Text, Texture } from "pixi.js";
|
|
5
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
-
import { colorForName, highlightColorForType } from "../../utils/color.mjs";
|
|
3
|
+
import { useMemo, useRef } from "react";
|
|
7
4
|
import "./index.css";
|
|
8
|
-
import { DropShadowFilter, GlowFilter } from "pixi-filters";
|
|
9
|
-
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
10
|
-
try {
|
|
11
|
-
var info = gen[key](arg);
|
|
12
|
-
var value = info.value;
|
|
13
|
-
} catch (error) {
|
|
14
|
-
reject(error);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
if (info.done) resolve(value);
|
|
18
|
-
else Promise.resolve(value).then(_next, _throw);
|
|
19
|
-
}
|
|
20
|
-
function _async_to_generator(fn) {
|
|
21
|
-
return function() {
|
|
22
|
-
var self = this, args = arguments;
|
|
23
|
-
return new Promise(function(resolve, reject) {
|
|
24
|
-
var gen = fn.apply(self, args);
|
|
25
|
-
function _next(value) {
|
|
26
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
|
|
27
|
-
}
|
|
28
|
-
function _throw(err) {
|
|
29
|
-
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
|
|
30
|
-
}
|
|
31
|
-
_next(void 0);
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
const itemFillAlpha = 0.4;
|
|
36
|
-
const highlightAlpha = 0.4;
|
|
37
|
-
const pointRadius = 10;
|
|
38
|
-
const pointMarkForItem = (point, type)=>{
|
|
39
|
-
const [x, y] = point;
|
|
40
|
-
const themeColor = highlightColorForType('element');
|
|
41
|
-
const graphics = new Graphics();
|
|
42
|
-
graphics.beginFill(themeColor, itemFillAlpha);
|
|
43
|
-
graphics.drawCircle(x, y, pointRadius);
|
|
44
|
-
graphics.endFill();
|
|
45
|
-
return graphics;
|
|
46
|
-
};
|
|
47
|
-
const rectMarkForItem = (rect, name, type)=>{
|
|
48
|
-
const { left, top, width, height } = rect;
|
|
49
|
-
let themeColor;
|
|
50
|
-
themeColor = 'element' === type ? colorForName(name) : 'searchArea' === type ? highlightColorForType('searchArea') : highlightColorForType('element');
|
|
51
|
-
const alpha = 'highlight' === type ? highlightAlpha : itemFillAlpha;
|
|
52
|
-
const graphics = new Graphics();
|
|
53
|
-
graphics.beginFill(themeColor, alpha);
|
|
54
|
-
graphics.lineStyle(1, themeColor, 1);
|
|
55
|
-
graphics.drawRect(left, top, width, height);
|
|
56
|
-
graphics.endFill();
|
|
57
|
-
const dropShadowFilter = new DropShadowFilter({
|
|
58
|
-
blur: 2,
|
|
59
|
-
quality: 3,
|
|
60
|
-
alpha: 0.4,
|
|
61
|
-
offset: {
|
|
62
|
-
x: 4,
|
|
63
|
-
y: 4
|
|
64
|
-
},
|
|
65
|
-
color: 0x333333
|
|
66
|
-
});
|
|
67
|
-
graphics.filters = [
|
|
68
|
-
dropShadowFilter
|
|
69
|
-
];
|
|
70
|
-
const nameFontSize = 18;
|
|
71
|
-
if (!name) return [
|
|
72
|
-
graphics
|
|
73
|
-
];
|
|
74
|
-
const texts = new Text(name, {
|
|
75
|
-
fontSize: nameFontSize,
|
|
76
|
-
fill: 0x0
|
|
77
|
-
});
|
|
78
|
-
texts.x = left;
|
|
79
|
-
texts.y = Math.max(top - (nameFontSize + 4), 0);
|
|
80
|
-
return [
|
|
81
|
-
graphics,
|
|
82
|
-
texts
|
|
83
|
-
];
|
|
84
|
-
};
|
|
85
5
|
const Blackboard = (props)=>{
|
|
86
6
|
var _props_uiContext;
|
|
87
7
|
const highlightElements = props.highlightElements || [];
|
|
88
|
-
highlightElements.map((e)=>e.id);
|
|
89
8
|
const highlightRect = props.highlightRect;
|
|
90
9
|
const highlightPoints = props.highlightPoints;
|
|
91
10
|
if (!(null == (_props_uiContext = props.uiContext) ? void 0 : _props_uiContext.shotSize)) return /*#__PURE__*/ jsx("div", {
|
|
@@ -100,6 +19,8 @@ const Blackboard = (props)=>{
|
|
|
100
19
|
});
|
|
101
20
|
const context = props.uiContext;
|
|
102
21
|
const { shotSize, screenshot } = context;
|
|
22
|
+
const screenWidth = shotSize.width;
|
|
23
|
+
const screenHeight = shotSize.height;
|
|
103
24
|
const screenshotBase64 = useMemo(()=>{
|
|
104
25
|
if (!screenshot) return '';
|
|
105
26
|
if ('object' == typeof screenshot && 'base64' in screenshot) return screenshot.base64;
|
|
@@ -108,221 +29,20 @@ const Blackboard = (props)=>{
|
|
|
108
29
|
}, [
|
|
109
30
|
screenshot
|
|
110
31
|
]);
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
useEffect(()=>{
|
|
126
|
-
Promise.resolve((()=>_async_to_generator(function*() {
|
|
127
|
-
if (!domRef.current || !screenWidth) return;
|
|
128
|
-
yield app.init({
|
|
129
|
-
width: screenWidth,
|
|
130
|
-
height: screenHeight,
|
|
131
|
-
background: 0xffffff
|
|
132
|
-
});
|
|
133
|
-
const canvasEl = domRef.current;
|
|
134
|
-
domRef.current.appendChild(app.canvas);
|
|
135
|
-
const { clientWidth } = domRef.current.parentElement;
|
|
136
|
-
const targetHeight = 0.6 * window.innerHeight;
|
|
137
|
-
const viewportRatio = clientWidth / targetHeight;
|
|
138
|
-
if (screenWidth / screenHeight <= viewportRatio) {
|
|
139
|
-
const ratio = targetHeight / screenHeight;
|
|
140
|
-
canvasEl.style.width = `${Math.floor(screenWidth * ratio)}px`;
|
|
141
|
-
canvasEl.style.height = `${Math.floor(screenHeight * ratio)}px`;
|
|
142
|
-
}
|
|
143
|
-
app.stage.addChild(highlightContainer);
|
|
144
|
-
app.stage.addChild(elementMarkContainer);
|
|
145
|
-
setAppInitialed(true);
|
|
146
|
-
})())());
|
|
147
|
-
return ()=>{
|
|
148
|
-
console.log('will destroy');
|
|
149
|
-
if (null !== animationFrameRef.current) {
|
|
150
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
151
|
-
animationFrameRef.current = null;
|
|
152
|
-
}
|
|
153
|
-
try {
|
|
154
|
-
app.destroy(true, {
|
|
155
|
-
children: true,
|
|
156
|
-
texture: true
|
|
157
|
-
});
|
|
158
|
-
} catch (e) {
|
|
159
|
-
console.warn('destroy failed', e);
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
}, [
|
|
163
|
-
app,
|
|
164
|
-
screenWidth,
|
|
165
|
-
screenHeight
|
|
166
|
-
]);
|
|
167
|
-
useEffect(()=>{
|
|
168
|
-
if (!appInitialed) return;
|
|
169
|
-
app.stage.eventMode = 'static';
|
|
170
|
-
app.stage.hitArea = new Rectangle(0, 0, screenWidth, screenHeight);
|
|
171
|
-
const clickHandler = (event)=>{
|
|
172
|
-
var _props_onCanvasClick;
|
|
173
|
-
console.log('pixi click', event);
|
|
174
|
-
const { x, y } = event.data.global;
|
|
175
|
-
null == (_props_onCanvasClick = props.onCanvasClick) || _props_onCanvasClick.call(props, [
|
|
176
|
-
Math.round(x),
|
|
177
|
-
Math.round(y)
|
|
178
|
-
]);
|
|
179
|
-
};
|
|
180
|
-
app.stage.on('click', clickHandler);
|
|
181
|
-
return ()=>{
|
|
182
|
-
var _app_stage;
|
|
183
|
-
null == app || null == (_app_stage = app.stage) || _app_stage.off('click');
|
|
184
|
-
};
|
|
185
|
-
}, [
|
|
186
|
-
appInitialed,
|
|
187
|
-
props.onCanvasClick,
|
|
188
|
-
screenWidth,
|
|
189
|
-
screenHeight
|
|
190
|
-
]);
|
|
191
|
-
useEffect(()=>{
|
|
192
|
-
if (!appInitialed) return;
|
|
193
|
-
const img = new Image();
|
|
194
|
-
img.onload = ()=>{
|
|
195
|
-
if (!app.stage) return;
|
|
196
|
-
const screenshotTexture = Texture.from(img);
|
|
197
|
-
const backgroundSprite = new Sprite(screenshotTexture);
|
|
198
|
-
backgroundSprite.x = 0;
|
|
199
|
-
backgroundSprite.y = 0;
|
|
200
|
-
backgroundSprite.width = screenWidth;
|
|
201
|
-
backgroundSprite.height = screenHeight;
|
|
202
|
-
backgroundSprite.eventMode = 'passive';
|
|
203
|
-
app.stage.addChildAt(backgroundSprite, 0);
|
|
204
|
-
pixiBgRef.current = backgroundSprite;
|
|
205
|
-
backgroundSprite.visible = backgroundVisible;
|
|
206
|
-
};
|
|
207
|
-
img.onerror = (e)=>{
|
|
208
|
-
console.error('load screenshot failed', e);
|
|
209
|
-
};
|
|
210
|
-
if (screenshotBase64) img.src = screenshotBase64;
|
|
211
|
-
else console.error('screenshotBase64 is empty, cannot load image');
|
|
212
|
-
}, [
|
|
213
|
-
app.stage,
|
|
214
|
-
appInitialed,
|
|
215
|
-
screenWidth,
|
|
216
|
-
screenHeight,
|
|
217
|
-
screenshotBase64
|
|
218
|
-
]);
|
|
219
|
-
const { highlightElementRects } = useMemo(()=>{
|
|
220
|
-
const highlightElementRects = [];
|
|
221
|
-
highlightContainer.removeChildren();
|
|
222
|
-
elementMarkContainer.removeChildren();
|
|
223
|
-
highlightContainer.eventMode = 'passive';
|
|
224
|
-
elementMarkContainer.eventMode = 'passive';
|
|
225
|
-
highlightGraphicsRef.current = [];
|
|
226
|
-
glowFiltersRef.current = [];
|
|
227
|
-
if (highlightRect) {
|
|
228
|
-
const [graphics] = rectMarkForItem(highlightRect, 'Search Area', 'searchArea');
|
|
229
|
-
highlightContainer.addChild(graphics);
|
|
230
|
-
}
|
|
231
|
-
if (highlightElements.length) highlightElements.forEach((element)=>{
|
|
232
|
-
const { rect, content, id } = element;
|
|
233
|
-
const items = rectMarkForItem(rect, content, 'highlight');
|
|
234
|
-
const graphics = items[0];
|
|
235
|
-
const glowFilter = new GlowFilter({
|
|
236
|
-
distance: 30,
|
|
237
|
-
outerStrength: 3,
|
|
238
|
-
innerStrength: 0,
|
|
239
|
-
color: 0xfd5907,
|
|
240
|
-
quality: 0.5
|
|
241
|
-
});
|
|
242
|
-
const existingFilters = graphics.filters;
|
|
243
|
-
if (Array.isArray(existingFilters)) graphics.filters = [
|
|
244
|
-
...existingFilters,
|
|
245
|
-
glowFilter
|
|
246
|
-
];
|
|
247
|
-
else if (existingFilters) graphics.filters = [
|
|
248
|
-
existingFilters,
|
|
249
|
-
glowFilter
|
|
250
|
-
];
|
|
251
|
-
else graphics.filters = [
|
|
252
|
-
glowFilter
|
|
253
|
-
];
|
|
254
|
-
items.forEach((item)=>highlightContainer.addChild(item));
|
|
255
|
-
highlightGraphicsRef.current.push(graphics);
|
|
256
|
-
glowFiltersRef.current.push(glowFilter);
|
|
257
|
-
});
|
|
258
|
-
if (null == highlightPoints ? void 0 : highlightPoints.length) highlightPoints.forEach((point)=>{
|
|
259
|
-
const graphics = pointMarkForItem(point, 'highlightPoint');
|
|
260
|
-
const glowFilter = new GlowFilter({
|
|
261
|
-
distance: 25,
|
|
262
|
-
outerStrength: 2.5,
|
|
263
|
-
innerStrength: 0,
|
|
264
|
-
color: 0xfd5907,
|
|
265
|
-
quality: 0.5
|
|
266
|
-
});
|
|
267
|
-
graphics.filters = [
|
|
268
|
-
glowFilter
|
|
269
|
-
];
|
|
270
|
-
highlightContainer.addChild(graphics);
|
|
271
|
-
highlightGraphicsRef.current.push(graphics);
|
|
272
|
-
glowFiltersRef.current.push(glowFilter);
|
|
273
|
-
});
|
|
274
|
-
elementMarkContainer.visible = elementsVisible;
|
|
275
|
-
return {
|
|
276
|
-
highlightElementRects
|
|
277
|
-
};
|
|
278
|
-
}, [
|
|
279
|
-
app,
|
|
280
|
-
appInitialed,
|
|
281
|
-
highlightElements,
|
|
282
|
-
hoverElement,
|
|
283
|
-
highlightRect,
|
|
284
|
-
highlightPoints
|
|
285
|
-
]);
|
|
286
|
-
useEffect(()=>{
|
|
287
|
-
if (!appInitialed || 0 === highlightGraphicsRef.current.length) return void console.log('Animation skipped:', {
|
|
288
|
-
appInitialed,
|
|
289
|
-
graphicsCount: highlightGraphicsRef.current.length
|
|
290
|
-
});
|
|
291
|
-
console.log('Starting pulsing animation for', highlightGraphicsRef.current.length, 'graphics');
|
|
292
|
-
const graphicsToAnimate = highlightGraphicsRef.current;
|
|
293
|
-
const glowFilters = glowFiltersRef.current;
|
|
294
|
-
const pulseDuration = 1200;
|
|
295
|
-
const minAlpha = 0.4;
|
|
296
|
-
const maxAlpha = 1.0;
|
|
297
|
-
const minGlowStrength = 2.0;
|
|
298
|
-
const maxGlowStrength = 5.0;
|
|
299
|
-
const startTime = performance.now();
|
|
300
|
-
const animate = ()=>{
|
|
301
|
-
const elapsed = performance.now() - startTime;
|
|
302
|
-
const progress = elapsed % pulseDuration / pulseDuration;
|
|
303
|
-
const sineValue = Math.sin(progress * Math.PI * 2);
|
|
304
|
-
const normalizedSine = (sineValue + 1) / 2;
|
|
305
|
-
const alpha = minAlpha + normalizedSine * (maxAlpha - minAlpha);
|
|
306
|
-
const glowStrength = minGlowStrength + normalizedSine * (maxGlowStrength - minGlowStrength);
|
|
307
|
-
graphicsToAnimate.forEach((graphics, index)=>{
|
|
308
|
-
graphics.alpha = alpha;
|
|
309
|
-
if (glowFilters[index]) glowFilters[index].outerStrength = glowStrength;
|
|
310
|
-
});
|
|
311
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
312
|
-
};
|
|
313
|
-
animate();
|
|
314
|
-
return ()=>{
|
|
315
|
-
console.log('Stopping pulsing animation');
|
|
316
|
-
if (null !== animationFrameRef.current) {
|
|
317
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
318
|
-
animationFrameRef.current = null;
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
}, [
|
|
322
|
-
appInitialed,
|
|
323
|
-
highlightElements,
|
|
324
|
-
highlightPoints
|
|
325
|
-
]);
|
|
32
|
+
const containerRef = useRef(null);
|
|
33
|
+
const handleClick = (e)=>{
|
|
34
|
+
if (!props.onCanvasClick || !containerRef.current) return;
|
|
35
|
+
const rect = containerRef.current.getBoundingClientRect();
|
|
36
|
+
const scaleX = screenWidth / rect.width;
|
|
37
|
+
const scaleY = screenHeight / rect.height;
|
|
38
|
+
const x = Math.round((e.clientX - rect.left) * scaleX);
|
|
39
|
+
const y = Math.round((e.clientY - rect.top) * scaleY);
|
|
40
|
+
props.onCanvasClick([
|
|
41
|
+
x,
|
|
42
|
+
y
|
|
43
|
+
]);
|
|
44
|
+
};
|
|
45
|
+
const highlightElementRects = highlightElements.map((e)=>e.rect);
|
|
326
46
|
let bottomTipA = null;
|
|
327
47
|
if (1 === highlightElementRects.length) bottomTipA = /*#__PURE__*/ jsx("div", {
|
|
328
48
|
className: "bottom-tip",
|
|
@@ -347,12 +67,64 @@ const Blackboard = (props)=>{
|
|
|
347
67
|
return /*#__PURE__*/ jsxs("div", {
|
|
348
68
|
className: "blackboard",
|
|
349
69
|
children: [
|
|
350
|
-
/*#__PURE__*/
|
|
70
|
+
/*#__PURE__*/ jsxs("div", {
|
|
351
71
|
className: "blackboard-main-content",
|
|
72
|
+
ref: containerRef,
|
|
73
|
+
onClick: handleClick,
|
|
352
74
|
style: {
|
|
353
|
-
width: '100%'
|
|
75
|
+
width: '100%',
|
|
76
|
+
position: 'relative',
|
|
77
|
+
cursor: props.onCanvasClick ? 'crosshair' : void 0
|
|
354
78
|
},
|
|
355
|
-
|
|
79
|
+
children: [
|
|
80
|
+
screenshotBase64 && /*#__PURE__*/ jsx("img", {
|
|
81
|
+
src: screenshotBase64,
|
|
82
|
+
alt: "screenshot",
|
|
83
|
+
className: "blackboard-screenshot",
|
|
84
|
+
draggable: false
|
|
85
|
+
}),
|
|
86
|
+
/*#__PURE__*/ jsxs("div", {
|
|
87
|
+
className: "blackboard-overlay",
|
|
88
|
+
style: {
|
|
89
|
+
aspectRatio: `${screenWidth}/${screenHeight}`
|
|
90
|
+
},
|
|
91
|
+
children: [
|
|
92
|
+
highlightRect && /*#__PURE__*/ jsx("div", {
|
|
93
|
+
className: "blackboard-rect blackboard-rect-search",
|
|
94
|
+
style: {
|
|
95
|
+
left: `${highlightRect.left / screenWidth * 100}%`,
|
|
96
|
+
top: `${highlightRect.top / screenHeight * 100}%`,
|
|
97
|
+
width: `${highlightRect.width / screenWidth * 100}%`,
|
|
98
|
+
height: `${highlightRect.height / screenHeight * 100}%`
|
|
99
|
+
},
|
|
100
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
101
|
+
className: "blackboard-rect-label",
|
|
102
|
+
children: "Search Area"
|
|
103
|
+
})
|
|
104
|
+
}),
|
|
105
|
+
highlightElements.map((el, idx)=>/*#__PURE__*/ jsx("div", {
|
|
106
|
+
className: "blackboard-rect blackboard-rect-highlight",
|
|
107
|
+
style: {
|
|
108
|
+
left: `${el.rect.left / screenWidth * 100}%`,
|
|
109
|
+
top: `${el.rect.top / screenHeight * 100}%`,
|
|
110
|
+
width: `${el.rect.width / screenWidth * 100}%`,
|
|
111
|
+
height: `${el.rect.height / screenHeight * 100}%`
|
|
112
|
+
},
|
|
113
|
+
children: el.content && /*#__PURE__*/ jsx("span", {
|
|
114
|
+
className: "blackboard-rect-label",
|
|
115
|
+
children: el.content
|
|
116
|
+
})
|
|
117
|
+
}, el.id || idx)),
|
|
118
|
+
null == highlightPoints ? void 0 : highlightPoints.map((point, idx)=>/*#__PURE__*/ jsx("div", {
|
|
119
|
+
className: "blackboard-point",
|
|
120
|
+
style: {
|
|
121
|
+
left: `${point[0] / screenWidth * 100}%`,
|
|
122
|
+
top: `${point[1] / screenHeight * 100}%`
|
|
123
|
+
}
|
|
124
|
+
}, idx))
|
|
125
|
+
]
|
|
126
|
+
})
|
|
127
|
+
]
|
|
356
128
|
}),
|
|
357
129
|
/*#__PURE__*/ jsx("div", {
|
|
358
130
|
className: "bottom-tip",
|
|
@@ -365,4 +137,4 @@ const Blackboard = (props)=>{
|
|
|
365
137
|
});
|
|
366
138
|
};
|
|
367
139
|
const blackboard = Blackboard;
|
|
368
|
-
export { Blackboard, blackboard as default
|
|
140
|
+
export { Blackboard, blackboard as default };
|