微信小程序canvas图表层级过高问题

2,605 阅读3分钟

uni-app 微信小程序开始,引入的uchart,问题,canvas层级过高,出现穿透问题

uCharts-gitee

uchart常见问题

微信小程序图表层级过高问题

因canvas在微信小程序是原生组件,如果使用自定义tabbar或者自定义导航栏,图表则会超出预期,此时需要给组件的canvas2d传值true来使用type='2d'的功能,开启此模式后,一定要在组件上自定义canvasId,不能为数字,不能动态绑定,要为随机字符串!不能“真机调试”,不能“真机调试”,不能“真机调试”开发者工具显示不正常,图表层级会变高,而正常预览或者发布上线则是正常状态,开发者不必担心,一切以真机预览为准(因微信开发者工具显示不正确,canvas2d这种模式下给调试带来了困难,开发时,可以先用:canvas2d="false"来调试,预览无误后再改成true)。

开启canvas2d后图表不显示问题

开启canvas2d后,需要手动指定canvasId,并且父元素不能含有v-if,否则会导致获取不到dom节点问题,请将v-if改成v-show,更多开启canvas2d不显示问题,请参考示例项目pages/layout/layout.vue文件,对照示例项目修改您的项目。

其实代码都有写明,

下。

canvas.vue

解决:

需要微信小程序有canvas2d模式,canvas添加type="2d"

<canvas canvas-id="canvasArcbar1" id="canvasArcbar1" class="charts3" type="2d"></canvas>

canvas重新渲染问题

首页home.vue

需要数据添加成功之后返回页面,canvas根据新的内容重新渲染。

问题:原先是开始绘画接口放置在了mounted生命周期中,但是部分手机出现了不重新渲染的问题

解决:页面请求完成之后数据再进行渲染。

//home.vue
<canvas canvas-id="canvasArcbarHome" id="canvasArcbarHome" class="charts3" type="2d"></canvas>

data(){
  return{
        canvasId: 'canvasArcbarHome'
    }
},
onShow(){
  bloodSugarInfoApi().then(res => {
      if (res.code == 100 && res.data && res.data.bloodSugarNum) {
          this.bloodData = res.data
          this.measurementTime = res.data.dateTime
          this.bloodSugarNum = res.data.bloodSugarNum
          this.params = {}
        this.params.code = res.data.dataTypeCode
        //获取当前的params以及根据测量时间判断测量时段
        this.$nextTick(() => {
            this.initArcbar()
            // this.handelDrawArcbar(res.data.bloodSugarNum)
            this.diningCodeDegree()
            this.noOnShow = false
        })
      } else {
        this.bloodSugarNum = null
        this.measurementTime = null
        this.params = {}
      }
	})
}

记录页面record.vue

<canvas canvas-id="canvasArcbarRecord" id="canvasArcbarRecord" class="charts3" type="2d"></canvas>


data(){
  return{
         canvasId: 'canvasArcbarRecord'
    }
},
onLoad(options) {
  //获取当前的params以及根据测量时间判断测量时段
		this.diningTimeDegree()
}
mounted() {
  //进度条初始设置
  this.initArcbar()
},

公共的mixin-progree.js

//  mixin/mixin-progree.js
import {eatTimeArr, diningTimeArr} from '@/utils/data.js'
import uCharts from '@/uni_modules/qiun-data-charts/js_sdk/u-charts/u-charts'
var uChartsInstance = {}
export const mixinProgree = {
	data() {
		return {
			cWidth3: '', //圆弧进度图
			cHeight3: '', //圆弧进度图
			arcbarWidth: '', //圆弧进度图,进度条宽度,此设置可使各端宽度一致
			pixelRatio: 1, //设备像素比
			curRange: {}, //测量时段拿到的当前range,用于获取
			curEatTime: eatTimeArr[0], //就餐时间段 用于显示低血糖等
		}
	},
	computed: {
		testTime() {
			const time = this.curEatTime.time
			return time
		},
	},
	created() {},
	mounted() {
		console.log('进度条初始设置')
		//进度条初始设置
		this.initArcbar()
	},
	methods: {
		initArcbar() {
      console.log('开始绘画')
			//#ifdef MP-ALIPAY || MP-WEIXIN
			this.pixelRatio = uni.getSystemInfoSync().pixelRatio
			//#endif
			this.cWidth3 = uni.upx2px(400) //这里要与样式的宽高对应
			this.cHeight3 = uni.upx2px(400) //这里要与样式的宽高对应
			this.arcbarWidth = uni.upx2px(24)
			this.handelDrawArcbar(this.bloodSugarNum || '')
		},
		//input并出发canvas绘画
		handelDrawArcbar(value) {
			this.bloodSugarNum = Number(value)
			this.$u.debounce(this.drawArcbar)
		},
		//设置绘画参数
		drawArcbar() {
      console.log('设置绘画参数')
			this.setCurRange()
			const bloodNumPercentage = this.bloodSugarNum / 30
			const sendArcbar = {
				series: [
					{
						data: [bloodNumPercentage > 1 ? 1 : bloodNumPercentage],
					},
				],
			}
			let sendColor = ['#F3F6F6', '#F3F6F6'] //初始化样式
			if (this.curRange && bloodNumPercentage > 0) {
				sendColor = this.curRange.sendColor
			}
			console.log(this.curRange, ' this.curRange')
			this.showArcbar(this.canvasId, sendArcbar, sendColor)
		},

		//显示绘画
		showArcbar(canvasId, chartData, cirCor) {
      console.log('显示绘画', canvasId)
			const query = uni.createSelectorQuery().in(this)
			query
				.select('#' + canvasId)
				.fields({
					node: true,
					size: true,
				})
				.exec(res => {
					if (res[0]) {
						const canvas = res[0].node
						//v2.0版本必须要获取context并传入opts(option)中
						const ctx = canvas.getContext('2d')
						canvas.width = res[0].width * this.pixelRatio
						canvas.height = res[0].height * this.pixelRatio
						uChartsInstance[canvasId] = new uCharts({
							type: 'arcbar',
							fontSize: 11,
							legend: {show: false},
							background: '#FFFFFF',
							pixelRatio: this.pixelRatio, //像素
							series: chartData.series,
							animation: false,
							width: this.cWidth3 * this.pixelRatio,
							height: this.cHeight3 * this.pixelRatio,
							dataLabel: true,
							canvas2d: true, //开启canvas2d
							context: ctx || uni.createCanvasContext(canvasId, this), //v2.0版本必须要传contex
							extra: {
								arcbar: {
									type: 'default', //整圆类型进度条图
									width: this.arcbarWidth, //圆弧的宽度
									linearType: 'custom', //开启色值渐变色值
									customColor: cirCor, //渐变色值
									backgroundColor: '#F3F6F6', //环形图的剩余百分比颜色
								},
							},
						})
					} else {
						console.error('[uCharts]:未获取到context')
					}
				})
		},
		//获取当前的params以及根据测量时间判断测量时段
		diningTimeDegree() {
			const centerTime = this.$date.formatDate(this.measurementTime, 'hh:mm')
			const dining = diningTimeArr.find(v => centerTime >= v.start && centerTime < v.end)
			this.params = dining
			this.setCurEatTime()
		},
    //根据code获取当前的params
		diningCodeDegree() {
			const dining = diningTimeArr.find(v => v.code == this.params.code)
			this.params = dining
			this.setCurEatTime()
		},
		//获取当前的血糖值  根据code查询 red:严重  orange:偏高  green:正常  blue1:偏低  blue2:低血糖
		setCurRange() {
			const bloodSugarNum = this.bloodSugarNum || 0
			const code = this.params.code || 0
			const obj = diningTimeArr.find(v => v.code == code)
			if (obj) {
				const curRange = obj.range.find(v => bloodSugarNum >= v.min && bloodSugarNum < v.max)
				this.curRange = curRange
			}
		},
		//获取当前选中的就餐时间段 根据code查询
		setCurEatTime() {
			const eatTime = eatTimeArr.find(v => v.code == this.params.code)
			this.curEatTime = eatTime
		},
	},
}
// canvas 进度条
.charts3 {
	width: 400rpx;
	height: 400rpx;
	margin: 0 auto;
}