您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“在vue中怎么封裝G2圖表”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
<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'); // 獲取坐標(biāo)系對(duì)象 var center = coord.center; // 極坐標(biāo)圓心坐標(biāo) var r = coord.radius; // 極坐標(biāo)半徑 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; // 左側(cè)文本左對(duì)齊并貼著畫布最左側(cè)邊緣 labelAttrs.textAlign = 'left'; } else { lastPoint.x = canvasWidth - APPEND_OFFSET; labelAttrs.x = canvasWidth - APPEND_OFFSET; // 右側(cè)文本右對(duì)齊并貼著畫布最右側(cè)邊緣 labelAttrs.textAlign = 'right'; } // 繪制文本 var text = labelGroup.addShape('Text', { attrs: labelAttrs }); labels.push(text); // 繪制連接線 var points = void 0; if (_router.y !== y) { // 文本位置做過調(diào)整 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獲取餅圖點(diǎn)位置 getEndPoint(center, angle, r) { return { x: center.x + r * Math.cos(angle), y: center.y + r * Math.sin(angle) }; } }, watch: { gtwopiedata: function (val, oldVal) { // 監(jiān)聽數(shù)據(jù),當(dāng)發(fā)生變化時(shí),觸發(fā)回調(diào)函數(shù)繪制圖表,使用mounted無法正常繪制 // if(this.dothisfun){ this.g2pie(val); // this.dothisfun = false // } } }, // mounted(){ // this.g2pie(); // } } </script>
<style scoped> #id{ width: 100%; height: 100%; } </style>
本來是想將生成的方法封裝到j(luò)s文件中的,但是不知道為什么,import G2 進(jìn)入js文件之后,vue便會(huì)卡在92%無法繼續(xù)熱更新,node的cpu占用率也會(huì)飽滿,所以只好封裝在.vue文件中,以子組件的形式被父組件調(diào)用。
本處需要注意的第一個(gè)問題,即為data中定義的chart,如果不定義,直接用let chart = new G2.chart(),也確實(shí)能夠正常生成圖表,但是當(dāng)數(shù)據(jù)更新的時(shí)候,便會(huì)重新渲染生成新的圖表,此時(shí)頁面上會(huì)同時(shí)存在多個(gè)圖表,所以需要提前定義chart,并使用this.chart = new G2.chart()。
本處需要注意的第二個(gè)問題,即為使用mounted鉤子函數(shù)運(yùn)行此函數(shù)時(shí),因?yàn)椴⑽礄z測到數(shù)據(jù)變化,所以不會(huì)生成有效圖表,所以需要使用watch監(jiān)聽數(shù)據(jù)變化,當(dāng)發(fā)生變化的時(shí)候,執(zhí)行方法渲染圖表。
G2 是一套基于圖形語法理論的可視化底層引擎,以數(shù)據(jù)驅(qū)動(dòng),提供圖形語法與交互語法,具有高度的易用性和擴(kuò)展性。使用 G2,你可以無需關(guān)注圖表各種繁瑣的實(shí)現(xiàn)細(xì)節(jié),一條語句即可使用 Canvas 或 SVG 構(gòu)建出各種各樣的可交互的統(tǒng)計(jì)圖表;
???? 完善的圖形語法:數(shù)據(jù)到圖形的映射,能夠繪制出所有的圖表;
???? 全新的交互語法:通過觸發(fā)和反饋機(jī)制可以組合出各種交互行為,對(duì)數(shù)據(jù)進(jìn)行探索;
???? 強(qiáng)大的 View 模塊:可支持開發(fā)個(gè)性化的數(shù)據(jù)多維分析圖形;
???? 雙引擎渲染:Canvas 或 SVG 任意切換;
???? 可視化組件體系:面向交互、體驗(yàn)優(yōu)雅;
?全面擁抱 TypeScript:提供完整的類型定義文件;
安裝G2依賴:
npm instal @antv/g2
在繪圖前我們需要為 G2 準(zhǔn)備一個(gè) DOM 容器:
<div id="c1"></div>
執(zhí)行代碼:
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: 創(chuàng)建 Chart 對(duì)象 const chart = new G2.Chart({ container: 'c1', // 指定圖表容器 ID width: 600, // 指定圖表寬度 height: 300, // 指定圖表高度 }); // Step 2: 載入數(shù)據(jù)源 chart.data(data); // Step 3:創(chuàng)建圖形語法,繪制柱狀圖 chart.interval().position('genre*sold'); // Step 4: 渲染圖表 chart.render(); } }
效果展示:
“在vue中怎么封裝G2圖表”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。