svg-pan-zoom icon indicating copy to clipboard operation
svg-pan-zoom copied to clipboard

Any implementation with an Angular 4+

Open rabinrai44 opened this issue 6 years ago • 3 comments

Hi, All Contributors! I'm working on Angular 4 project with SVG map and svg-pan-zoom js. However, I'd like to select specific pan id and zoom that pan, but while working it's not working what I expected. If you anyone has using it and implementing/used before please would you like to be share with me or want to give to any hints or help would be much appreciated!

Here are some things that I want to implement with svg-pan-zoom.js

  • The app(fun-game) is built with an Angular 4
  • The app(fun-game) is all SVG-map and there are many regions and countries
  • Each region have a unique name

The app will display before start new-game>game-mode>region-select>display the selected regions. Note: there might multiple regions selectable. some regions are small and some big so I would like to zoom pan that will be where a user selected before starting a game. I searched many examples but not exactly found that I want to implement with svg-pan-zoom, only found with a vanilla js. If there are any other great example/articles that would be fine as well. It seems a difficult problem for now!

If the issue description is not well let me know what kind of information do I need to provide for accomplish the goal.

Thanks, Rabin

rabinrai44 avatar Nov 30 '18 02:11 rabinrai44

hi @rabinrai44

import * as svgPanZoomNamespace from 'svg-pan-zoom';
import { panZoomConfig } from '../configs/svg-pan-zoom';

@Component({
    selector: 'schema-map',
    templateUrl: './schema-map.component.html'
})

export class schemeMap implements OnInit {
    @ViewChild('scene') public scene: ElementRef;
    public scheme: SvgPanZoom.Instance;
    public ngOnInit(): void {
        this.scheme = svgPanZoom(this.scene.nativeElement, panZoomConfig);
    }
}
<shema-map>
<svg [attr.viewBox]="'0 0 ' + map.width + ' ' + map.height"
     #scene 
     class="svg-map">

    <g class="svg-pan-zoom_viewport">

    <g *ngIf="shapesPath"
             [attr.transform]="shapesPath['position']">
              <g *ngFor="let figure of shapesPath['path']"
                  [attr.transform]="figure.transform"
                 [attr.fill-opacity]="figure.fillOpacity"
                 [attr.opacity]="figure.opacity">
                  <g (click)="blablaClick('please-scale-this-section-map')">
                      <path d="" />
                  </g>

                  <g *ngIf="blaClickTrue">
                     new svg data this for scale
                  </g>
              </g>
          </g>

    </g>
</svg>
</shema-map>

you can tap for zone and calc postition and scale for zoom clickingZone in full window

ps angular5+

howtomake avatar Nov 30 '18 21:11 howtomake

hello, @howtomake, Thank you for the reply with an example. It seems like to a good example though, But I'm wondering what you imported import { panZoomConfig } from '../configs/svg-pan-zoom'; how I can find that file and what does that? I don't have that file, unfortunately, could give me hints that I can generate or copy from? or if I'm not understanding about the svg-pan-zoom.

I've set up little different approach for applying svg-pan-zoom. I would like to share that might help you to understand what I'm looking.. Here is an svg doc inside the map-container.component.html there are so many contents (g) I just post couple code that you can look at how I can setup correctly

<svg
     width="100vw"
   height="100vh"
   id="europeanMap" 
  <defs
     id="defs3213">   
    <filter
       inkscape:label="Opacity"
       style="color-interpolation-filters:sRGB;"
       id="filter152">
      <feColorMatrix
         values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 5 -1 "
         result="colormatrix"
         id="feColorMatrix148" />
      <feComposite
         in2="colormatrix"
         operator="arithmetic"
         k2="0.5"
         result="composite"
         id="feComposite150" />
    </filter>
    <clipPath
       clipPathUnits="userSpaceOnUse"
       id="clipPath129">
      <rect
         style="fill:#ffeeaa"
         id="rect131"
         width="500"
         height="633.33331"       

  x="316.0946"
         y="181.64435" />
    </clipPath>
  </defs>
  <metadata
     id="metadata3216">
  </metadata>
  <g
     inkscape:label="Europe"
     inkscape:groupmode="layer"
     id="layer1"
     transform="translate(-283.68719,-87.199905)">
    <image
       y="170.33755"
       x="316.20566"
       id="image97"
       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAowAAAMdCAYAAAARfieEAAAAAXNSR0IArs4c6QAAAARnQU1BA"
       preserveAspectRatio="none"
       height="645.42859"
       width="527.57147" />
<g
       id="Scandinavia"
       name="Region"
       style="filter:url(#filter128)">
      <path
         sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccc"
         inkscape:connector-curvature="0"
         style="opacity:1;fill-rule:nonzero;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter128)"
         name="Country"
         id="Iceland"
         d="m 343.63966,270.36402 c -0.39622,-0.13206 -z"
         region_id="5"
         tabindex="0"
         class="country" />
      <path
         style="filter:url(#filter128)"
         sodipodi:nodetypes="ccccccccccccccscscccscscscccscscccccscccc"
         inkscape:connector-curvature="0"
         name="Country"
         id="Sweden"
         d="m 608.47916,472.73971 c 0.26415,-0.79243 -0.26414,-z"
         region_id="5"
         tabindex="0"
         class="country" />     
      
    </g>
</svg>
// Map-Container-Component it handles all the functionality for map
manageSubscriptions(): void {
    this.mapService.zoomInCallSource$.subscribe(() => this.zoomIn());
    this.mapService.zoomOutCallSource$.subscribe(() => this.zoomOut());
    this.mapService.resizeCallSource$.subscribe(() => this.windowResize());
    this.gameService.selectedRegions$
      .takeUntil(this.ngUnsubscribe)
      .subscribe((regions: HTMLElement[]) => {
        if (!!regions) {
          // find ui bounds for selectedRegions
          this.zoomPan(regions);
          // this.svgPanZoom.zoomBy(3);
        }
      });
  }
// Default Zoom level for selected Regions
  public zoomPan(selectedRegions: HTMLElement[]) {
    selectedRegions.filter(regions => {
      if (regions.id !== null) {
        const region: any = document.querySelector('#' + regions.id);
        // get the bounds of this region
        console.log('region bounds: ', region);
        const regionBound = region.getBBox();

        // const newZoom = {
        //   x: Math.min(newZoom.x, regionBound.x),
        //   y: Math.min(newZoom.y, regionBound.y),
        //   xEnd: Math.max(newZoom.xEnd, regionBound.x + regionBound.width),
        //   yEnd: Math.max(newZoom.yEnd, regionBound.y + regionBound.height)
        // };
        // console.log(this.svgPanZoom.pan);
      }
    });
  }

above the custom function called zoomPan(), it takes 1 argument that will be dynamically selected regions it may have multiple regions as well. I want to implement the functionality is there, when it takes the regions and select the bounds from that regions and calculate the bounds and zoom the that selected regions that are my goal. My code might be weird because I'm new with an Angular.

Thank you, Rabin

rabinrai44 avatar Dec 01 '18 05:12 rabinrai44

Can you provide an angular online demo? @howtomake

smile2014 avatar Nov 06 '20 08:11 smile2014