使用 lazy_high_chart 画图,同时把图表放在 bootstrap 的 nav-tab 下面。
情况一:打开页面是默认 active 的那个 tab-content,显示的 chart 是正常 100% 宽度。
情况二:点击 tab,切换到相应的 tab-content,因为之前这个区域是 display:none 的,所以它得不到正常宽度,所以会显示默认宽度 600px。但我需要它显示的是 100% 宽度。
怎样才能以最简洁的方式让它显示 100% 宽度呢?
注:
scss
svg rect{
width: 100%;
}
无效。
它自动生成的 html 为
erb
<rect x="0" y="0" width="600" height="400" strokeWidth="0" fill="#FFFFFF" class=" highcharts-background"></rect>
其它:正在研究这个官方例子 和另一个例子:我觉得它能解决这个问题,但好像代码太复杂了……我用不着这么多……
回帖有几个解决方案,但我自己还没有用对。 目前比较简洁的是一个 css hack 方法
.tab-content > .tab-pane{
display: block;
height: 0;
overflow-y: hidden;
&.active{
height: auto;
}
}
lazy_high_chart 或者其他 chart 组件,通常为了方便应用,一般都是通过初始化参数指定,或者直接从上层容器获取宽度,高度信息,所以请检查一下改变一下放置 chart 容器的宽度是不是正确。
#3 楼 @lgn21st 可是为了简洁一点,我现在是只在 controller 里面设置所有参数,在 view 中显示,就没有再在 js 文件中写什么了…… 如果要计算什么的,我想想,是不是应该在 view 中去改些什么东东……
现在我的写法是 view 中:
<div role="tabpanel" class="text-center">
<ul class="nav nav-tabs text-center" role="tablist">
<li role="presentation" class="active">
<a href="#per_week" class="btn btn-default" aria-controls="per_week" role="tab" data-toggle="tab">一周</a>
</li>
<li role="presentation">
<a href="#per_month" class="btn btn-default" aria-controls="per_month" role="tab" data-toggle="tab">一月</a>
</li>
<li role="presentation">
<a href="#per_year" class="btn btn-default" aria-controls="per_year" role="tab" data-toggle="tab">一年</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<article role="tabpanel" class="tab-pane active" id="per_week">
<%= high_chart("asset_growth_per_week_chart", @asset_growth_per_week_chart) %>
</article>
<article role="tabpanel" class="tab-pane" id="per_month">
<%= high_chart("asset_growth_per_month_chart", @asset_growth_per_month_chart) %>
</article>
<article role="tabpanel" class="tab-pane" id="per_year">
<%= high_chart("asset_growth_per_year_chart", @asset_growth_per_year_chart) %>
</article>
</div>
</div>
controller 中
# 资产增长 - 每周
@asset_growth_per_week_chart = LazyHighCharts::HighChart.new('graph') do |f|
f.chart({ type: 'line'} )
series = {
name: '资金数量',
data: [7.0, 6.9, 9.5, 14.5, 18.4, 21.5, 25.2]
}
f.series(series)
f.xAxis({categories: ['周一', '周二', '周三', '周四', '周五', '周六', '周日']})
f.yAxis({title: {text: '资产数量 (万)'}})
f.plot_options(line:{
allowPointSelect: true,
cursor: "pointer" ,
color: 'rgb(122, 201, 237)',
dataLabels:{enabled: true},
enableMouseTracking: false
})
end
楼主这个问题我也碰到过类似的,使用 lazy 在多个 tab pane 生成图,第一个是 100% 宽度,后面几个切换就是 pane 的宽度,很窄,然后浏览器缩小下,然后放大,就变成 100% 宽度了。
就像 @lgn21st 提及的那样,首先看这个选项支不支持类似于 label formatter 那样传入函数:
labels: {
formatter: %|function(){ return this.value + '#{x_suffix}' }|.js_code
}
但是,非常遗憾,我查了一下 API,好像不支持,那么就只能使用纯 JS 的方式解决问题了。先获取 tab 宽度,然后使用 setSize 这个函数设置宽度就可以了,详情请仔细阅读 API,哈哈!
chart.setSize(chartWidth);
在处理响应式页面的时候我用的是:
$(this).highcharts().reflow()
$(this)
是 highchart 的 DOM obj
bs nav-tab 不是有事件调用吗?绑定 tab 的 click/shown 然后调用 reflow() 有没有试过?
#8 楼 @xhj6 有啊,在 view 中使用,就是丑陋了点。比如我上一个饼图,在 view 中是这么写的
<%= high_chart("asset_allocation_chart", @asset_allocation_chart) do |c| %>
<%= raw "options.tooltip.formatter = function() {return '<b>'+ this.point.name +'</b>: '+ this.y +' %';}" %>
<%= raw "options.plotOptions.pie.dataLabels.formatter = function() {
if (this.y > 5) return this.point.name + ': ' + Math.round(this.percentage*100)/100 + ' %';; }" %>
<% end %>
感觉像是把 js 代码写到 html 里,挺别扭的其实……
对于本问题,@gihnius 的答案是最优解(我提的 reSize 也行,只不过要指定一下宽度,稍显麻烦了一些),具体实现可参考如下代码:
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
$('.chart', e.relatedTarget).highcharts().reflow();
})
注意以上代码未经测试,不一定可用,但思路应该是这样的,你后面改 CSS 就越走越远了。
另外,你把 js 写入 HTML 中,当然就很丑了啊,js 就应该在 js 文件中,而向传递 formatter 的函数,lazyhighcharts 给出的正确做法是写入 Controller 中(或 Model 中),具体写法见我在 8 楼给出的代码示例。
#21 楼 @jasontang168 我现在报废一台用了不到一年的苹果电脑,心情不好,不要找我。你就直接用上面那个 scss 的去覆盖对应的元素就行了!