]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Implement equally sized bars (#4994)
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Sat, 2 Dec 2017 11:38:36 +0000 (12:38 +0100)
committerGitHub <noreply@github.com>
Sat, 2 Dec 2017 11:38:36 +0000 (12:38 +0100)
When `barThickness: undefined|null` (default), we compute an optimal sample size based on the smallest tick interval reduced to prevent any bar to overlap (bar equally sized). Also added support for a special `barThickness: 'flex'` value (previous default) that globally arranges bars side by side to prevent any gap when percentage options are 1 (variable bar sizes).

27 files changed:
.gitignore
src/controllers/controller.bar.js
test/.eslintrc
test/fixtures/controller.bar/bar-thickness-absolute.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-absolute.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-flex-offset.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-flex-offset.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-flex.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-flex.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-max.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-max.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-min-interval.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-min-interval.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-multiple.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-multiple.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-no-overlap.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-no-overlap.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-offset.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-offset.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-single-xy.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-single-xy.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-single.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-single.png [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-stacked.json [new file with mode: 0644]
test/fixtures/controller.bar/bar-thickness-stacked.png [new file with mode: 0644]
test/jasmine.utils.js
test/specs/controller.bar.tests.js

index 53ce8fedb1c674d41883e49e4d8d72b1b69a6a01..cfb878a6dee020146dc7841f6bae6ec9dc3a2e79 100644 (file)
@@ -12,3 +12,4 @@
 bower.json
 *.log
 *.swp
+*.stackdump
index b811c6f05b1ef849cc25b729efa403bfa2b42c32..ff2b56ae5a00709389d5d86b6ac3bb8a0f5c4f8f 100644 (file)
@@ -95,6 +95,93 @@ defaults._set('horizontalBar', {
        }
 });
 
+/**
+ * Computes the "optimal" sample size to maintain bars equally sized while preventing overlap.
+ * @private
+ */
+function computeMinSampleSize(scale, pixels) {
+       var min = scale.isHorizontal() ? scale.width : scale.height;
+       var ticks = scale.getTicks();
+       var prev, curr, i, ilen;
+
+       for (i = 1, ilen = pixels.length; i < ilen; ++i) {
+               min = Math.min(min, pixels[i] - pixels[i - 1]);
+       }
+
+       for (i = 0, ilen = ticks.length; i < ilen; ++i) {
+               curr = scale.getPixelForTick(i);
+               min = i > 0 ? Math.min(min, curr - prev) : min;
+               prev = curr;
+       }
+
+       return min;
+}
+
+/**
+ * Computes an "ideal" category based on the absolute bar thickness or, if undefined or null,
+ * uses the smallest interval (see computeMinSampleSize) that prevents bar overlapping. This
+ * mode currently always generates bars equally sized (until we introduce scriptable options?).
+ * @private
+ */
+function computeFitCategoryTraits(index, ruler, options) {
+       var thickness = options.barThickness;
+       var count = ruler.stackCount;
+       var curr = ruler.pixels[index];
+       var size, ratio;
+
+       if (helpers.isNullOrUndef(thickness)) {
+               size = ruler.min * options.categoryPercentage;
+               ratio = options.barPercentage;
+       } else {
+               // When bar thickness is enforced, category and bar percentages are ignored.
+               // Note(SB): we could add support for relative bar thickness (e.g. barThickness: '50%')
+               // and deprecate barPercentage since this value is ignored when thickness is absolute.
+               size = thickness * count;
+               ratio = 1;
+       }
+
+       return {
+               chunk: size / count,
+               ratio: ratio,
+               start: curr - (size / 2)
+       };
+}
+
+/**
+ * Computes an "optimal" category that globally arranges bars side by side (no gap when
+ * percentage options are 1), based on the previous and following categories. This mode
+ * generates bars with different widths when data are not evenly spaced.
+ * @private
+ */
+function computeFlexCategoryTraits(index, ruler, options) {
+       var pixels = ruler.pixels;
+       var curr = pixels[index];
+       var prev = index > 0 ? pixels[index - 1] : null;
+       var next = index < pixels.length - 1 ? pixels[index + 1] : null;
+       var percent = options.categoryPercentage;
+       var start, size;
+
+       if (prev === null) {
+               // first data: its size is double based on the next point or,
+               // if it's also the last data, we use the scale end extremity.
+               prev = curr - (next === null ? ruler.end - curr : next - curr);
+       }
+
+       if (next === null) {
+               // last data: its size is also double based on the previous point.
+               next = curr + curr - prev;
+       }
+
+       start = curr - ((curr - prev) / 2) * percent;
+       size = ((next - prev) / 2) * percent;
+
+       return {
+               chunk: size / ruler.stackCount,
+               ratio: options.barPercentage,
+               start: start
+       };
+}
+
 module.exports = function(Chart) {
 
        Chart.controllers.bar = Chart.DatasetController.extend({
@@ -262,17 +349,22 @@ module.exports = function(Chart) {
                        var scale = me.getIndexScale();
                        var stackCount = me.getStackCount();
                        var datasetIndex = me.index;
-                       var pixels = [];
                        var isHorizontal = scale.isHorizontal();
                        var start = isHorizontal ? scale.left : scale.top;
                        var end = start + (isHorizontal ? scale.width : scale.height);
-                       var i, ilen;
+                       var pixels = [];
+                       var i, ilen, min;
 
                        for (i = 0, ilen = me.getMeta().data.length; i < ilen; ++i) {
                                pixels.push(scale.getPixelForValue(null, i, datasetIndex));
                        }
 
+                       min = helpers.isNullOrUndef(scale.options.barThickness)
+                               ? computeMinSampleSize(scale, pixels)
+                               : -1;
+
                        return {
+                               min: min,
                                pixels: pixels,
                                start: start,
                                end: end,
@@ -332,51 +424,21 @@ module.exports = function(Chart) {
                calculateBarIndexPixels: function(datasetIndex, index, ruler) {
                        var me = this;
                        var options = ruler.scale.options;
-                       var meta = me.getMeta();
-                       var stackIndex = me.getStackIndex(datasetIndex, meta.stack);
-                       var pixels = ruler.pixels;
-                       var base = pixels[index];
-                       var length = pixels.length;
-                       var start = ruler.start;
-                       var end = ruler.end;
-                       var leftSampleSize, rightSampleSize, leftCategorySize, rightCategorySize, fullBarSize, size;
-
-                       if (length === 1) {
-                               leftSampleSize = base > start ? base - start : end - base;
-                               rightSampleSize = base < end ? end - base : base - start;
-                       } else {
-                               if (index > 0) {
-                                       leftSampleSize = (base - pixels[index - 1]) / 2;
-                                       if (index === length - 1) {
-                                               rightSampleSize = leftSampleSize;
-                                       }
-                               }
-                               if (index < length - 1) {
-                                       rightSampleSize = (pixels[index + 1] - base) / 2;
-                                       if (index === 0) {
-                                               leftSampleSize = rightSampleSize;
-                                       }
-                               }
-                       }
-
-                       leftCategorySize = leftSampleSize * options.categoryPercentage;
-                       rightCategorySize = rightSampleSize * options.categoryPercentage;
-                       fullBarSize = (leftCategorySize + rightCategorySize) / ruler.stackCount;
-                       size = fullBarSize * options.barPercentage;
+                       var range = options.barThickness === 'flex'
+                               ? computeFlexCategoryTraits(index, ruler, options)
+                               : computeFitCategoryTraits(index, ruler, options);
 
-                       size = Math.min(
-                               helpers.valueOrDefault(options.barThickness, size),
-                               helpers.valueOrDefault(options.maxBarThickness, Infinity));
-
-                       base -= leftCategorySize;
-                       base += fullBarSize * stackIndex;
-                       base += (fullBarSize - size) / 2;
+                       var stackIndex = me.getStackIndex(datasetIndex, me.getMeta().stack);
+                       var center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
+                       var size = Math.min(
+                               helpers.valueOrDefault(options.maxBarThickness, Infinity),
+                               range.chunk * range.ratio);
 
                        return {
-                               size: size,
-                               base: base,
-                               head: base + size,
-                               center: base + size / 2
+                               base: center - size / 2,
+                               head: center + size / 2,
+                               center: center,
+                               size: size
                        };
                },
 
index 8e8f899bffd634a781dc6b6fa7423d8c51ca279c..9d98c45287885b5e458263eb0e1988bbeab6f79b 100644 (file)
@@ -11,3 +11,4 @@ globals:
 rules:
   # Best Practices
   complexity: 0
+  max-statements: 0
diff --git a/test/fixtures/controller.bar/bar-thickness-absolute.json b/test/fixtures/controller.bar/bar-thickness-absolute.json
new file mode 100644 (file)
index 0000000..599b090
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2017", "2018", "2019", "2024", "2025"],
+            "datasets": [{
+                "backgroundColor": "rgba(255, 99, 132, 0.5)",
+                "data": [1, null, 3, 4, 5]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "offset": true,
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "barThickness": 128,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-absolute.png b/test/fixtures/controller.bar/bar-thickness-absolute.png
new file mode 100644 (file)
index 0000000..40172b3
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-absolute.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-flex-offset.json b/test/fixtures/controller.bar/bar-thickness-flex-offset.json
new file mode 100644 (file)
index 0000000..1776b07
--- /dev/null
@@ -0,0 +1,42 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2017", "2018", "2020", "2024", "2038"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "offset": true,
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "barThickness": "flex",
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-flex-offset.png b/test/fixtures/controller.bar/bar-thickness-flex-offset.png
new file mode 100644 (file)
index 0000000..e20cc4e
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-flex-offset.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-flex.json b/test/fixtures/controller.bar/bar-thickness-flex.json
new file mode 100644 (file)
index 0000000..0bef9db
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2017", "2018", "2020", "2024", "2038"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "barThickness": "flex",
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-flex.png b/test/fixtures/controller.bar/bar-thickness-flex.png
new file mode 100644 (file)
index 0000000..791a29d
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-flex.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-max.json b/test/fixtures/controller.bar/bar-thickness-max.json
new file mode 100644 (file)
index 0000000..3add555
--- /dev/null
@@ -0,0 +1,41 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "maxBarThickness": 8,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-max.png b/test/fixtures/controller.bar/bar-thickness-max.png
new file mode 100644 (file)
index 0000000..e22867d
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-max.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-min-interval.json b/test/fixtures/controller.bar/bar-thickness-min-interval.json
new file mode 100644 (file)
index 0000000..e586168
--- /dev/null
@@ -0,0 +1,40 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-min-interval.png b/test/fixtures/controller.bar/bar-thickness-min-interval.png
new file mode 100644 (file)
index 0000000..ae01a9b
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-min-interval.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-multiple.json b/test/fixtures/controller.bar/bar-thickness-multiple.json
new file mode 100644 (file)
index 0000000..fc39849
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }, {
+                "backgroundColor": "#36A2EB",
+                "data": [5, 4, 3, null, 1]
+            }, {
+                "backgroundColor": "#FFCE56",
+                "data": [3, 5, 2, null, 4]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-multiple.png b/test/fixtures/controller.bar/bar-thickness-multiple.png
new file mode 100644 (file)
index 0000000..d384052
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-multiple.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-no-overlap.json b/test/fixtures/controller.bar/bar-thickness-no-overlap.json
new file mode 100644 (file)
index 0000000..3e9f1f5
--- /dev/null
@@ -0,0 +1,46 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [
+                    {"y": "1", "t": "2016"},
+                    {"y": "2", "t": "2017"},
+                    {"y": "3", "t": "2017-08"},
+                    {"y": "4", "t": "2024"},
+                    {"y": "5", "t": "2030"}
+                ]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-no-overlap.png b/test/fixtures/controller.bar/bar-thickness-no-overlap.png
new file mode 100644 (file)
index 0000000..1385a08
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-no-overlap.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-offset.json b/test/fixtures/controller.bar/bar-thickness-offset.json
new file mode 100644 (file)
index 0000000..b31eb73
--- /dev/null
@@ -0,0 +1,47 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }, {
+                "backgroundColor": "#36A2EB",
+                "data": [5, 4, 3, null, 1]
+            }, {
+                "backgroundColor": "#FFCE56",
+                "data": [3, 5, 2, null, 4]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "offset": true,
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-offset.png b/test/fixtures/controller.bar/bar-thickness-offset.png
new file mode 100644 (file)
index 0000000..8dcecac
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-offset.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-single-xy.json b/test/fixtures/controller.bar/bar-thickness-single-xy.json
new file mode 100644 (file)
index 0000000..76caa37
--- /dev/null
@@ -0,0 +1,40 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [{"x": "2022", "y": 42}]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-single-xy.png b/test/fixtures/controller.bar/bar-thickness-single-xy.png
new file mode 100644 (file)
index 0000000..26171e5
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-single-xy.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-single.json b/test/fixtures/controller.bar/bar-thickness-single.json
new file mode 100644 (file)
index 0000000..322af75
--- /dev/null
@@ -0,0 +1,43 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    },
+                    "time": {
+                        "min": "2013"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-single.png b/test/fixtures/controller.bar/bar-thickness-single.png
new file mode 100644 (file)
index 0000000..2231431
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-single.png differ
diff --git a/test/fixtures/controller.bar/bar-thickness-stacked.json b/test/fixtures/controller.bar/bar-thickness-stacked.json
new file mode 100644 (file)
index 0000000..aa2d825
--- /dev/null
@@ -0,0 +1,48 @@
+{
+    "config": {
+        "type": "bar",
+        "data": {
+            "labels": ["2016", "2018", "2020", "2024", "2030"],
+            "datasets": [{
+                "backgroundColor": "#FF6384",
+                "data": [1, null, 3, 4, 5]
+            }, {
+                "backgroundColor": "#36A2EB",
+                "data": [5, 4, 3, null, 1]
+            }, {
+                "backgroundColor": "#FFCE56",
+                "data": [3, 5, 2, null, 4]
+            }]
+        },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scales": {
+                "xAxes": [{
+                    "type": "time",
+                    "stacked": true,
+                    "display": false,
+                    "barPercentage": 1,
+                    "categoryPercentage": 1,
+                    "ticks": {
+                        "source": "labels"
+                    }
+                }],
+                "yAxes": [{
+                    "display": false,
+                    "stacked": true,
+                    "ticks": {
+                        "beginAtZero": true
+                    }
+                }]
+            }
+        }
+    },
+    "options": {
+        "canvas": {
+            "height": 256,
+            "width": 512
+        }
+    }
+}
diff --git a/test/fixtures/controller.bar/bar-thickness-stacked.png b/test/fixtures/controller.bar/bar-thickness-stacked.png
new file mode 100644 (file)
index 0000000..696829e
Binary files /dev/null and b/test/fixtures/controller.bar/bar-thickness-stacked.png differ
index 7db35642e062ee8c55509c1fd23bd1e752da31b7..2c2006a2c074dc476527fa9c7561f9f85d5784e7 100644 (file)
@@ -118,9 +118,6 @@ function specFromFixture(description, inputs) {
                        var chart = acquireChart(json.config, json.options);
                        if (!inputs.png) {
                                fail('Missing PNG comparison file for ' + inputs.json);
-                               if (!json.debug) {
-                                       releaseChart(chart);
-                               }
                                done();
                        }
 
index 315bdbd346b00ac86b075006f4012c71ee4c88b8..096b2e8e116338a8867c56c3bd7394892985e028 100644 (file)
@@ -1,4 +1,6 @@
 describe('Chart.controllers.bar', function() {
+       describe('auto', jasmine.specsFromFixtures('controller.bar'));
+
        it('should be constructed', function() {
                var chart = window.acquireChart({
                        type: 'bar',
@@ -1630,84 +1632,4 @@ describe('Chart.controllers.bar', function() {
                        });
                });
        });
-
-       describe('Bar thickness with a time scale', function() {
-               ['auto', 'data', 'labels'].forEach(function(source) {
-                       ['series', 'linear'].forEach(function(distribution) {
-                               describe('When ticks.source is "' + source + '", distribution is "' + distribution + '"', function() {
-                                       beforeEach(function() {
-                                               this.chart = window.acquireChart({
-                                                       type: 'bar',
-                                                       data: {
-                                                               datasets: [{
-                                                                       data: [1, 2, 3]
-                                                               }, {
-                                                                       data: [1, 2, 3]
-                                                               }],
-                                                               labels: ['2017', '2018', '2020']
-                                                       },
-                                                       options: {
-                                                               legend: false,
-                                                               title: false,
-                                                               scales: {
-                                                                       xAxes: [{
-                                                                               id: 'x',
-                                                                               type: 'time',
-                                                                               time: {
-                                                                                       unit: 'year',
-                                                                                       parser: 'YYYY'
-                                                                               },
-                                                                               ticks: {
-                                                                                       source: source
-                                                                               },
-                                                                               offset: true,
-                                                                               distribution: distribution
-                                                                       }],
-                                                                       yAxes: [{
-                                                                               type: 'linear'
-                                                                       }]
-                                                               }
-                                                       }
-                                               });
-                                       });
-
-                                       it('should correctly set bar width', function() {
-                                               var chart = this.chart;
-                                               var scale = chart.scales.x;
-                                               var options = chart.options.scales.xAxes[0];
-                                               var categoryPercentage = options.categoryPercentage;
-                                               var barPercentage = options.barPercentage;
-                                               var firstInterval = scale.getPixelForValue('2018') - scale.getPixelForValue('2017');
-                                               var firstExpected = firstInterval * categoryPercentage / 2 * barPercentage;
-                                               var lastInterval = scale.getPixelForValue('2020') - scale.getPixelForValue('2018');
-                                               var lastExpected = lastInterval * categoryPercentage / 2 * barPercentage;
-                                               var i, ilen, meta;
-
-                                               for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
-                                                       meta = chart.getDatasetMeta(i);
-                                                       expect(meta.data[0]._model.width).toBeCloseToPixel(firstExpected);
-                                                       expect(meta.data[1]._model.width).toBeCloseToPixel((firstExpected + lastExpected) / 2);
-                                                       expect(meta.data[2]._model.width).toBeCloseToPixel(lastExpected);
-                                               }
-                                       });
-
-                                       it('should correctly set bar width if maxBarThickness is specified', function() {
-                                               var chart = this.chart;
-                                               var options = chart.options.scales.xAxes[0];
-                                               var i, ilen, meta;
-
-                                               options.maxBarThickness = 10;
-                                               chart.update();
-
-                                               for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
-                                                       meta = chart.getDatasetMeta(i);
-                                                       expect(meta.data[0]._model.width).toBeCloseToPixel(10);
-                                                       expect(meta.data[1]._model.width).toBeCloseToPixel(10);
-                                                       expect(meta.data[2]._model.width).toBeCloseToPixel(10);
-                                               }
-                                       });
-                               });
-                       });
-               });
-       });
 });