]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Improvements to tooltip alignment to avoid the canvas edges
authorEvert Timberg <evert.timberg@gmail.com>
Wed, 23 Dec 2015 02:35:23 +0000 (21:35 -0500)
committerEvert Timberg <evert.timberg@gmail.com>
Wed, 23 Dec 2015 02:35:23 +0000 (21:35 -0500)
src/core/core.controller.js
src/core/core.tooltip.js

index d57ebcc8aa34e6532c4984f1b58afb2a12c9d34d..17b875c5e55c3d1345a528ea92970db672008018 100644 (file)
                initToolTip: function initToolTip() {
                        this.tooltip = new Chart.Tooltip({
                                _chart: this.chart,
+                               _chartInstance: this,
                                _data: this.data,
                                _options: this.options,
                        }, this);
index 3fdc54d17bc0dd8f962ee1da933b96748221c5cf..10cef30b4be0e755949f647e7af4bae9f2ec62c5 100644 (file)
                                helpers.extend(this._model, {
                                        x: Math.round(tooltipPosition.x),
                                        y: Math.round(tooltipPosition.y),
-                                       caretPadding: tooltipPosition.padding,
+                                       caretPadding: helpers.getValueOrDefault(tooltipPosition.padding, 2),
                                        labelColors: labelColors,
                                });
+
+                               // We need to determine alignment of 
+                               var tooltipSize = this.getTooltipSize(this._model);
+                               this.determineAlignment(tooltipSize); // Smart Tooltip placement to stay on the canvas
+
+                               helpers.extend(this._model, this.getBackgroundPoint(this._model, tooltipSize));
                        }
                        else{
                                this._model.opacity = 0;
 
                        return this;
                },
-               getTooltipSize: function getTooltipSize() {
-                       var vm = this._view;
+               getTooltipSize: function getTooltipSize(vm) {
                        var ctx = this._chart.ctx;
 
                        var size = {
                        return size;
                },
                determineAlignment: function determineAlignment(size) {
-                       var vm = this._view;
-                       vm.yAlign = "center";
-                       if (vm.y - (size.height / 2) < 0) {
-                               vm.yAlign = "top";
-                       } else if (vm.y + (size.height / 2) > this._chart.height) {
-                               vm.yAlign = "bottom";
+                       this._model.xAlign = this._model.yAlign = "center";
+
+                       if (this._model.y < size.height) {
+                               this._model.yAlign = 'top';
+                       } else if (this._model.y > (this._chart.height - size.height)) {
+                               this._model.yAlign = 'bottom';
+                       }
+
+                       var lf, rf;
+                       var _this = this;
+                       var midX = (this._chartInstance.chartArea.left + this._chartInstance.chartArea.right) / 2;
+
+                       if (this._model.yAlign === 'center') {
+                               lf = function(x) { return x <= midX; };
+                               rf = function(x) { return x > midX; };
+                       } else {
+                               lf = function(x) { return x <= (size.width / 2); };
+                               rf = function(x) { return x >= (_this._chart.width - (size.width / 2)); };
                        }
 
-                       // Left or Right
-                       vm.xAlign = "right";
-                       if (vm.x + size.width > this._chart.width) {
-                               vm.xAlign = "left";
+                       if (lf(this._model.x)) {
+                               this._model.xAlign = 'left';
+                       } else if (rf(this._model.x)) {
+                               this._model.xAlign = 'right';
                        }
                },
-               getBackgroundPoint: function getBackgroundPoint(size, caretPadding) {
-                       var vm = this._view;
+               getBackgroundPoint: function getBackgroundPoint(vm, size) {
                        // Background Position
                        var pt = {
                                x: vm.x,
                                y: vm.y
                        };
 
+                       if (vm.xAlign === 'right') {
+                               pt.x -= size.width;
+                       } else if (vm.xAlign === 'center') {
+                               pt.x -= (size.width / 2);
+                       }
+
                        if (vm.yAlign === 'top') {
-                               pt.y = vm.y - vm.caretSize - vm.cornerRadius;
+                               pt.y += vm.caretPadding + vm.caretSize;
                        } else if (vm.yAlign === 'bottom') {
-                               pt.y = vm.y - size.height + vm.caretSize + vm.cornerRadius;
+                               pt.y -= size.height + vm.caretPadding + vm.caretSize;
                        } else {
-                               pt.y = vm.y - (size.height / 2);
+                               pt.y -= (size.height / 2);
                        }
 
-                       if (vm.xAlign === 'left') {
-                               pt.x = vm.x - size.width;
-                       } else if (vm.xAlign === 'right') {
-                               pt.x = vm.x + caretPadding + vm.caretSize;
+                       if (vm.yAlign == 'center') {
+                               if (vm.xAlign === 'left') {
+                                       pt.x += vm.caretPadding + vm.caretSize;
+                               } else if (vm.xAlign === 'right') {
+                                       pt.x -= vm.caretPadding + vm.caretSize;
+                               }
                        } else {
-                               pt.x = vm.x + (size.width / 2);
+                               if (vm.xAlign === 'left') {
+                                       pt.x -= vm.cornerRadius + vm.caretPadding;
+                               } else if (vm.xAlign === 'right') {
+                                       pt.x += vm.cornerRadius + vm.caretPadding;
+                               }
                        }
 
                        return pt;
                },
-               drawCaret: function drawCaret(opacity, caretPadding) {
+               drawCaret: function drawCaret(tooltipPoint, size, opacity, caretPadding) {
                        var vm = this._view;
                        var ctx = this._chart.ctx;
+                       var x1, x2, x3;
+                       var y1, y2, y3;
+
+                       if (vm.yAlign === 'center') {
+                               // Left or right side
+                               if (vm.xAlign === 'left') {
+                                       x1 = tooltipPoint.x;
+                                       x2 = x1 - vm.caretSize;
+                                       x3 = x1;
+                               } else {
+                                       x1 = tooltipPoint.x + size.width;
+                                       x2 = x1 + vm.caretSize;
+                                       x3 = x1;
+                               }
 
-                       ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(opacity).rgbString();
-                       ctx.beginPath();
-
-                       if (vm.xAlign === 'left') {
-                               ctx.moveTo(vm.x - caretPadding, vm.y);
-                               ctx.lineTo(vm.x - caretPadding - vm.caretSize, vm.y - vm.caretSize);
-                               ctx.lineTo(vm.x - caretPadding - vm.caretSize, vm.y + vm.caretSize);
+                               y2 = tooltipPoint.y + (size.height / 2);
+                               y1 = y2 - vm.caretSize;
+                               y3 = y2 + vm.caretSize;
                        } else {
-                               ctx.moveTo(vm.x + caretPadding, vm.y);
-                               ctx.lineTo(vm.x + caretPadding + vm.caretSize, vm.y - vm.caretSize);
-                               ctx.lineTo(vm.x + caretPadding + vm.caretSize, vm.y + vm.caretSize);
+                               if (vm.xAlign === 'left') {
+                                       x1 = tooltipPoint.x + vm.cornerRadius;
+                                       x2 = x1 + vm.caretSize;
+                                       x3 = x2 + vm.caretSize;
+                               } else if (vm.xAlign === 'right') {
+                                       x1 = tooltipPoint.x + size.width - vm.cornerRadius;
+                                       x2 = x1 - vm.caretSize;
+                                       x3 = x2 - vm.caretSize;
+                               } else {
+                                       x2 = tooltipPoint.x + (size.width / 2);
+                                       x1 = x2 - vm.caretSize;
+                                       x3 = x2 + vm.caretSize;
+                               }
+
+                               if (vm.yAlign === 'top') {
+                                       y1 = tooltipPoint.y;
+                                       y2 = y1 - vm.caretSize;
+                                       y3 = y1;
+                               } else {
+                                       y1 = tooltipPoint.y + size.height;
+                                       y2 = y1 + vm.caretSize;
+                                       y3 = y1;
+                               }
                        }
 
+                       ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(opacity).rgbString();
+                       ctx.beginPath();
+                       ctx.moveTo(x1, y1);
+                       ctx.lineTo(x2, y2);
+                       ctx.lineTo(x3, y3);
                        ctx.closePath();
                        ctx.fill();
                },
                                return;
                        }
 
-                       var caretPadding = vm.caretPadding || 2;
-                       var tooltipSize = this.getTooltipSize();
-                       var backgroundWidth = tooltipSize.width;
-                       
-                       // Expand to be new total size (including caret)
-                       tooltipSize.width += vm.caretSize + caretPadding;
-
-                       // Smart Tooltip placement to stay on the canvas
-                       // Top, center, or bottom
-                       this.determineAlignment(tooltipSize);
-
-                       var pt = this.getBackgroundPoint(tooltipSize, caretPadding);
+                       var caretPadding = vm.caretPadding;
+                       var tooltipSize = this.getTooltipSize(vm);
+                       var pt = {
+                               x: vm.x,
+                               y: vm.y
+                       };
 
                        // IE11/Edge does not like very small opacities, so snap to 0
                        var opacity = Math.abs(vm.opacity < 1e-3) ? 0 : vm.opacity;
                        if (this._options.tooltips.enabled) {
                                // Draw Background
                                ctx.fillStyle = helpers.color(vm.backgroundColor).alpha(opacity).rgbString();
-                               helpers.drawRoundedRectangle(ctx, pt.x, pt.y, backgroundWidth, tooltipSize.height, vm.cornerRadius);
+                               helpers.drawRoundedRectangle(ctx, pt.x, pt.y, tooltipSize.width, tooltipSize.height, vm.cornerRadius);
                                ctx.fill();
 
                                // Draw Caret
-                               this.drawCaret(opacity, caretPadding);
+                               this.drawCaret(pt, tooltipSize, opacity, caretPadding);
                                
                                // Draw Title, Body, and Footer
                                pt.x += vm.xPadding;