diff --git a/angular.json b/angular.json
index daa02deb9f77b04e2cb9ccf9839352466f7cdaf5..5482a7544c7eb2f297d410be6b225f995c3b1de9 100644
--- a/angular.json
+++ b/angular.json
@@ -32,7 +32,9 @@
               "node_modules/primeng/resources/primeng.min.css",
               "node_modules/primeng/resources/themes/nova-light/theme.css"
             ],
-            "scripts": [],
+            "scripts": [
+              "node_modules/chartjs-plugin-zoom/chartjs-plugin-zoom.min.js"
+            ],
             "showCircularDependencies": false
           },
           "configurations": {
diff --git a/package-lock.json b/package-lock.json
index 72d12202a4b58cec9399e6f57b455428be2edaf3..23fc51a4600763f6611275c96aae80776545573a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3417,6 +3417,14 @@
         "color-name": "^1.0.0"
       }
     },
+    "chartjs-plugin-zoom": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-0.7.2.tgz",
+      "integrity": "sha512-5AtMCjlBlRsA/vxlvcBsAYKbkk0tVYE6+XX9M9LE6aSqbjqGR5NUQwYH0YvvvpmJjTZfB+HDhHaaGxJ/8aGaaw==",
+      "requires": {
+        "hammerjs": "^2.0.8"
+      }
+    },
     "cheerio": {
       "version": "1.0.0-rc.2",
       "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz",
diff --git a/package.json b/package.json
index e39372066ebc30346e11099c74ee57aad18651c9..d3fda3c44d5c03a20718e9a468395292af30a4d4 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,7 @@
     "@types/pako": "^1.0.1",
     "@types/sprintf-js": "^1.1.2",
     "angular2-chartjs": "^0.5.1",
+    "chartjs-plugin-zoom": "^0.7.2",
     "cordova-android": "^8.0.0",
     "cordova-plugin-device": "^2.0.2",
     "core-js": "^2.6.5",
diff --git a/src/app/components/pab-profile-graph/pab-profile-graph.component.html b/src/app/components/pab-profile-graph/pab-profile-graph.component.html
index bfbe7c551a39c3c855317577d5c39fd64040f610..28b4288fd2bbf48bcedac4e7a4ed9375a2f91cc1 100644
--- a/src/app/components/pab-profile-graph/pab-profile-graph.component.html
+++ b/src/app/components/pab-profile-graph/pab-profile-graph.component.html
@@ -1,13 +1,16 @@
 <div class="graph-results-container" #graphProfile fxLayout="row wrap" fxLayoutAlign="center center">
     <div fxFlex="1 1 100%">
         <div class="graph-profile-buttons">
-            <button mat-icon-button (click)="exportAsImage(graphProfile)">
+            <button mat-icon-button (click)="resetZoom()" [disabled]="! zoomWasChanged" [title]="uitextResetZoomTitle">
+                <mat-icon color="primary">replay</mat-icon>
+            </button>
+            <button mat-icon-button (click)="exportAsImage(graphProfile)" [title]="uitextExportImageTitle">
                 <mat-icon color="primary">image</mat-icon>
             </button>
-            <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(graphProfile)">
+            <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(graphProfile)" [title]="uitextEnterFSTitle">
                 <mat-icon color="primary" class="scaled12">fullscreen</mat-icon>
             </button>
-            <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()">
+            <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()" [title]="uitextExitFSTitle">
                 <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon>
             </button>
         </div>
@@ -15,4 +18,4 @@
         <chart type="scatter" [data]="graph_data" [options]="graph_options" #graphChart>
         </chart>
     </div>
-</div>
+</div>
\ No newline at end of file
diff --git a/src/app/components/pab-profile-graph/pab-profile-graph.component.scss b/src/app/components/pab-profile-graph/pab-profile-graph.component.scss
index 6382f8a709f582892c2411aa07c1701793d52dad..465866a6ce03ef7eaa710c1e4545563c44d2e9dd 100644
--- a/src/app/components/pab-profile-graph/pab-profile-graph.component.scss
+++ b/src/app/components/pab-profile-graph/pab-profile-graph.component.scss
@@ -19,5 +19,11 @@
                 transform: scale(1.2);
             }
         }
+
+        &:disabled {
+            mat-icon {
+                color: #bfbfbf;
+            }
+        }
     }
 }
diff --git a/src/app/components/pab-profile-graph/pab-profile-graph.component.ts b/src/app/components/pab-profile-graph/pab-profile-graph.component.ts
index 9c61cf60928e22db75be7fb878fe3b0c186e27dc..de364b5e3a6c04d9ec1772460f3d74580ced18cb 100644
--- a/src/app/components/pab-profile-graph/pab-profile-graph.component.ts
+++ b/src/app/components/pab-profile-graph/pab-profile-graph.component.ts
@@ -1,4 +1,6 @@
-import { Component } from "@angular/core";
+import { Component, ViewChild, ChangeDetectorRef } from "@angular/core";
+
+import { ChartComponent } from "angular2-chartjs";
 
 import { ApplicationSetupService } from "../../services/app-setup/app-setup.service";
 import { I18nService } from "../../services/internationalisation/internationalisation.service";
@@ -14,6 +16,9 @@ import { PabResults } from "../../results/pab-results";
 })
 export class PabProfileGraphComponent extends ResultsComponent {
 
+    @ViewChild(ChartComponent)
+    private chartComponent;
+
     private _results: PabResults;
 
     /** size of the longest variable value */
@@ -22,6 +27,8 @@ export class PabProfileGraphComponent extends ResultsComponent {
     /** inferred extended values list for each variating parameter */
     private varValues = [];
 
+    private _zoomWasChanged = false;
+
     /*
      * config du graphe
      */
@@ -50,7 +57,8 @@ export class PabProfileGraphComponent extends ResultsComponent {
 
     public constructor(
         private appSetupService: ApplicationSetupService,
-        private intlService: I18nService
+        private intlService: I18nService,
+        private cd: ChangeDetectorRef
     ) {
         super();
         const nDigits = this.appSetupService.displayDigits;
@@ -79,6 +87,24 @@ export class PabProfileGraphComponent extends ResultsComponent {
                 }
             }]
         };
+        // enable zoom and pan (using "chartjs-plugin-zoom" package)
+        const that = this;
+        this.graph_options["plugins"] = {
+            zoom: {
+                pan: {
+                    enabled: false, // conflicts with drag zoom
+                    mode: "xy",
+                },
+                zoom: {
+                    enabled: true,
+                    drag: true, // conflicts with pan; set to false to enable mouse wheel zoom
+                    mode: "xy",
+                    // percentage of zoom on a wheel event
+                    // speed: 0.1,
+                    onZoomComplete: function(t: any) { return function() { t.zoomComplete(); }; }(that)
+                }
+            }
+        };
     }
 
     public set results(r: PabResults) {
@@ -109,6 +135,15 @@ export class PabProfileGraphComponent extends ResultsComponent {
         }
     }
 
+    private zoomComplete() {
+        this._zoomWasChanged = true;
+        this.cd.detectChanges();
+    }
+
+    public get zoomWasChanged(): boolean {
+        return this._zoomWasChanged;
+    }
+
     public updateView() {
         this.generateScatterGraph();
     }
@@ -134,33 +169,6 @@ export class PabProfileGraphComponent extends ResultsComponent {
                 showLine: "true"
             });
         }
-
-        /* const that = this;
-        this.graph_options["tooltips"] = {
-            displayColors: false,
-            callbacks: {
-                title: (tooltipItems, data) => {
-                    return this.chartY + " = " + Number(tooltipItems[0].yLabel).toFixed(nDigits);
-                },
-                label: (tooltipItem, data) => {
-                    const lines: string[] = [];
-                    const nbLines = that._results.getVariatingParametersSymbols().length;
-                    for (const v of that._results.getVariatingParametersSymbols()) {
-                        const series = that._results.getValuesSeries(v);
-                        const line = v + " = " + series[tooltipItem.index].toFixed(nDigits);
-                        if (v === this.chartX) {
-                            if (nbLines > 1) {
-                                lines.unshift("");
-                            }
-                            lines.unshift(line);
-                        } else {
-                            lines.push(line);
-                        }
-                    }
-                    return lines;
-                }
-            }
-        }; */
     }
 
     public exportAsImage(element: HTMLDivElement) {
@@ -170,6 +178,27 @@ export class PabProfileGraphComponent extends ResultsComponent {
         }); // defaults to image/png
     }
 
+    public resetZoom() {
+        this.chartComponent.chart.resetZoom();
+        this._zoomWasChanged = false;
+    }
+
+    public get uitextResetZoomTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_RESET_ZOOM");
+    }
+
+    public get uitextExportImageTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_EXPORT_IMAGE");
+    }
+
+    public get uitextEnterFSTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_ENTER_FS");
+    }
+
+    public get uitextExitFSTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_EXIT_FS");
+    }
+
     private getXSeries(): string[] {
         const data: string[] = [];
         const nDigits = this.appSetupService.displayDigits;
diff --git a/src/app/components/results-graph/results-graph.component.html b/src/app/components/results-graph/results-graph.component.html
index c30eebd7b950b4b1df94e68a27a8b31ed4c7ae61..1c15bdcc25844e4fcb2681d0ed6559a9757eb38d 100644
--- a/src/app/components/results-graph/results-graph.component.html
+++ b/src/app/components/results-graph/results-graph.component.html
@@ -1,13 +1,16 @@
 <div class="graph-results-container" #graphResults fxLayout="row wrap" fxLayoutAlign="center center">
     <div fxFlex="1 1 100%">
         <div class="graph-results-buttons">
-            <button mat-icon-button (click)="exportAsImage(graphResults)">
+            <button mat-icon-button (click)="resetZoom()" [disabled]="! zoomWasChanged" [title]="uitextResetZoomTitle">
+                <mat-icon color="primary">replay</mat-icon>
+            </button>
+            <button mat-icon-button (click)="exportAsImage(graphResults)" [title]="uitextExportImageTitle">
                 <mat-icon color="primary">image</mat-icon>
             </button>
-            <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(graphResults)">
+            <button mat-icon-button *ngIf="! isFullscreen" (click)="setFullscreen(graphResults)" [title]="uitextEnterFSTitle">
                 <mat-icon color="primary" class="scaled12">fullscreen</mat-icon>
             </button>
-            <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()">
+            <button mat-icon-button *ngIf="isFullscreen" (click)="exitFullscreen()" [title]="uitextExitFSTitle">
                 <mat-icon color="primary" class="scaled12">fullscreen_exit</mat-icon>
             </button>
         </div>
diff --git a/src/app/components/results-graph/results-graph.component.scss b/src/app/components/results-graph/results-graph.component.scss
index c50b430fde0e544b56c71b98f899ce694674414b..4eab50fee6ca30b52c952b3aed76d350a987e95f 100644
--- a/src/app/components/results-graph/results-graph.component.scss
+++ b/src/app/components/results-graph/results-graph.component.scss
@@ -19,6 +19,12 @@
                 transform: scale(1.2);
             }
         }
+
+        &:disabled {
+            mat-icon {
+                color: #bfbfbf;
+            }
+        }
     }
 }
 
diff --git a/src/app/components/results-graph/results-graph.component.ts b/src/app/components/results-graph/results-graph.component.ts
index 7e775c89a5dd14cd0f761a21cb7ea25b6326f6d5..abda1f85a7f479a5189ca28114d2c81b37d21c02 100644
--- a/src/app/components/results-graph/results-graph.component.ts
+++ b/src/app/components/results-graph/results-graph.component.ts
@@ -1,4 +1,6 @@
-import { Component, ViewChild, AfterContentInit, OnInit } from "@angular/core";
+import { Component, ViewChild, AfterContentInit, ChangeDetectorRef } from "@angular/core";
+
+import { ChartComponent } from "angular2-chartjs";
 
 import { Observer } from "jalhyd";
 
@@ -17,11 +19,17 @@ import { ResultsComponent } from "../fixedvar-results/results.component";
     ]
 })
 export class ResultsGraphComponent extends ResultsComponent implements AfterContentInit, Observer {
+
+    @ViewChild(ChartComponent)
+    private chartComponent;
+
     private _results: PlottableData;
 
     /** used to briefly destroy/rebuild the chart component, to refresh axis labels (@see bug #137) */
     public displayChart = true;
 
+    private _zoomWasChanged = false;
+
     @ViewChild(GraphTypeSelectComponent)
     private _graphTypeComponent: GraphTypeSelectComponent;
 
@@ -52,9 +60,28 @@ export class ResultsGraphComponent extends ResultsComponent implements AfterCont
 
     public constructor(
         private appSetup: ApplicationSetupService,
-        private intlService: I18nService
+        private intlService: I18nService,
+        private cd: ChangeDetectorRef
     ) {
         super();
+        // enable zoom and pan (using "chartjs-plugin-zoom" package)
+        const that = this;
+        this.graph_options["plugins"] = {
+            zoom: {
+                pan: {
+                    enabled: false, // conflicts with drag zoom
+                    mode: "xy",
+                },
+                zoom: {
+                    enabled: true,
+                    drag: true, // conflicts with pan; set to false to enable mouse wheel zoom
+                    mode: "xy",
+                    // percentage of zoom on a wheel event
+                    // speed: 0.1,
+                    onZoomComplete: function(t: any) { return function() { t.zoomComplete(); }; }(that)
+                }
+            }
+        };
     }
 
     public set results(r: PlottableData) {
@@ -116,6 +143,15 @@ export class ResultsGraphComponent extends ResultsComponent implements AfterCont
         return this.intlService.localizeText("INFO_PARAMFIELD_GRAPH_SELECT_Y_AXIS");
     }
 
+    private zoomComplete() {
+        this._zoomWasChanged = true;
+        this.cd.detectChanges();
+    }
+
+    public get zoomWasChanged(): boolean {
+        return this._zoomWasChanged;
+    }
+
     public updateView() {
         // (re)generate chart
         switch (this._graphTypeComponent.selectedValue) {
@@ -316,6 +352,27 @@ export class ResultsGraphComponent extends ResultsComponent implements AfterCont
         }); // defaults to image/png
     }
 
+    public resetZoom() {
+        this.chartComponent.chart.resetZoom();
+        this._zoomWasChanged = false;
+    }
+
+    public get uitextResetZoomTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_RESET_ZOOM");
+    }
+
+    public get uitextExportImageTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_EXPORT_IMAGE");
+    }
+
+    public get uitextEnterFSTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_ENTER_FS");
+    }
+
+    public get uitextExitFSTitle() {
+        return this.intlService.localizeText("INFO_GRAPH_BUTTON_TITLE_EXIT_FS");
+    }
+
     // interface Observer
 
     update(sender: any, data: any) {
diff --git a/src/app/formulaire/definition/concrete/form-pab.ts b/src/app/formulaire/definition/concrete/form-pab.ts
index 898f542172bfdf2af0755e627ff7799dd5b2b7b0..aa5bac6865d805850182ac1912022910e9bc3568 100644
--- a/src/app/formulaire/definition/concrete/form-pab.ts
+++ b/src/app/formulaire/definition/concrete/form-pab.ts
@@ -23,10 +23,10 @@ export class FormulairePab extends FormulaireBase {
         return this.currentNub as Pab;
     }
 
-    public doCompute() {
+    /* public doCompute() {
         this.dumpPabStructure(this.pabNub);
         super.doCompute();
-    }
+    } */
 
     // debug method
     private dumpPabStructure(pab: Pab) {
diff --git a/src/locale/messages.en.json b/src/locale/messages.en.json
index 5e07c524b0066afc7574eb4724a182194b4b031c..1fce8bfcdaf8e786cedf0587d7ed2a18410e0617 100644
--- a/src/locale/messages.en.json
+++ b/src/locale/messages.en.json
@@ -101,6 +101,10 @@
     "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_1": "Partially submerged",
     "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_2": "Submerged",
     "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_3": "Zero flow",
+    "INFO_GRAPH_BUTTON_TITLE_RESET_ZOOM": "Restore default zoom",
+    "INFO_GRAPH_BUTTON_TITLE_EXPORT_IMAGE": "Save picture",
+    "INFO_GRAPH_BUTTON_TITLE_ENTER_FS": "Display fullscreen",
+    "INFO_GRAPH_BUTTON_TITLE_EXIT_FS": "Exis fullscreen mode",
     "INFO_DEVICE_ADDED": "1 device added",
     "INFO_DEVICE_ADDED_N_TIMES": "%s devices added",
     "INFO_DEVICE_COPIED": "Device #%s copied",
diff --git a/src/locale/messages.fr.json b/src/locale/messages.fr.json
index 8b97db8956cb20751bdbfa803453555729462bce..1c4ace04cc51b24cf453797047f00db14128cc2e 100644
--- a/src/locale/messages.fr.json
+++ b/src/locale/messages.fr.json
@@ -101,6 +101,10 @@
     "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_1": "Partiellement noyé",
     "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_2": "Noyé",
     "INFO_EXTRARES_ENUM_STRUCTUREFLOWREGIME_3": "Débit nul",
+    "INFO_GRAPH_BUTTON_TITLE_RESET_ZOOM": "Réinitialiser le zoom",
+    "INFO_GRAPH_BUTTON_TITLE_EXPORT_IMAGE": "Enregistrer l'image",
+    "INFO_GRAPH_BUTTON_TITLE_ENTER_FS": "Afficher en plein écran",
+    "INFO_GRAPH_BUTTON_TITLE_EXIT_FS": "Sortir du mode plein écran",
     "INFO_DEVICE_ADDED": "1 ouvrage ajouté",
     "INFO_DEVICE_ADDED_N_TIMES": "%s ouvrages ajoutés",
     "INFO_DEVICE_COPIED": "Ouvrage n°%s copié",
diff --git a/src/main.ts b/src/main.ts
index 9b8fff7b96bcd6f42218db26ef282901d5136450..018a6f867c32a3cbe4b9eee6682ce72c5b18614a 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -5,6 +5,8 @@ import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
 import { AppModule } from "./app/app.module";
 import { environment } from "./environments/environment";
 
+import "chartjs-plugin-zoom";
+
 if (environment.production) {
   enableProdMode();
 }