antvis / my-f2

F2 的支付宝小程序版本
MIT License
146 stars 23 forks source link

绘制折线图时没有完整填充画布 #26

Closed linningmii closed 4 years ago

linningmii commented 4 years ago

重现步骤: 折线图放在一个mini-antui的popup组件中,popup弹出后有概率显示小图

我们在钉钉小程序上使用了mini-chart进行绘图,出现了截图所示的问题

最初我们设置的宽高是320和240,后来尝试使用dd.getSystemInfo获取屏幕宽度和pixelRatio通过my-f2直出图表,在iOS设备上依然会偶尔重现该问题。

linningmii commented 4 years ago

折线图组件实现

<view class="c-line-chart {{className ? className : ''}}">
  <view class="line-chart-title">{{title}}    
  </view>
  <view a:if="{{options.length}}" class="line-chart-options-container">
    <view a:for="{{options}}" onTap="onSelectOptionHandler" data-item="{{item}}" class="line-chart-option {{selectedOption === item.value ? 'active' : ''}}">{{item.label}}        
    </view>
  </view>
  <view class="line-chart-container">
    <line-chart a:if="{{series && series.length}}" categories="{{categories}}" series="{{series}}" xAxis="{{xAxis}}" yAxis="{{yAxis}}" legend="{{legend}}" tooltip="{{tooltip}}" height="{{height}}" width="{{width}}"/>
  </view>
</view>

调用位置

  <popup-modal show="{{showTrendPopup}}" onClose="onPopupClose" title="{{`${globalData.currentKpiGroup.indicators[globalData.activeBlockIndex].label}趋势图${lineChartPercentData ? '(%)' : ''}`}}" class="trend-chart-popup" loading="{{trendPopupLoading}}">
    <block a:if="{{showTrendPopup}}">
      <line-chart class="trend-line-chart" options="{{lineChartOptions}}" defaultOption="{{dateType}}" series="{{lineChartSeries}}" categories="{{lineChartXAxis}}" onOptionChange="handleLineChangeOption" width="{{lineChartWidth}}" height="{{lineChartHeight}}"/>
    </block>
  </popup-modal>
leungwensen commented 4 years ago

line-chart 里的 js 代码贴一下 @linningmii

leungwensen commented 4 years ago

@simaQ 可以帮忙看一下吗?

nichkun commented 4 years ago

line-chart 里的 js 代码贴一下 @linningmii

<view class="f2-container">
    <canvas id="trend" width="{{width}}" height="{{height}}"/>
</view>
import F2 from '@antv/my-f2'
function drawChart(canvas, data, width, height) {
  let chart = new F2.Chart({el: canvas, width, height})
  chart.source(data, {
    date: {
      range: [0, 1],
      type: 'timeCat',
      mask: 'MM-DD'
    },
    value: {
      max: 300,
      tickCount: 4
    }
  })
  chart.axis('date', {
    label(text, index, total) {
      const textCfg = {}
      if (index === 0) {
        textCfg.textAlign = 'left'
      }
      if (index === total - 1) {
        textCfg.textAlign = 'right'
      }
      return textCfg
    }
  })
  chart.line().position('date*value').color('city').adjust('stack')
  chart.render()
  return chart
}

Component({
  data: {
    height: 240,
    width: 320,
    selectedOption: null
  },
  props: {
    datas: [
      { value: 0, city: '日', date: '2011-10-01' },
      { value: 0, city: '日', date: '2011-10-02' },
      { value: 0, city: '日', date: '2011-10-03' },
      { value: 0, city: '日', date: '2011-10-04' },
      { value: 2323, city: '日', date: '2011-10-05' },
      { value: 6676, city: '日', date: '2011-10-06' }
    ]
  },
  didMount() {
    console.log('didMount')
    dd.createSelectorQuery()
      .select('#trend')
      .boundingClientRect()
      .exec(res => {
        // 获取分辨率
        const pixelRatio = dd.getSystemInfoSync().pixelRatio
        // 获取画布实际宽高
        const canvasWidth = Math.floor(res[0].width)
        const canvasHeight = Math.floor(res[0].height)
        // 高清解决方案
        this.setData({
          width: canvasWidth * pixelRatio,
          height: canvasHeight * pixelRatio
        })
        const myCtx = dd.createCanvasContext('trend')
        // 必要!按照设置的分辨率进行放大
        // 就是这里时而有效时而无效
        // myCtx.scale(1, 1) 永久小图
        myCtx.scale(pixelRatio, pixelRatio)
        const canvas = new F2.Renderer(myCtx)
        console.log(pixelRatio+':'+canvasWidth+':'+canvasHeight)
        drawChart(canvas, this.props.datas, canvasWidth, canvasHeight)
      })
  },
  didUnmount() {
    console.log('didUnmount')
  }
})
leungwensen commented 4 years ago

所以问题出现在 dd.getSystemInfoSync().pixelRatio 有时会变成 1 ? @nickyztt

leungwensen commented 4 years ago

你先试试把获取 pixelRatio 这件事放到全局上去,不要每次绘图都重新获取。有可能 popup 环境里这个值会不一样 @nickyztt

nichkun commented 4 years ago

你先试试把获取 pixelRatio 这件事放到全局上去,不要每次绘图都重新获取。有可能 popup 环境里这个值会不一样 @nickyztt

尝试过了,很尴尬,大图与小图信息完全是一样的(分别是分辨率:宽:高) image image

nichkun commented 4 years ago

固定为2倍情况也相同

https://github.com/antvis/my-f2/blob/master/src/renderer.js

myCtx.scale(2, 2)
const canvas = new F2.Renderer(myCtx)
leungwensen commented 4 years ago

drawChart(canvas, this.props.datas, canvasWidth * pixelRatio, canvasHeight * pixelRatio)

这样呢?

nichkun commented 4 years ago

解决了,如你所说,去掉 scale 缩放,改为画布* pixelRatio,然后手动设置趋势图日期和数据的文字大小就行了