Polymer 1.x:页面加载后调整图表大小

时间:2016-02-14 11:39:59

标签: javascript google-visualization polymer polymer-1.0

TLDR; Here is the jsBin

我如何最初在我的布局边界内绘制我的<google-chart> geochart元素,并防止它溢出&#34;溢出&#34;在第一次油漆?

在我的自定义元素中,我使用google-chart元素,后者又使用Google GeoChart和API。当它第一次出现在屏幕上时,它看起来像这样。 (请注意右侧如何溢出paper-card的边缘?)

首先绘制外边界

我在第一次涂漆时实际看到了什么。 (突出显示的状态是声明性预设。)

First appearance

在我选择一个州(比如说,在这种情况下是加利福尼亚州)之后,图表会重新绘制并在边界内正确绘制,就像我想要的那样。

单击状态

后重绘内部边界 我期望在第一次涂漆时看到什么。选择州后。

Appearance after click and redraw

重新创建问题

请按照以下步骤操作:

  1. Open this jsBin
  2. 点击标有 Reveal Chart
  3. 的按钮
  4. ❌请注意,图表现在首先显示 大于 paper-card(100px)的最大宽度。
  5. 点击州。
  6. 请注意,图表会调整大小以适应paper-card
  7. 的宽度

    问题出在&#34;隐藏&#34; &#34; div&#34;的属性标签

    问题(当实施@ScottMiles建议的以下解决方案时)在这里:
    <div id="chart" hidden> <!-- "hidden" attribute is the problem -->
      <x-element color="red"
                 selected='["Colorado", "South Dakota"]'>
      </x-element>
    </div>
    

    如果删除hidden属性,则会根据需要进行第一次绘制。但是,出于UX原因,我需要在页面加载时使用hidden属性。

    到目前为止,我没有成功尝试过两种解决方案。

    解决方案尝试1:手动重绘附加

    attached: function() {
      this.$.geochart.drawChart(); // Called manually to handle page resizes
    }
    

    解决方案尝试2:IronResizableBehavior

    behaviors: [
      Polymer.IronResizableBehavior,
    ],
    listeners: {
      'iron-resize': '_onIronResize',
    },
    _onIronResize: function() {
      this.$.geochart.drawChart(); // Called manually to handle page resizes
    },
    attached: function() {
      this.async(this.notifyResize, 1);
    },
    

    来源

    http://jsbin.com/zumireradi/1/edit?html,output
    <!DOCTYPE html>
    
    <head>
      <meta charset="utf-8">
      <base href="https://polygit.org/components/">
      <script src="webcomponentsjs/webcomponents-lite.min.js"></script>
      <link href="polymer/polymer.html" rel="import">
      <link href="google-chart/google-chart.html" rel="import">
      <link href="paper-card/paper-card.html" rel="import">
    </head>
    
    <body>
      <dom-module id="x-element">
        <template>
          <style>
            google-chart {
              width: 100%;
            }
          </style>
          <br><br><br><br>
          <button on-tap="_show">Show Values</button>
          <button on-tap="clearAll">Clear All</button>
          <button on-tap="selectAll">Select All</button>
          <div>[[selectedString]]</div>
          <google-chart id="geochart"
                        type="geo"
                        options="[[options]]"
                        data="[[data]]"
                        on-google-chart-select="_onGoogleChartSelect">
          </google-chart>
        </template>
        <script>
          (function() {
            // Monkey patch for google-chart
            var gcp = Object.getPrototypeOf(document.createElement('google-chart'));
            gcp.drawChart = function() {
              if (this._canDraw) {
                if (!this.options) {
                  this.options = {};
                }
                if (!this._chartObject) {
                  var chartClass = this._chartTypes[this.type];
                  if (chartClass) {
                    this._chartObject = new chartClass(this.$.chartdiv);
                    google.visualization.events.addOneTimeListener(this._chartObject,
                        'ready', function() {
                            this.fire('google-chart-render');
                        }.bind(this));
                    google.visualization.events.addListener(this._chartObject,
                        'select', function() {
                            this.selection = this._chartObject.getSelection();
                            this.fire('google-chart-select', { selection: this.selection });
                        }.bind(this));
                    if (this._chartObject.setSelection){
                      this._chartObject.setSelection(this.selection);
                    }
                  }
                }
                if (this._chartObject) {
                  this._chartObject.draw(this._dataTable, this.options);
                } else {
                  this.$.chartdiv.innerHTML = 'Undefined chart type';
                }
              }
            };
            Polymer({
              is: 'x-element',
              /** /
               * Fired when user selects chart item.
               *
               * @event us-map-select
               * @param {object} detail Alpabetized array of selected state names.
              /**/
              properties: {
                items: {
                  type: Array,
                  value: function() {
                    return [ 'Alabama', 'Alaska', 'Arizona', 'Arkansas', 'California', 'Colorado', 'Connecticut', 'Delaware', 'Florida', 'Georgia', 'Hawaii', 'Idaho', 'Illinois', 'Indiana', 'Iowa', 'Kansas', 'Kentucky', 'Louisiana', 'Maine', 'Maryland', 'Massachusetts', 'Michigan', 'Minnesota', 'Mississippi', 'Missouri', 'Montana', 'Nebraska', 'Nevada', 'New Hampshire', 'New Jersey', 'New Mexico', 'New York', 'North Carolina', 'North Dakota', 'Ohio', 'Oklahoma', 'Oregon', 'Pennsylvania', 'Rhode Island', 'South Carolina', 'South Dakota', 'Tennessee', 'Texas', 'Utah', 'Vermont', 'Virginia', 'Washington', 'West Virginia', 'Wisconsin', 'Wyoming', ].sort();
                  },
                },
                color: {
                  type: String,
                  value: 'blue',
                },
                options: {
                  type: Object,
                  computed: '_computeOptions(color)',
                },
                selected: {
                  type: Array,
                },
                data: {
                  type: Array,
                  computed: '_computeData(items, selected.length)'
                },
                selectedString: {
                  type: String,
                  computed: '_computeSelectedString(selected.length)',
                },
              },
              attached: function() {
                if (this.selected === undefined) {
                  this.async(function() {
                    this.selected = [];
                  }, 0);
                }
              },
              _computeOptions: function() {
                return {
                  region: 'US',
                  displayMode: 'regions',
                  resolution: 'provinces',
                  legend: 'none',
                  defaultColor: 'white',
                  colorAxis: {
                    colors: ['#E0E0E0', this.color],
                    minValue: 0,  
                    maxValue: 1,
                  }
                }
              },    
              // On select event, compute 'selected'
              _onGoogleChartSelect: function(e) {
                var string = e.path[0].textContent.split('Select')[0].trim(), // e.g. 'Ohio'
                    selected = this.selected, // Array of selected items
                    index = selected.indexOf(string);
                // If 'string' is not in 'selected' array, add it; else delete it
                if (index === -1) {
                  this.push('selected', string);
                } else {
                  this.splice('selected', index, 1);
                }
              },
              _computeSelectedString: function(selectedInfo) {
                var selected = this.selected.sort();
                this.fire('us-map-select', selected);
                return selected.join(', ');
              },
              // After 'items' populates or 'selected' changes, compute 'data'
              _computeData: function(items, selectedInfo) {
                var data = [],
                    selected = this.selected,
                    i = items.length;
                while (i--) {
                  data.unshift([items[i], selected.indexOf(items[i]) > -1 ? 1 : 0]);
                }
                data.unshift(['State', 'Select']);
                return data;
              },
              clearAll: function() {
                this.set('selected', []);
              },
              selectAll: function() {
                this.set('selected', this.items.slice());
              },
              _show: function() {
                //console.log('items', this.items);
                console.log('selected', this.selected);
                //console.log('data', this.data);
              },
            });
          })();
        </script>
      </dom-module>
      <br /><br /><br />
      <paper-card style="max-width:100px;">
        <button onclick="unhide()">Reveal Chart</button>
        <div id="chart" hidden>
          <x-element color="red"
                     selected='["Colorado", "South Dakota"]'>
          </x-element>
        </div>
      </paper-card>
      <script>
        function unhide() {
          document.getElementById('chart').hidden = false;
        }
      </script>
    </body>
    
    </html>
    

2 个答案:

答案 0 :(得分:2)

聚合物在首次涂漆前尽可能多地生成应用程序,以避免闪烁和FOUC。像google-chart这样的元素如果在涂料已经发生之前渲染(因为某些测量尚不可用),则会感到不快。

要尝试的是推迟google-chart的初始绘图,如下所示:

  1. 保持selected未初始化。这将阻止计算chartData并阻止图表过早绘制。

    selected: {
      type: Array
     }
    
  2. selected异步初始化attached

    attached: function() {
      if (this.selected === undefined) {
        this.async(function() {
          this.selected = []; 
        }, 0);
      }
    }
    
  3. 这有点像黑客攻击,但是调用this.async(.., 0)会让你超越第一个画面。那时我们给selected一个值,触发chartData计算和图表绘制。

    HTH

    在OP发布的JSbin之后更新:在取消隐藏后重写图表可以解决问题:http://jsbin.com/pekahix/edit?html

    document.querySelector('#chart').hidden = false;
    document.querySelector('x-element').$.geochart.drawChart();
    

答案 1 :(得分:0)

我对Polymer.IronResizableBehavior很幸运,但问题是drawChart()我相信,试试redraw()。我能够使用你的努力+ demo of the component来简单地调整大小。我将图表的宽度设置为100%,并且它可以平滑地缩放到放置的卡片中(它具有适合页面的自动边距)

<google-chart
    id="marketchart"
    type="column"
    options='{"title": "Responsive chart",
              "vAxis": {"minValue" : 0, "maxValue": 10}}'
    cols='[{"label": "Data", "type": "string"},{"label": "Value", "type": "number"}]'
    rows='[ ["Col1", 5.0],["Col2", 5.0],["Col3", 5.0] ]'>
  </google-chart>

  <script>
Polymer({
  is: 'my-dashboard',

  behaviors: [
    Polymer.IronResizableBehavior
  ],

  listeners: {
    'iron-resize': '_onIronResize'
  },

  attached: function() {
    this.async(this.notifyResize, 1);
  },

  get parent() {
    if (this.parentNode.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
      return this.parentNode.host;
    }
    return this.parentNode;
  },

  _onIronResize: function() {
    this.$.marketchart.redraw();
  }

});