@@ -5,7 +5,6 @@ import { Logger } from "typescript-logging";
55import { Color , colorFromHex , colorFromRgba } from "../api/draw/color" ;
66import { Dimension , Point } from "../api/draw/draw.basic" ;
77import { Circle , DrawElement , Ellipse , Line , PolyLine , Rectangle } from "../api/draw/elements" ;
8- import { pairwise } from "../arrays" ;
98import { LoggerFactory } from "../log-config" ;
109import { ElementBuilderFactoryImpl } from "./element.builders.impl" ;
1110import { ElementDragEventMap , ElementResizeEventMap } from "./events" ;
@@ -162,6 +161,24 @@ export interface CanvasFormElement<T extends DrawElement> extends CanvasBorderEl
162161 fillColor : Color ;
163162}
164163
164+ /**
165+ * Describes all four coordinates of a rbox rectangle.
166+ *
167+ * @author Nicolas Schaefli <ns@studer-raimann.ch>
168+ * @since 0.3.6
169+ * @internal
170+ */
171+ interface ClientRBoxCoordinate {
172+ readonly x1 : number ;
173+ readonly y1 : number ;
174+ readonly x2 : number ;
175+ readonly y2 : number ;
176+ readonly x3 : number ;
177+ readonly y3 : number ;
178+ readonly x4 : number ;
179+ readonly y4 : number ;
180+ }
181+
165182/**
166183 * Abstract base implementation of all border elements.
167184 *
@@ -266,6 +283,26 @@ abstract class AbstractCanvasBorderElement<T extends DrawElement> implements Can
266283 }
267284
268285 abstract transform ( ) : T ;
286+
287+ protected getUnrotatedStartCoordinate ( element : svgjs . Element ) : ClientRBoxCoordinate {
288+ const doc : svgjs . Parent = element . parent ( svgjs . Doc ) as svgjs . Parent ;
289+ const box : svgjs . RBox = element . rbox ( doc ) ;
290+ const bbox : svgjs . BBox = element . bbox ( ) ;
291+ // const rotationInRad: number = this.rotation * (Math.PI / 180);
292+ const cartX : number = - ( bbox . w / 2 ) ;
293+ const cartY : number = ( bbox . h / 2 ) ;
294+
295+ return {
296+ x1 : box . cx + cartX ,
297+ x2 : box . cx - cartX ,
298+ x3 : box . cx + cartX ,
299+ x4 : box . cx - cartX ,
300+ y1 : box . cy - cartY ,
301+ y2 : box . cy - cartY ,
302+ y3 : box . cy + cartY ,
303+ y4 : box . cy + cartY
304+ } ;
305+ }
269306}
270307
271308/**
@@ -301,30 +338,36 @@ abstract class AbstractCanvasFormElement<T extends DrawElement> extends Abstract
301338 */
302339export class CanvasPolyLine extends AbstractCanvasBorderElement < PolyLine > {
303340
304- private static readonly POINT_FORMAT_AFTER_TRANSFORMATION : RegExp = / ^ (?: ( \d + ( : ? \. \d + ) ? ) , ( \d + ( : ? \. \d + ) ? ) \s ? ) + $ / ;
305-
306341 private get coordinates ( ) : Array < Point > {
307342
308- // We have a different point format after the polyline transformation ...
309- const points : string = this . element . attr ( "points" ) as string ;
310- if ( CanvasPolyLine . POINT_FORMAT_AFTER_TRANSFORMATION . test ( points ) ) {
311- return points . split ( " " )
312- . map < Array < string > > ( ( it ) => it . split ( "," ) )
313- . map < Point > ( ( it ) => {
314- const [ x , y , z ] : [ number , number , number ] = [ parseFloat ( it [ 0 ] ) , parseFloat ( it [ 1 ] ) , this . element . position ( ) ] ;
343+ const element : svgjs . PolyLine = ( this . element as unknown ) as svgjs . PolyLine ;
344+ const matrix : SVGMatrix = element . ctm ( ) . native ( ) ;
315345
316- return { x, y, z} ;
317- } ) ;
318- }
346+ // Type definintion is wrong the type is in fact Array<Array<number>>
347+ const elementPoints : Array < Array < number > > = ( element . array ( ) . value as unknown ) as Array < Array < number > > ;
319348
320- return pairwise ( ( this . element . attr ( "points" ) as string ) . split ( "," ) )
349+ // @ts -ignore (type definition is no accurate because the type misses the function "createSVGPoint")
350+ const point : SVGPoint = element . doc ( ) . node . createSVGPoint ( ) ;
351+
352+ return elementPoints
321353 . map < Point > ( ( it ) => {
322- const [ x , y , z ] : [ number , number , number ] = [ parseFloat ( it [ 0 ] ) , parseFloat ( it [ 1 ] ) , this . element . position ( ) ] ;
354+
355+ // Transform the coordinates, this is necessary to preserve the rotation.
356+ point . x = it [ 0 ] ;
357+ point . y = it [ 1 ] ;
358+ const transP : SVGPoint = point . matrixTransform ( matrix ) ;
359+
360+ const [ x , y , z ] : [ number , number , number ] = [ transP . x , transP . y , this . element . position ( ) ] ;
323361
324362 return { x, y, z} ;
325363 } ) ;
326364 }
327365
366+ // No rotation needed, because we store the transformed coordinates.
367+ get rotation ( ) : number {
368+ return 0 ;
369+ }
370+
328371 constructor ( private readonly element : svgjs . PolyLine ) {
329372 super ( element ) ;
330373 }
@@ -350,9 +393,10 @@ export class CanvasPolyLine extends AbstractCanvasBorderElement<PolyLine> {
350393export class CanvasRectangle extends AbstractCanvasFormElement < Rectangle > {
351394
352395 private get position ( ) : Point {
396+ const coords : ClientRBoxCoordinate = this . getUnrotatedStartCoordinate ( this . element ) ;
353397 const [ x , y , z ] : [ number , number , number ] = [
354- parseFloat ( this . element . attr ( "x" ) ) ,
355- parseFloat ( this . element . attr ( "y" ) ) ,
398+ coords . x1 ,
399+ coords . y1 ,
356400 this . element . position ( )
357401 ] ;
358402 return { x, y, z} ;
@@ -393,7 +437,8 @@ export class CanvasRectangle extends AbstractCanvasFormElement<Rectangle> {
393437export class CanvasCircle extends AbstractCanvasFormElement < Circle > {
394438
395439 private get position ( ) : Point {
396- const [ x , y , z ] : [ number , number , number ] = [ this . element . x ( ) , this . element . y ( ) , this . element . position ( ) ] ;
440+ const coords : ClientRBoxCoordinate = this . getUnrotatedStartCoordinate ( this . element ) ;
441+ const [ x , y , z ] : [ number , number , number ] = [ coords . x1 , coords . y1 , this . element . position ( ) ] ;
397442 return { x, y, z} ;
398443 }
399444
@@ -428,7 +473,8 @@ export class CanvasCircle extends AbstractCanvasFormElement<Circle> {
428473export class CanvasEllipse extends AbstractCanvasFormElement < Ellipse > {
429474
430475 private get position ( ) : Point {
431- const [ x , y , z ] : [ number , number , number ] = [ this . element . x ( ) , this . element . y ( ) , this . element . position ( ) ] ;
476+ const coords : ClientRBoxCoordinate = this . getUnrotatedStartCoordinate ( this . element ) ;
477+ const [ x , y , z ] : [ number , number , number ] = [ coords . x1 , coords . y1 , this . element . position ( ) ] ;
432478 return { x, y, z} ;
433479 }
434480
@@ -467,17 +513,19 @@ export class CanvasEllipse extends AbstractCanvasFormElement<Ellipse> {
467513export class CanvasLine extends AbstractCanvasBorderElement < Line > {
468514
469515 private get start ( ) : Point {
516+ const coords : ClientRBoxCoordinate = this . getUnrotatedStartCoordinate ( this . element ) ;
470517 return {
471- x : parseFloat ( this . element . attr ( "x1" ) ) ,
472- y : parseFloat ( this . element . attr ( "y1" ) ) ,
518+ x : coords . x1 ,
519+ y : coords . y1 ,
473520 z : this . element . position ( )
474521 } ;
475522 }
476523
477524 private get end ( ) : Point {
525+ const coords : ClientRBoxCoordinate = this . getUnrotatedStartCoordinate ( this . element ) ;
478526 return {
479- x : parseFloat ( this . element . attr ( "x2" ) ) ,
480- y : parseFloat ( this . element . attr ( "y2" ) ) ,
527+ x : coords . x4 ,
528+ y : coords . y4 ,
481529 z : this . element . position ( )
482530 } ;
483531 }
0 commit comments