Skip to content

Commit 31932cf

Browse files
committed
Try to improve mobile experience
1 parent 8921ab7 commit 31932cf

File tree

1 file changed

+102
-7
lines changed

1 file changed

+102
-7
lines changed

frontend/packages/common/TraceViewer.js

Lines changed: 102 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,86 @@ export const TraceViewer = ({traceData,width, height, onSelect}) => {
166166
setMouseDownLocation(e.evt.layerX)
167167
}
168168
}
169+
const [lastTouchX, setLastTouchX] = useState(null)
170+
171+
const handleTouchStart = (e) => {
172+
if (e.evt.touches.length === 1) {
173+
setLastTouchX(e.evt.touches[0].clientX);
174+
}
175+
}
176+
const [lastPinchDistance, setLastPinchDistance] = useState(null);
177+
const handleTouchMove = (e) => {
178+
const touches = e.evt.touches;
179+
180+
if (touches.length === 2) {
181+
e.evt.preventDefault(); // Prevent page scroll
182+
183+
const dx = touches[0].clientX - touches[1].clientX;
184+
const dy = touches[0].clientY - touches[1].clientY;
185+
const distance = Math.sqrt(dx * dx + dy * dy);
186+
187+
const centerX = (touches[0].clientX + touches[1].clientX) / 2;
188+
const layerX = centerX - offsetX;
189+
const timePosition = layerX / scaleX + timeRange[0];
190+
191+
if (lastPinchDistance) {
192+
const scaleFactor = distance / lastPinchDistance;
193+
let newScaleX = scaleX * scaleFactor;
194+
195+
if (newScaleX < initialScaleX) {
196+
newScaleX = initialScaleX;
197+
setScaleX(newScaleX);
198+
setTimeRange([0, maxTime]);
199+
} else {
200+
const newPosition = (timePosition - timeRange[0]) * newScaleX;
201+
const diff = layerX - newPosition;
202+
let newTimeStart = timeRange[0] - diff / newScaleX;
203+
let newTimeEnd = newTimeStart + dataWidth / newScaleX;
204+
205+
if (newTimeEnd > maxTime) {
206+
newTimeStart -= newTimeEnd - maxTime;
207+
newTimeEnd = maxTime;
208+
}
209+
210+
if (newTimeStart < 0) {
211+
newTimeStart = 0;
212+
newTimeEnd = dataWidth / newScaleX;
213+
}
214+
215+
setScaleX(newScaleX);
216+
setTimeRange([newTimeStart, newTimeEnd]);
217+
}
218+
}
219+
220+
setLastPinchDistance(distance);
221+
} else if (touches.length === 1 && lastTouchX !== null) {
222+
// one-finger pan
223+
const currentX = touches[0].clientX;
224+
const deltaX = currentX - lastTouchX;
225+
226+
let newTimeStart = timeRange[0] - deltaX / scaleX;
227+
let newTimeEnd = newTimeStart + dataWidth / scaleX;
228+
229+
if (newTimeStart < 0) {
230+
newTimeStart = 0;
231+
newTimeEnd = dataWidth / scaleX;
232+
}
233+
if (newTimeEnd > maxTime) {
234+
newTimeStart -= newTimeEnd - maxTime;
235+
newTimeEnd = maxTime;
236+
}
237+
238+
setTimeRange([newTimeStart, newTimeEnd]);
239+
setLastTouchX(currentX);
240+
}
241+
}
242+
243+
244+
const handleTouchEnd = () => {
245+
setLastTouchX(null);
246+
setLastPinchDistance(null);
247+
}
248+
169249
const [rows, setRows] = useState([]);
170250

171251

@@ -216,10 +296,25 @@ export const TraceViewer = ({traceData,width, height, onSelect}) => {
216296
//}, []);
217297
return (
218298
<div>
219-
<div style={{maxHeight: height-60, overflowY: "auto"}} title={"CTRL+Scroll for Zooming, Drag and Drop for Moving"}>
220-
<Stage width={canvasWidth} height={window.innerHeight}
221-
onWheel={(e) => handleScroll(e)} onMouseDown={handleMouseDown} onMouseUp={handleMouseUp}
222-
onMouseMove={handleMouseMove}>
299+
<div
300+
style={{
301+
maxHeight: height - 60,
302+
overflowY: "auto",
303+
touchAction: "none", // prevent browser gestures like zoom
304+
WebkitOverflowScrolling: "touch" // keep native scrolling on parent
305+
}}
306+
title={"CTRL+Scroll for Zooming, Drag and Drop for Moving"}
307+
> <Stage
308+
width={canvasWidth}
309+
height={window.innerHeight}
310+
onWheel={(e) => handleScroll(e)}
311+
onMouseDown={handleMouseDown}
312+
onMouseUp={handleMouseUp}
313+
onMouseMove={handleMouseMove}
314+
onTouchStart={handleTouchStart}
315+
onTouchMove={handleTouchMove}
316+
onTouchEnd={handleTouchEnd}
317+
>
223318
<Layer>
224319
{
225320
threads.map((t, i) => <Group>
@@ -248,14 +343,14 @@ export const TraceViewer = ({traceData,width, height, onSelect}) => {
248343
var correctedDuration = d.start < timeRange[0] ? duration - (timeRange[0] - d.start) : duration
249344
correctedDuration = d.start + duration > timeRange[1] ? duration - (d.start + duration - timeRange[1]) : correctedDuration
250345
if (duration == 0) {
251-
return <Circle x={correctedStart * scaleX+offsetX} y={d.row * rowOffset+offsetY} radius={2} fill={"black"} onClick={()=> selectEvent(d)}></Circle>
346+
return <Circle x={correctedStart * scaleX+offsetX} y={d.row * rowOffset+offsetY} radius={2} fill={"black"} onClick={()=> selectEvent(d)} onTap={()=>selectEvent(d)}></Circle>
252347
} else {
253348
let extraText = formatExtraText(d)
254-
return (<Group onClick={() => selectEvent(d)}>
349+
return (<Group onClick={() => selectEvent(d)} onTap={()=>selectEvent(d)}>
255350
<Rect x={offsetX + correctedStart * scaleX} y={offsetY + d.row * rowOffset} height={15}
256351
width={correctedDuration * scaleX}
257352
fill={d.category=== "Ignore" ? "white":categoryColors[d.category + "::" + d.name]} stroke={"gray"} strokeWidth={0.4}
258-
onClick={() => {}}></Rect>
353+
onClick={() => {}} onTap={()=>{}}></Rect>
259354

260355
<Text x={offsetX + correctedStart * scaleX} y={offsetY + d.row * rowOffset}
261356
text={`${d.name} (${extraText})`}

0 commit comments

Comments
 (0)