您好,登錄后才能下訂單哦!
本篇內容介紹了“在vue中怎么封裝G2圖表”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
<template> <div id="id"></div> </template>
<script> import G2 from '@antv/g2' import { DataSet } from '@antv/data-set' export default { name: 'pie', data () { return { chart: null }; }, props:{ gtwopiedata:{ type: Array }, // gtwopiecolor:{ // type: Array // }, }, methods:{ g2pie(){ if(this.chart){ // 如果存在的話就刪除圖表再重新生成 this.chart.destroy() } var startAngle = - Math.PI / 2 - Math.PI / 4; var data = this.gtwopiedata.data; var ds = new DataSet(); var dv = ds.createView().source(data); dv.transform({ type: 'percent', field: 'value', dimension: 'type', as: 'percent' }); this.chart = new G2.Chart({ container: 'id', forceFit: true, height: this.gtwopiedata.height, padding: 'auto' }); this.chart.source(dv); this.chart.legend(false); this.chart.coord('theta', { radius: 0.75, innerRadius: 0.5, startAngle: startAngle, endAngle: startAngle + Math.PI * 2 }); this.chart.intervalStack().position('value').color('type', this.gtwopiedata.color).opacity(1).label('percent', { offset: -20, textStyle: { fill: 'white', fontSize: 12, shadowBlur: 2, shadowColor: 'rgba(0, 0, 0, .45)' }, formatter: function formatter(val) { return parseInt(val * 100) + '%'; } }); this.chart.guide().html({ position: ['50%', '50%'], html: '<div class="g2-guide-html"><p class="title">'+this.gtwopiedata.title+'</p></div>' }); this.chart.render(); //draw label var OFFSET = 20; var APPEND_OFFSET = 50; var LINEHEIGHT = 60; var coord = this.chart.get('coord'); // 獲取坐標系對象 var center = coord.center; // 極坐標圓心坐標 var r = coord.radius; // 極坐標半徑 var canvas = this.chart.get('canvas'); var canvasWidth = this.chart.get('width'); var canvasHeight = this.chart.get('height'); var labelGroup = canvas.addGroup(); var labels = []; // addPieLabel(this.chart); var halves = [[], []]; var data = dv.rows; var angle = startAngle; for (var i = 0; i < data.length; i++) { var percent = data[i].percent; var targetAngle = angle + Math.PI * 2 * percent; var middleAngle = angle + (targetAngle - angle) / 2; angle = targetAngle; var edgePoint = this.getEndPoint(center, middleAngle, r); var routerPoint = this.getEndPoint(center, middleAngle, r + OFFSET); //label var label = { _anchor: edgePoint, _router: routerPoint, _data: data[i], x: routerPoint.x, y: routerPoint.y, r: r + OFFSET, fill: '#bfbfbf' }; // 判斷文本的方向 if (edgePoint.x < center.x) { label._side = 'left'; halves[0].push(label); } else { label._side = 'right'; halves[1].push(label); } } // end of for var maxCountForOneSide = parseInt(canvasHeight / LINEHEIGHT, 10); halves.forEach(function(half, index) { // step 2: reduce labels if (half.length > maxCountForOneSide) { half.sort(function(a, b) { return b._percent - a._percent; }); half.splice(maxCountForOneSide, half.length - maxCountForOneSide); } // step 3: distribute position (x and y) half.sort(function(a, b) { return a.y - b.y; }); // antiCollision(half, index); var startY = center.y - r - OFFSET - LINEHEIGHT; var overlapping = true; var totalH = canvasHeight; var i = void 0; var maxY = 0; var minY = Number.MIN_VALUE; var boxes = half.map(function(label) { var labelY = label.y; if (labelY > maxY) { maxY = labelY; } if (labelY < minY) { minY = labelY; } return { size: LINEHEIGHT, targets: [labelY - startY] }; }); if (maxY - startY > totalH) { totalH = maxY - startY; } while (overlapping) { boxes.forEach(function(box) { var target = (Math.min.apply(minY, box.targets) + Math.max.apply(minY, box.targets)) / 2; box.pos = Math.min(Math.max(minY, target - box.size / 2), totalH - box.size); }); // detect overlapping and join boxes overlapping = false; i = boxes.length; while (i--) { if (i > 0) { var previousBox = boxes[i - 1]; var box = boxes[i]; if (previousBox.pos + previousBox.size > box.pos) { // overlapping previousBox.size += box.size; previousBox.targets = previousBox.targets.concat(box.targets); // overflow, shift up if (previousBox.pos + previousBox.size > totalH) { previousBox.pos = totalH - previousBox.size; } boxes.splice(i, 1); // removing box overlapping = true; } } } } // step 4: normalize y and adjust x i = 0; boxes.forEach(function(b) { var posInCompositeBox = startY; // middle of the label b.targets.forEach(function() { half[i].y = b.pos + posInCompositeBox + LINEHEIGHT / 2; posInCompositeBox += LINEHEIGHT; i++; }); }); // (x - cx)^2 + (y - cy)^2 = totalR^2 half.forEach(function(label) { var rPow2 = label.r * label.r; var dyPow2 = Math.pow(Math.abs(label.y - center.y), 2); if (rPow2 < dyPow2) { label.x = center.x; } else { var dx = Math.sqrt(rPow2 - dyPow2); if (!index) { // left label.x = center.x - dx; } else { // right label.x = center.x + dx; } } // drawLabel(label); var _anchor = label._anchor, _router = label._router, fill = label.fill, y = label.y; var labelAttrs = { y: y, fontSize: 12, // 字體大小 fill: '#808080', text: label._data.type + '\n' + label._data.value, textBaseline: 'bottom' }; var lastPoint = { y: y }; if (label._side === 'left') { // 具體文本的位置 lastPoint.x = APPEND_OFFSET; labelAttrs.x = APPEND_OFFSET; // 左側文本左對齊并貼著畫布最左側邊緣 labelAttrs.textAlign = 'left'; } else { lastPoint.x = canvasWidth - APPEND_OFFSET; labelAttrs.x = canvasWidth - APPEND_OFFSET; // 右側文本右對齊并貼著畫布最右側邊緣 labelAttrs.textAlign = 'right'; } // 繪制文本 var text = labelGroup.addShape('Text', { attrs: labelAttrs }); labels.push(text); // 繪制連接線 var points = void 0; if (_router.y !== y) { // 文本位置做過調整 points = [[_anchor.x, _anchor.y], [_router.x, y], [lastPoint.x, lastPoint.y]]; } else { points = [[_anchor.x, _anchor.y], [_router.x, _router.y], [lastPoint.x, lastPoint.y]]; } labelGroup.addShape('polyline', { attrs: { points: points, lineWidth: 1, stroke: fill } }); }); }); canvas.draw(); // this.chart.on('afterpaint', function() { // addPieLabel(this.chart); // }); }, // g2獲取餅圖點位置 getEndPoint(center, angle, r) { return { x: center.x + r * Math.cos(angle), y: center.y + r * Math.sin(angle) }; } }, watch: { gtwopiedata: function (val, oldVal) { // 監聽數據,當發生變化時,觸發回調函數繪制圖表,使用mounted無法正常繪制 // if(this.dothisfun){ this.g2pie(val); // this.dothisfun = false // } } }, // mounted(){ // this.g2pie(); // } } </script>
<style scoped> #id{ width: 100%; height: 100%; } </style>
本來是想將生成的方法封裝到js文件中的,但是不知道為什么,import G2 進入js文件之后,vue便會卡在92%無法繼續熱更新,node的cpu占用率也會飽滿,所以只好封裝在.vue文件中,以子組件的形式被父組件調用。
本處需要注意的第一個問題,即為data中定義的chart,如果不定義,直接用let chart = new G2.chart(),也確實能夠正常生成圖表,但是當數據更新的時候,便會重新渲染生成新的圖表,此時頁面上會同時存在多個圖表,所以需要提前定義chart,并使用this.chart = new G2.chart()。
本處需要注意的第二個問題,即為使用mounted鉤子函數運行此函數時,因為并未檢測到數據變化,所以不會生成有效圖表,所以需要使用watch監聽數據變化,當發生變化的時候,執行方法渲染圖表。
G2 是一套基于圖形語法理論的可視化底層引擎,以數據驅動,提供圖形語法與交互語法,具有高度的易用性和擴展性。使用 G2,你可以無需關注圖表各種繁瑣的實現細節,一條語句即可使用 Canvas 或 SVG 構建出各種各樣的可交互的統計圖表;
???? 完善的圖形語法:數據到圖形的映射,能夠繪制出所有的圖表;
???? 全新的交互語法:通過觸發和反饋機制可以組合出各種交互行為,對數據進行探索;
???? 強大的 View 模塊:可支持開發個性化的數據多維分析圖形;
???? 雙引擎渲染:Canvas 或 SVG 任意切換;
???? 可視化組件體系:面向交互、體驗優雅;
?全面擁抱 TypeScript:提供完整的類型定義文件;
安裝G2依賴:
npm instal @antv/g2
在繪圖前我們需要為 G2 準備一個 DOM 容器:
<div id="c1"></div>
執行代碼:
import * as G2 from '@antv/g2'; export default { mounted() { const data = [ { genre: 'Sports', sold: 275 }, { genre: 'Strategy', sold: 115 }, { genre: 'Action', sold: 120 }, { genre: 'Shooter', sold: 350 }, { genre: 'Other', sold: 150 }, ]; // Step 1: 創建 Chart 對象 const chart = new G2.Chart({ container: 'c1', // 指定圖表容器 ID width: 600, // 指定圖表寬度 height: 300, // 指定圖表高度 }); // Step 2: 載入數據源 chart.data(data); // Step 3:創建圖形語法,繪制柱狀圖 chart.interval().position('genre*sold'); // Step 4: 渲染圖表 chart.render(); } }
效果展示:
“在vue中怎么封裝G2圖表”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。