@@ -126,14 +126,14 @@ suite('Scrolling into view', function () {
126126 return blockBounds ;
127127 } ) ;
128128 console . log ( "block bounds:" , blockBounds ) ;
129- const blockPosition = await this . browser . execute ( ( ) => {
129+ const [ blockPosition , blockRelative ] = await this . browser . execute ( ( ) => {
130130 const workspace = Blockly . getMainWorkspace ( ) as Blockly . WorkspaceSvg ;
131131 const block = workspace . getBlocksByType (
132132 'controls_if' ,
133133 ) [ 0 ] as Blockly . BlockSvg ;
134- return block . getRelativeToSurfaceXY ( ) ;
134+ return [ block . getRelativeToSurfaceXY ( ) , getRelativeXY ( block . getSvgRoot ( ) ) ] ;
135135 } ) ;
136- console . log ( "block position:" , blockPosition ) ;
136+ console . log ( "block position:" , blockPosition , "relative:" , blockRelative ) ;
137137 const [ blockParentBounds , blockParentId ] = await this . browser . execute ( ( ) => {
138138 const workspace = Blockly . getMainWorkspace ( ) as Blockly . WorkspaceSvg ;
139139 const block = workspace . getBlocksByType (
@@ -173,3 +173,99 @@ suite('Scrolling into view', function () {
173173 chai . assert . isTrue ( inViewport ) ;
174174 } ) ;
175175} ) ;
176+
177+ const XY_REGEX = / t r a n s l a t e \( \s * ( [ - + \d . e ] + ) ( [ , ] \s * ( [ - + \d . e ] + ) \s * ) ? / ;
178+ const XY_STYLE_REGEX =
179+ / t r a n s f o r m : \s * t r a n s l a t e (?: 3 d ) ? \( \s * ( [ - + \d . e ] + ) \s * p x ( [ , ] \s * ( [ - + \d . e ] + ) \s * p x ) ? / ;
180+
181+ function getRelativeXY ( element : Element ) : Coordinate {
182+ const xy = new Coordinate ( 0 , 0 ) ;
183+ // First, check for x and y attributes.
184+ // Checking for the existence of x/y properties is faster than getAttribute.
185+ // However, x/y contains an SVGAnimatedLength object, so rely on getAttribute
186+ // to get the number.
187+ const x = ( element as any ) . x && element . getAttribute ( 'x' ) ;
188+ const y = ( element as any ) . y && element . getAttribute ( 'y' ) ;
189+ if ( x ) {
190+ xy . x = parseInt ( x ) ;
191+ }
192+ if ( y ) {
193+ xy . y = parseInt ( y ) ;
194+ }
195+ // Second, check for transform="translate(...)" attribute.
196+ const transform = element . getAttribute ( 'transform' ) ;
197+ const r = transform && transform . match ( XY_REGEX ) ;
198+ if ( r ) {
199+ xy . x += Number ( r [ 1 ] ) ;
200+ if ( r [ 3 ] ) {
201+ xy . y += Number ( r [ 3 ] ) ;
202+ }
203+ }
204+
205+ // Then check for style = transform: translate(...) or translate3d(...)
206+ const style = element . getAttribute ( 'style' ) ;
207+ if ( style && style . includes ( 'translate' ) ) {
208+ const styleComponents = style . match ( XY_STYLE_REGEX ) ;
209+ if ( styleComponents ) {
210+ xy . x += Number ( styleComponents [ 1 ] ) ;
211+ if ( styleComponents [ 3 ] ) {
212+ xy . y += Number ( styleComponents [ 3 ] ) ;
213+ }
214+ }
215+ }
216+ return xy ;
217+ }
218+
219+ class Coordinate {
220+ constructor (
221+ public x : number ,
222+ public y : number ,
223+ ) { }
224+
225+ clone ( ) : Coordinate {
226+ return new Coordinate ( this . x , this . y ) ;
227+ }
228+
229+ scale ( s : number ) : Coordinate {
230+ this . x *= s ;
231+ this . y *= s ;
232+ return this ;
233+ }
234+
235+ translate ( tx : number , ty : number ) : Coordinate {
236+ this . x += tx ;
237+ this . y += ty ;
238+ return this ;
239+ }
240+
241+ static equals ( a ?: Coordinate | null , b ?: Coordinate | null ) : boolean {
242+ if ( a === b ) {
243+ return true ;
244+ }
245+ if ( ! a || ! b ) {
246+ return false ;
247+ }
248+ return a . x === b . x && a . y === b . y ;
249+ }
250+
251+ static distance ( a : Coordinate , b : Coordinate ) : number {
252+ const dx = a . x - b . x ;
253+ const dy = a . y - b . y ;
254+ return Math . sqrt ( dx * dx + dy * dy ) ;
255+ }
256+
257+ static magnitude ( a : Coordinate ) : number {
258+ return Math . sqrt ( a . x * a . x + a . y * a . y ) ;
259+ }
260+
261+ static difference (
262+ a : Coordinate | SVGPoint ,
263+ b : Coordinate | SVGPoint ,
264+ ) : Coordinate {
265+ return new Coordinate ( a . x - b . x , a . y - b . y ) ;
266+ }
267+
268+ static sum ( a : Coordinate | SVGPoint , b : Coordinate | SVGPoint ) : Coordinate {
269+ return new Coordinate ( a . x + b . x , a . y + b . y ) ;
270+ }
271+ }
0 commit comments