The environment

Framework: UniApp package wechat applets

Echarts components: echarts-for-WX

Because of their own use of the pie chart multiple places reference, in order to reuse, packaged into a component

The problem

There is a fixed positioning button selection area on the page and a scroll bar in the interface content. However, due to the high level of canvas component, the canvas covers the fixed positioning button selection area during scrolling

Hit the pit

  1. Canvas belongs to the applets source component and has the highest level. It is invalidated by the z-index of other components
  2. Canvas drawing pictures must be wide and high, otherwise the white board will be displayed. Picture drawing is also a white board
  3. The canvas exported image must occupy a height, but opacity and visiblity are invalid on the real computer, and display cannot be used either

plan

After the echarts drawing is complete, the Canvas transformImage method is called to display the image and the canvas pans to the left, perfect solution

1, the outermost layer calls the pie chart component, only needs to pass the parameter, no special processing

. <pie-chart :canvasData="inspectorTasksStatistics.itemData" canvasId="inspect_chart" :nowRatio="inspectorTasksStatistics.completion_rate" ref="piechart" nowType="worker" ></pie-chart> ... . / / call peichart component method according to the ref enclosing getInspectorTasksStatistics (data). Then ((res) = > {try {this. $refs. Piechart. ChartInit (); } catch (e) { console.log(e); }}); .Copy the code

2. After the pie chart is introduced, when listening to switch, redraw the Echarts. After the Echarts draws finished, call the uni-EC-Canvas. vue transformImage method to redraw the image. Dynamically move the canvas by listening for value changes. When the value changes, draw the canvas first, and then move the canvas to display the picture when there is a picture. See chart_pie component for detailed operations:

<! <template> <view class="canvas-wrap"> <view> <! Uni-ec-canvas class="uni-ec-canvas" :class="{translateCanvas: isShowImage }" :ref="canvasId" canvas-id="uni-ec-canvas" :ec="ec" force-use-old-canvas="true" @chartImgUrl="chartImgUrlParent" > </uni-ec-canvas> </view> <! <view class="img-wrap"> <image class="img-chart" : SRC ="canvasImgUrl" v-if="isShowImage" mode="widthFix" ></image> </view> </view> </template> <script> import uniEcCanvas from ".. /.. /components/uni-ec-canvas/uni-ec-canvas.vue"; import * as echarts from ".. /.. /components/uni-ec-canvas/echarts"; export default { props: { canvasData: { type: Array }, canvasId: { type: String }, nowRatio: { tyoe: Number }, nowType: {type: String},}, components: {uniEcCanvas,}, data() {return {ec: {lazyLoad: true, // lazy loading}, canvasImgUrl: "", isShowImage: false, }; }, created() {}, mounted() { try { this.$refs[this.canvasId].init(this.initChart); } catch (error) { console.log(err); } }, methods: { chartInit() { this.$refs[this.canvasId].init(this.initChart); }, initChart(canvas, width, height, canvasDpr) { this.isShowImage = false; let chart = null; let that = this; chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: canvasDpr, }); canvas.setChart(chart); chart.setOption(this.pieGetOption()); On ("finished", function() {that.$refs[that.canvasid]. TransformImage (); this.isShowImage = true; }); return chart; }, // pieGetOption() {let that = this; let data = that.canvasData; let colorArr = []; if (this.nowType === "admin") { colorArr = ["#15ADEF", "#FFBF34", "#F0230D"]; } else if (this.nowType === "worker") { colorArr = ["#15ADEF", "#F0230D", "#FFBF34"]; } var option = {title: {text: "(this. NowRatio * 100).tofixed (2) + "%", right: 10, top: 15, textStyle: {fontSize: 13, fontWeight: 400,},}, Tooltip: {show: false,}, legend: {Orient: "vertical", // PageIconInactiveColor: "# CCC ", // Disable button color y: "center", // extend y axis center right: 10, top: 40, selectedMode: false, textStyle: { rich: { a: { fontSize: 12, padding: [0, 10, 0, 10], width: 35, }, b: { fontSize: 12, padding: [0, 10, 0, 10], width: 35, }, }, }, formatter: function(name) { var target; var total = 0; for (var i = 0, l = data.length; i < l; i++) { total += data[i].value; if (data[i].name == name) { target = data[i].value; } } var arr = ["{a|" + name + "}", "{b|" + target + "}"]; return arr.join(""); }, }, color: colorArr, series: [ { type: "pie", radius: "90%", center: ["25%", "50%"], data: that.canvasData, label: TextStyle: {fontWeight: 300, fontSize: {display: true, position: "inner", // 8, / / text font size color: "# FFF,"}, the formatter: "{b}, {c}",,}},},],}; return option; }, chartImgUrlParent(src) { this.canvasImgUrl = src; CanvasImgUrl (val, oldVal) {if (val! = oldVal) { this.isShowImage = true; } else { this.isShowImage = false; ,}}}}; </script> <style scoped> .canvas-wrap, .uni-ec-canvas, .img-wrap { width: 680rpx; height: 260rpx; } .canvas-wrap { position: relative; } .uni-ec-canvas { position: absolute; left: 0; top: 0; } .img-wrap { position: absolute; left: 0; top: 0; background: #fff; } .img-chart { width: 100%; height: 100%; } .translateCanvas { left: -1000rpx; } </style>Copy the code
Copy the code

Uni-ec-canvas /uni-ec-canvas. Vue adds code to convert canvas into image

methods:{ ... TransformImage () {let that = this; uni.canvasToTempFilePath( { canvasId: that.canvasId, success: (res) => { let tempFilePath = res.tempFilePath; that.$emit("chartImgUrl", tempFilePath); }, fail: (res) => { console.log(res); }, }, this ); },... }Copy the code

Final display effect: