You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@echarts.apache.org by su...@apache.org on 2019/11/06 21:15:29 UTC

[incubator-echarts] 01/01: fix: fix bar width strategy. (1) On value axis, the auto-calculated bar width might be near 0, which make the bar invisible. So we add option `barMinWidth` (default 1 in category and default null in other coord sys). (2) In #5316 (commit 2823ab502bf1af27c33de6d09729bc287ef0a185) the fix seems not correct. check the "main3" case in `echarts/test/bar-width.html`. That fix would made the `barMaxWidth` has higher priority than `barWidth`. But it only works when auto-calculated bar width is big [...]

This is an automated email from the ASF dual-hosted git repository.

sushuang pushed a commit to branch fix/bar-width-on-value-axis
in repository https://gitbox.apache.org/repos/asf/incubator-echarts.git

commit 7f7e0131ac2a9efddbc04b3f308e83c6f7d12226
Author: SHUANG SU <su...@gmail.com>
AuthorDate: Thu Nov 7 05:14:19 2019 +0800

    fix: fix bar width strategy.
    (1) On value axis, the auto-calculated bar width might be near 0, which make the bar invisible.
    So we add option `barMinWidth` (default 1 in category and default null in other coord sys).
    (2) In #5316 (commit 2823ab502bf1af27c33de6d09729bc287ef0a185) the fix seems not correct.
    check the "main3" case in `echarts/test/bar-width.html`. That fix would made the `barMaxWidth` has
    higher priority than `barWidth`. But it only works when auto-calculated bar width is bigger than the
    giving `barWidth`. So the behavior seems weird.
    This fix revert it and use the strategy: `barWidth` always has higher priority than `barMaxWidth`.
---
 src/chart/bar/BaseBarSeries.js |   4 +
 src/chart/custom.js            |   1 +
 src/layout/barGrid.js          |  35 ++++-
 test/bar-width.html            | 289 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 322 insertions(+), 7 deletions(-)

diff --git a/src/chart/bar/BaseBarSeries.js b/src/chart/bar/BaseBarSeries.js
index 7c8b603..e27f0a7 100644
--- a/src/chart/bar/BaseBarSeries.js
+++ b/src/chart/bar/BaseBarSeries.js
@@ -66,6 +66,10 @@ export default SeriesModel.extend({
         progressiveChunkMode: 'mod',
 
         // barMaxWidth: null,
+
+        // In cartesian, the default value is 1. Otherwise null.
+        // barMinWidth: null,
+
         // 默认自适应
         // barWidth: null,
         // 柱间距离,默认为柱形宽度的30%,可设固定值
diff --git a/src/chart/custom.js b/src/chart/custom.js
index 784e59c..c1dd8be 100644
--- a/src/chart/custom.js
+++ b/src/chart/custom.js
@@ -539,6 +539,7 @@ function makeRenderItem(customSeries, data, ecModel, api) {
      * @param {number} opt.count Positive interger.
      * @param {number} [opt.barWidth]
      * @param {number} [opt.barMaxWidth]
+     * @param {number} [opt.barMinWidth]
      * @param {number} [opt.barGap]
      * @param {number} [opt.barCategoryGap]
      * @return {Object} {width, offset, offsetCenter} is not support, return undefined.
diff --git a/src/layout/barGrid.js b/src/layout/barGrid.js
index 069cc25..a287938 100644
--- a/src/layout/barGrid.js
+++ b/src/layout/barGrid.js
@@ -43,6 +43,7 @@ function getAxisKey(axis) {
  * @param {number} opt.count Positive interger.
  * @param {number} [opt.barWidth]
  * @param {number} [opt.barMaxWidth]
+ * @param {number} [opt.barMinWidth]
  * @param {number} [opt.barGap]
  * @param {number} [opt.barCategoryGap]
  * @return {Object} {width, offset, offsetCenter} If axis.type is not 'category', return undefined.
@@ -187,6 +188,11 @@ export function makeColumnLayout(barSeries) {
         var barMaxWidth = parsePercent(
             seriesModel.get('barMaxWidth'), bandWidth
         );
+        var barMinWidth = parsePercent(
+            // barMinWidth by default is 1 in cartesian. Because in value axis,
+            // the auto-calculated bar width might be less than 1.
+            seriesModel.get('barMinWidth') || 1, bandWidth
+        );
         var barGap = seriesModel.get('barGap');
         var barCategoryGap = seriesModel.get('barCategoryGap');
 
@@ -194,6 +200,7 @@ export function makeColumnLayout(barSeries) {
             bandWidth: bandWidth,
             barWidth: barWidth,
             barMaxWidth: barMaxWidth,
+            barMinWidth: barMinWidth,
             barGap: barGap,
             barCategoryGap: barCategoryGap,
             axisKey: getAxisKey(baseAxis),
@@ -248,6 +255,8 @@ function doCalBarWidthAndOffset(seriesInfoList) {
 
         var barMaxWidth = seriesInfo.barMaxWidth;
         barMaxWidth && (stacks[stackId].maxWidth = barMaxWidth);
+        var barMinWidth = seriesInfo.barMinWidth;
+        barMinWidth && (stacks[stackId].minWidth = barMinWidth);
         var barGap = seriesInfo.barGap;
         (barGap != null) && (columnsOnAxis.gap = barGap);
         var barCategoryGap = seriesInfo.barCategoryGap;
@@ -273,14 +282,26 @@ function doCalBarWidthAndOffset(seriesInfoList) {
 
         // Find if any auto calculated bar exceeded maxBarWidth
         zrUtil.each(stacks, function (column, stack) {
+            if (column.width) {
+                return;
+            }
             var maxWidth = column.maxWidth;
-            if (maxWidth && maxWidth < autoWidth) {
-                maxWidth = Math.min(maxWidth, remainedWidth);
-                if (column.width) {
-                    maxWidth = Math.min(maxWidth, column.width);
-                }
-                remainedWidth -= maxWidth;
-                column.width = maxWidth;
+            var minWidth = column.minWidth;
+            var finalWidth = autoWidth;
+            if (maxWidth && maxWidth < finalWidth) {
+                finalWidth = Math.min(finalWidth, maxWidth, remainedWidth);
+            }
+            // `minWidth` has higher priority. `minWidth` decide that wheter the
+            // bar is able to be visible. So `minWidth` should not be restricted
+            // by `maxWidth` or `remainedWidth` (which is from `bandWidth`). In
+            // the extreme cases for `value` axis, bars are allowed to overlap
+            // with each other if `minWidth` specified.
+            if (minWidth && minWidth > finalWidth) {
+                finalWidth = Math.max(finalWidth, minWidth);
+            }
+            if (finalWidth !== autoWidth) {
+                column.width = finalWidth;
+                remainedWidth -= finalWidth;
                 autoWidthCount--;
             }
         });
diff --git a/test/bar-width.html b/test/bar-width.html
new file mode 100644
index 0000000..e788d04
--- /dev/null
+++ b/test/bar-width.html
@@ -0,0 +1,289 @@
+
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<html>
+    <head>
+        <meta charset="utf-8">
+        <script src="lib/esl.js"></script>
+        <script src="lib/config.js"></script>
+        <script src="lib/jquery.min.js"></script>
+        <script src="lib/facePrint.js"></script>
+        <script src="lib/testHelper.js"></script>
+        <meta name="viewport" content="width=device-width, initial-scale=1" />
+        <link rel="stylesheet" href="lib/reset.css">
+    </head>
+    <body>
+        <style>
+            h1 {
+                line-height: 60px;
+                height: 60px;
+                background: #146402;
+                text-align: center;
+                font-weight: bold;
+                color: #eee;
+                font-size: 14px;
+            }
+            .chart {
+                height: 400px;
+            }
+        </style>
+
+        <div class="chart" id="main1"></div>
+        <div class="chart" id="main2"></div>
+        <div class="chart" id="main3"></div>
+
+
+        <script>
+
+            require([
+                'echarts'
+            ], function (echarts) {
+                var data = [
+                    [7880,6.52],
+                    [7881,3.18], // very near 7880, which makes the bar very thin
+                    [6110,2.68],
+                    [7390,9.55],
+                    [7250,5.59],
+                    [7300,7.43],
+                    [3980,8.54],
+                    [4290,3.22],
+                    [500,4.68],
+                    [1720,5.15],
+                    [900,9],
+                    [910,10]
+                ];
+
+                function makeOption() {
+                    var option = {
+                        tooltip: {},
+                        xAxis: {
+                        },
+                        yAxis: {
+                        },
+                        dataZoom:
+                        [{
+                            type: 'inside'
+                        }, {
+                            type: 'slider'
+                        }],
+                        series: {
+                            type: 'bar',
+                            label: {
+                                show: true,
+                                position: 'top'
+                            },
+                            data: data
+                        },
+                        title: {
+                            text: 'no barMinWidth, no barMaxWidth specifed'
+                        }
+                    };
+                    return option;
+                }
+
+                var chart = testHelper.create(echarts, 'main1', {
+                    title: [
+                        'On `value` axis.',
+                        'Test **barMinWidth** and **barMaxWidth**: move dataZoom, ',
+                        'bar should be **visible** ',
+                        '**bar width** should be correct as the title described.'
+                    ],
+                    height: 200,
+                    option: makeOption(),
+                    buttons: [{
+                        text: 'barMinWidth: 10',
+                        onclick: function () {
+                            var option = makeOption();
+                            option.title.text = 'barMinWidth: 10, no barMaxWidth';
+                            option.series.barMinWidth = 10;
+                            chart.setOption(option, true);
+                        }
+                    }, {
+                        text: 'barMinWidth: 10, barMaxWidth: 40',
+                        onclick: function () {
+                            var option = makeOption();
+                            option.title.text = 'barMinWidth: 10, barMaxWidth: 40';
+                            option.series.barMinWidth = 10;
+                            option.series.barMaxWidth = 40;
+                            chart.setOption(option, true);
+                        }
+                    }, {
+                        text: 'barMaxWidth: 40',
+                        onclick: function () {
+                            var option = makeOption();
+                            option.title.text = 'no barMinWidth, barMaxWidth: 40';
+                            option.series.barMaxWidth = 40;
+                            chart.setOption(option, true);
+                        }
+                    }]
+                });
+            });
+
+        </script>
+
+
+
+
+
+
+
+
+        <script>
+
+            require([
+                'echarts'
+            ], function (echarts) {
+                var data = [];
+                for (var i = 0; i < 80; i++) {
+                    data.push(['a' + i, 10]);
+                }
+
+                function makeOption() {
+                    var option = {
+                        tooltip: {},
+                        xAxis: {
+                            type: 'category'
+                        },
+                        yAxis: {
+                        },
+                        dataZoom:
+                        [{
+                            type: 'inside'
+                        }, {
+                            type: 'slider'
+                        }],
+                        series: {
+                            type: 'bar',
+                            data: data
+                        },
+                        title: {
+                            text: 'no barMinWidth, no barMaxWidth specifed'
+                        }
+                    };
+                    return option;
+                }
+
+                var chart = testHelper.create(echarts, 'main2', {
+                    title: [
+                        'On `category` axis.',
+                        'Test **barMinWidth** and **barMaxWidth**: move dataZoom, ',
+                        'bar should be **visible**.',
+                        '**bar width** should be correct as the title described.'
+                    ],
+                    height: 200,
+                    width: 600,
+                    option: makeOption(),
+                    buttons: [{
+                        text: 'barMinWidth: 10',
+                        onclick: function () {
+                            var option = makeOption();
+                            option.title.text = 'barMinWidth: 10, no barMaxWidth';
+                            option.series.barMinWidth = 10;
+                            chart.setOption(option, true);
+                        }
+                    }, {
+                        text: 'barMinWidth: 10, barMaxWidth: 40',
+                        onclick: function () {
+                            var option = makeOption();
+                            option.title.text = 'barMinWidth: 10, barMaxWidth: 40';
+                            option.series.barMinWidth = 10;
+                            option.series.barMaxWidth = 40;
+                            chart.setOption(option, true);
+                        }
+                    }, {
+                        text: 'barMaxWidth: 40',
+                        onclick: function () {
+                            var option = makeOption();
+                            option.title.text = 'no barMinWidth, barMaxWidth: 40';
+                            option.series.barMaxWidth = 40;
+                            chart.setOption(option, true);
+                        }
+                    }]
+                });
+            });
+
+        </script>
+
+
+
+
+        <script>
+
+            require([
+                'echarts'
+            ], function (echarts) {
+                var data = [
+                    [7880,6.52],
+                    [7881,3.18],
+                    [6110,2.68],
+                    [7390,9.55],
+                    [7250,5.59],
+                    [7300,7.43],
+                    [3980,8.54],
+                    [4290,3.22],
+                    [500,4.68],
+                    [1720,5.15],
+                    [900,9],
+                    [910,10]
+                ];
+
+                var option = {
+                    tooltip: {},
+                    xAxis: {
+                        type: 'category'
+                    },
+                    yAxis: {
+                    },
+                    dataZoom:
+                    [{
+                        type: 'inside'
+                    }, {
+                        type: 'slider'
+                    }],
+                    series: {
+                        type: 'bar',
+                        label: {
+                            show: true,
+                            position: 'top'
+                        },
+                        barWidth: 40,
+                        // Smaller than `barWidth`
+                        barMaxWidth: 10,
+                        data: data
+                    }
+                };
+
+                var chart = testHelper.create(echarts, 'main3', {
+                    title: [
+                        'Test: **barWidth** should have higher priority then **barMaxWidth**',
+                        'Zoom the data, the bar width should **keep 40px**'
+                    ],
+                    height: 200,
+                    option: option
+                });
+            });
+
+        </script>
+
+
+
+
+    </body>
+</html>
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@echarts.apache.org
For additional commands, e-mail: commits-help@echarts.apache.org