base_ui/components/charts/PieDonut.vue

208 lines
7.6 KiB
Vue
Raw Permalink Normal View History

2025-02-01 09:34:55 +00:00
<template>
<div>
<v-chart
:key="jstreeCounter"
:option="options"
ref="chart"
@click="onChartClick"
:style="{ height: $attrs.height, width: $attrs.width }"
lazy
></v-chart>
</div>
</template>
<script>
//
import { use } from "echarts/core";
import { PieChart } from "echarts/charts";
import {
TitleComponent,
TooltipComponent,
LegendComponent,
} from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
use([
TitleComponent,
TooltipComponent,
LegendComponent,
PieChart,
CanvasRenderer,
]);
/**
* @vue-prop {Array} [dataPie=[]] - دادههای نمودار پای
* @vue-prop {Object} [PieOptions={}] - گزینههای نمودار پای
*
* @vue-data {Number} [jstreeCounter=1] - شمارنده jstree
* @vue-data {Object} [options] - گزینههای نمودار پای
* @vue-data {Object} [options.title] - عنوان نمودار
* @vue-data {String} [options.title.left="center"] - تراز عنوان
* @vue-data {Object} [options.tooltip] - راهنمای نمودار
* @vue-data {String} [options.tooltip.trigger="item"] - ماشه نمایش راهنما
* @vue-data {Function} [options.tooltip.formatter] - قالببندیکننده راهنما
* @vue-data {Object} [options.legend] - راهنمای نمودار
* @vue-data {Number} [options.legend.right=0] - تراز راست راهنما
* @vue-data {String} [options.legend.top="10%"] - تراز بالایی راهنما
* @vue-data {String} [options.legend.orient="vertical"] - جهت راهنما
* @vue-data {String} [options.legend.left="left"] - تراز چپ راهنما
* @vue-data {Object} [options.legend.textStyle] - سبک متن راهنما
* @vue-data {Function} [options.legend.formatter] - قالببندیکننده راهنما
* @vue-data {Array} [options.series] - دادههای سریهای نمودار
* @vue-data {Number} [options.series[].left=300] - تراز چپ سری نمودار
* @vue-data {Object} [options.series[].label] - برچسب سری نمودار
* @vue-data {Boolean} [options.series[].label.show=true] - نمایش برچسب
* @vue-data {Number} [options.series[].label.fontSize=15] - اندازه فونت برچسب
* @vue-data {String} [options.series[].label.fontFamily="sahel"] - فونت برچسب
* @vue-data {Function} [options.series[].label.formatter] - قالببندیکننده برچسب
* @vue-data {String} [options.series[].name="Access From"] - نام سری
* @vue-data {String} [options.series[].type="pie"] - نوع سری
* @vue-data {String} [options.series[].radius="50%"] - شعاع سری
* @vue-data {Object} [options.series[].emphasis] - تاکید سری
* @vue-data {Object} [options.series[].emphasis.label] - برچسب تاکید
* @vue-data {Boolean} [options.series[].emphasis.label.show=true] - نمایش برچسب تاکید
* @vue-data {Number} [options.series[].emphasis.label.fontSize=20] - اندازه فونت برچسب تاکید
* @vue-data {String} [options.series[].emphasis.label.fontWeight="bold"] - وزن فونت برچسب تاکید
* @vue-data {String} [options.series[].emphasis.label.fontFamily="sahel"] - فونت برچسب تاکید
* @vue-data {Object} [options.series[].emphasis.itemStyle] - سبک آیتم تاکید
* @vue-data {Number} [options.series[].emphasis.itemStyle.shadowBlur=10] - شعاع سایهی آیتم تاکید
* @vue-data {Number} [options.series[].emphasis.itemStyle.shadowOffsetX=0] - آفست سایهی آیتم تاکید در راستای x
* @vue-data {String} [options.series[].emphasis.itemStyle.shadowColor="rgba(0, 0, 0, 0.5)"] - رنگ سایهی آیتم تاکید
* @vue-data {Array} [options.series[].data] - دادههای سری نمودار
* @vue-data {Number} [options.series[].data[].value=1048] - مقدار داده سری نمودار
* @vue-data {String} [options.series[].data[].name="Search Engine"] - نام داده سری نمودار
*/
export default {
props: {
dataPie: {
default() {
return [];
},
type: Array,
},
PieOptions: {
default() {
return {};
},
type: Object,
},
},
data() {
return {
jstreeCounter: 1,
options: {
title: {
// text: "Referer of a Website",
// subtext: "Fake Data",
left: "center",
},
tooltip: {
trigger: "item",
formatter: (params) => {
return `${params.marker} ${params.name}: ${params.percent}%<br/>`;
},
},
legend: {
right: 0,
top: "10%",
orient: "vertical",
left: "left",
textStyle: { fontFamily: "sahel" },
formatter: (name) => {
const series = this.options.series[0];
const item = series.data.find((dataItem) => dataItem.name === name);
if (item) {
// اضافه کردن علامت درصد به نام مورد در راهنما
return `${name} (${item.value}%)`;
}
return name;
},
},
series: [
{
left: 300,
label: {
show: true,
fontSize: 15,
fontFamily: "sahel",
formatter: (params) => {
// اضافه کردن علامت درصد به label
return `${params.name}: ${params.value}%`;
},
},
name: "Access From",
type: "pie",
radius: "50%",
emphasis: {
label: {
show: true,
fontSize: 20,
fontWeight: "bold",
fontFamily: "sahel",
},
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: "rgba(0, 0, 0, 0.5)",
},
},
data: [
{ value: 1048, name: "Search Engine" },
{ value: 735, name: "Direct" },
{ value: 580, name: "Email" },
{ value: 484, name: "Union Ads" },
{ value: 300, name: "Video Ads" },
],
},
],
},
};
},
watch: {
dataPie(newData) {
const modifiedData = newData.map((item) => {
return {
name: item.name,
value: item.y,
};
});
this.$set(this.options.series[0], "data", modifiedData);
this.jstreeCounter++;
},
},
mounted() {
const modifiedData = this.dataPie.map((item) => {
return {
name: item.name,
value: item.y,
};
});
this.options.series[0].data = modifiedData;
if (this.PieOptions == {}) return;
let option = this.options.series[0];
this.options.series[0] = { ...option, ...this.PieOptions };
},
methods: {
/**
* رویداد کلیک بر روی نمودار.
* این متد زمانی فراخوانی میشود که کاربر بر روی یک مورد در نمودار کلیک میکند و اطلاعات مورد نظر را از آن مورد استخراج میکند و از طریق یک رویداد به خارج ارسال میکند.
*
* @param {object} event - رویداد کلیک بر روی نمودار
* @param {string} event.name - نام مورد انتخاب شده
* @param {number} event.value - مقدار مورد انتخاب شده
*/
onChartClick(event) {
const itemSelected = { name: event.name, y: event.value };
this.$emit("list", itemSelected);
},
},
};
</script>
<style lang="scss"></style>