简体   繁体   中英

Angular and SVG: how to dynamically load custom components?

I need to dynamically load SVG items.

The items are very simple. Template:

<svg:rect [attr.x]="x" [attr.y]="y" width="10" height="10" />

Class:

export class DraggableSvgItemComponent implements OnInit {

  x: number = 0;
  y: number = 0;

  constructor() { }

  ngOnInit() {
  }

}

This is how the container component template looks like:

<svg attr.height.px="{{height}}" attr.width.px="{{width}}">
    <svg:g app-draggable-svg-item *ngFor="let d of draggables" />
</svg>

And this is how I generate the items form the container component:

// commands <- load fun stuff with x and y coordinates
var toSet = new Array<DraggableSvgItemComponent>();
commands.forEach((value) => {
  if (value instanceof ZPL2.GraphicShapeBase) {
    var toAdd = new DraggableSvgItemComponent();
    toAdd.x = value.x;
    toAdd.y = value.y;

    console.log(toAdd);
    toSet.push(toAdd);
  }
});

this.draggables = toSet;

The console log shows that x and y have non zero values: DraggableSvgItemComponent {x: 100, y: 50} but the output is a svg with a square in the top-left corner and the values of x and y are 0.

If I put the <rect> directly in the canvas without using a different component it works but I need it because I have to deal with different svg stuff.

What am I doing wrong with the value bindings?

You shouldn't have to create the DraggableSvgItemComponent components in code. They will be created as children of the <svg:g> elements if you define the component selector as an attribute selector. The x and y properties could be marked with the Input decorator to allow data binding.

@Component({
  selector: '[draggable-svg-item]',
  template: `<svg:rect [attr.x]="x" [attr.y]="y" width="10" height="10" />`
})
export class DraggableSvgItemComponent {
  @Input() x: number = 0;
  @Input() y: number = 0;
}

In the parent component, draggables can simply be an array of positions:

export class AppComponent {
  width = 200;
  height = 200;
  draggables = [
    { x: 5, y: 0 },
    { x: 20, y: 30 },
    { x: 0, y: 20 },
    { x: 24, y: 8 },
  ];
}

which are supplied to the child components with property binding:

<svg [attr.height.px]="height" [attr.width.px]="width">
    <svg:g draggable-svg-item [x]="d.x" [y]="d.y" *ngFor="let d of draggables" />
</svg>

See this stackblitz for a demo.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM