Skip to content

Commit 6eeb909

Browse files
committed
Scroll the design mode cursor into view
And scroll the character into view when design mode is exited.
1 parent 144f9e2 commit 6eeb909

1 file changed

Lines changed: 55 additions & 35 deletions

File tree

src/Scene.js

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -102,59 +102,72 @@ class Scene extends React.Component<SceneProps, {}> {
102102
}
103103
}
104104

105+
/* istanbul ignore next */
105106
scrollCharacterIntoView() {
106-
// Required to avoid the lack of scrollIntoView on SVG elements in Safari.
107-
/* istanbul ignore next */
108-
if (this.sceneRef.current != null && this.sceneSvgRef.current != null) {
107+
this.scrollSquareIntoView(
108+
this.props.characterState.xPos,
109+
this.props.characterState.yPos
110+
);
111+
}
112+
113+
/* istanbul ignore next */
114+
scrollDesignModeCursorIntoView() {
115+
this.scrollSquareIntoView(
116+
this.props.designModeCursorState.x,
117+
this.props.designModeCursorState.y
118+
);
119+
}
109120

121+
/* istanbul ignore next */
122+
scrollSquareIntoView(x: number, y: number) {
123+
// Check to see if the specified square is visible. If not, scroll to
124+
// bring it into view. We do this ourselves for two reasons:
125+
//
126+
// 1. On Safari, scrollIntoView doesn't work on SVG elements (C2LC-347)
127+
// 2. On Firefox, scrollIntoView seems to scroll to the centre of
128+
// an element rather than bringing it completely into view (C2LC-343)
129+
130+
if (this.sceneRef.current != null && this.sceneSvgRef.current != null) {
110131
const sceneElem = this.sceneRef.current;
111132
const sceneSvgElem = this.sceneSvgRef.current;
112133

113134
const sceneBounds = sceneElem.getBoundingClientRect();
114135
const sceneSvgBounds = sceneSvgElem.getBoundingClientRect();
115136

116-
// Calculate the grid cell width in pixels by dividing the width
137+
// Calculate the grid square width in pixels by dividing the width
117138
// of the scene in pixels by the number of columns in the scene
118-
const cellWidth = sceneSvgBounds.width / this.props.dimensions.getWidth();
119-
// Calculate the grid cell height in pixels by dividing the height
120-
// of the scene in pixels by the number of rows in the scene
121-
const cellHeight = sceneSvgBounds.height / this.props.dimensions.getHeight();
139+
const squareW = sceneSvgBounds.width / this.props.dimensions.getWidth();
122140

123-
// Check to see if the character is visible. If not, scroll to
124-
// bring it into view. We do this ourselves for two reasons:
125-
//
126-
// 1. On Safari, scrollIntoView doesn't work on SVG elements
127-
// (C2LC-347)
128-
// 2. On Firefox, scrollIntoView seems to scroll to the center of
129-
// the character rather than bringing it completely into view
130-
// (C2LC-343)
141+
// Calculate the grid square height in pixels by dividing the height
142+
// of the scene in pixels by the number of rows in the scene
143+
const squareH = sceneSvgBounds.height / this.props.dimensions.getHeight();
131144

132145
// We add some padding to the position checking to ensure that we
133-
// always leave some room between the character and the edge of the
134-
// scene (unless we are in the first or last row/col)
135-
const paddingH = 0.75 * cellWidth;
136-
const paddingV = 0.75 * cellHeight;
146+
// always leave some room between the target square and the edge of
147+
// the scene (unless we are in the first or last row/col)
148+
const paddingH = 0.75 * squareW;
149+
const paddingV = 0.75 * squareH;
137150

138-
// Calculate the location of the grid cell that the character is on
139-
const cellLeft = (this.props.characterState.xPos - this.props.dimensions.getMinX()) * cellWidth;
140-
const cellRight = cellLeft + cellWidth;
141-
const cellTop = (this.props.characterState.yPos - this.props.dimensions.getMinY()) * cellHeight;
142-
const cellBottom = cellTop + cellHeight;
151+
// Calculate the bounds of the target square to scroll into view
152+
const targetSquareLeft = (x - this.props.dimensions.getMinX()) * squareW;
153+
const targetSquareRight = targetSquareLeft + squareW;
154+
const targetSquareTop = (y - this.props.dimensions.getMinY()) * squareH;
155+
const targetSquareBottom = targetSquareTop + squareH;
143156

144-
if (cellLeft - paddingH < sceneElem.scrollLeft) {
157+
if (targetSquareLeft - paddingH < sceneElem.scrollLeft) {
145158
// Off screen to the left
146-
sceneElem.scrollLeft = cellLeft - paddingH;
147-
} else if (cellRight + paddingH > sceneElem.scrollLeft + sceneBounds.width) {
159+
sceneElem.scrollLeft = targetSquareLeft - paddingH;
160+
} else if (targetSquareRight + paddingH > sceneElem.scrollLeft + sceneBounds.width) {
148161
// Off screen to the right
149-
sceneElem.scrollLeft = cellRight + paddingH - sceneBounds.width;
162+
sceneElem.scrollLeft = targetSquareRight + paddingH - sceneBounds.width;
150163
}
151164

152-
if (cellTop - paddingV < sceneElem.scrollTop) {
165+
if (targetSquareTop - paddingV < sceneElem.scrollTop) {
153166
// Off screen above
154-
sceneElem.scrollTop = cellTop - paddingV;
155-
} else if (cellBottom + paddingV > sceneElem.scrollTop + sceneBounds.height) {
167+
sceneElem.scrollTop = targetSquareTop - paddingV;
168+
} else if (targetSquareBottom + paddingV > sceneElem.scrollTop + sceneBounds.height) {
156169
// Off screen below
157-
sceneElem.scrollTop = cellBottom + paddingV - sceneBounds.height;
170+
sceneElem.scrollTop = targetSquareBottom + paddingV - sceneBounds.height;
158171
}
159172
}
160173
}
@@ -308,14 +321,21 @@ class Scene extends React.Component<SceneProps, {}> {
308321
);
309322
}
310323

324+
/* istanbul ignore next */
311325
componentDidUpdate(prevProps) {
312326
if (prevProps.characterState.xPos !== this.props.characterState.xPos
313327
|| prevProps.characterState.yPos !== this.props.characterState.yPos) {
314328
this.scrollCharacterIntoView();
315-
}
316-
if (prevProps.runningState !== this.props.runningState
329+
} else if (prevProps.runningState !== this.props.runningState
317330
&& this.props.runningState === 'running') {
318331
this.scrollCharacterIntoView();
332+
} else if (prevProps.customBackgroundDesignMode !== this.props.customBackgroundDesignMode
333+
&& this.props.customBackgroundDesignMode === false) {
334+
this.scrollCharacterIntoView();
335+
} else if (this.props.customBackgroundDesignMode === true
336+
&& (prevProps.designModeCursorState.x !== this.props.designModeCursorState.x
337+
|| prevProps.designModeCursorState.y !== this.props.designModeCursorState.y)) {
338+
this.scrollDesignModeCursorIntoView();
319339
}
320340
}
321341
}

0 commit comments

Comments
 (0)