How to remove line over the stroke line in area chart - Apexchart. the image
Please help me to fix this!
Here is my code so far
<template>
<div id="chart">
<apexchart
ref="pricesRef"
type="area"
height="150"
:options="options"
:series="series"
></apexchart>
<!-- <button #click="updateSeries">click</button> -->
</div>
</template>
<script>
import { axios } from 'boot/axios';
// import { dates, prices } from 'src/services/area-chart';
import { date } from 'quasar';
function formatNumber2(number, tofix) {
const val = (number / 1).toFixed(tofix).replace(',', ' ');
return val.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
let sharePrice = [];
const dataSharePrice = [];
export default {
name: 'AreaChart',
data() {
return {
timeInterval: 0,
dataSharePrice: [],
series: [
{
name: 'Share Price',
data: [
// { x: dates[0], y: prices[1] },
// { x: 1602392287529, y: 0.05 },
],
date: [],
},
],
options: {
chart: {
type: 'area',
zoom: {
enabled: false,
},
toolbar: {
show: false,
},
sparkline: {
enabled: true,
},
},
tooltip: {
custom({ series, w, dataPointIndex }) {
const unixTime = w.config.series[0].data[dataPointIndex].x;
const timeStamp = new Date(unixTime * 1000);
const hour = date.formatDate(timeStamp, 'DD MMMM');
return (
`
<div class="arrow_box_tooltip q-pa-md">
<span class="text-h6">
Date: ${hour}</span>
<br />
<span class="text-h6">
Share Price: $${formatNumber2(
series[0][dataPointIndex],
0,
)} USD</span>
</div>
`
);
},
},
noData: {
text: 'Loading...',
},
dataLabels: {
enabled: false,
},
stroke: {
curve: 'smooth',
lineCap: 'butt',
colors: undefined,
width: 2,
},
title: {
text: '',
align: 'left',
},
grid: {
show: false,
},
xaxis: {
type: 'datetime',
},
yaxis: {
opposite: true,
},
legend: {
horizontalAlign: 'left',
},
},
};
},
computed: {},
methods: {
getData() {
axios
.get(
'apiurl',
)
.then((response) => {
// console.log(response.data.prices);
sharePrice = response.data.prices;
})
.catch((err) => {
console.log(err);
});
},
updateSeriesData() {
for (const price of sharePrice) {
const unixTime = price[0];
if (Object.keys(price).length > 0) {
dataSharePrice.push({
x: unixTime,
y: price[1],
});
} else {
dataSharePrice.push({});
console.log('err');
}
// console.log(price[0], price[1]);
}
// console.log(dataSharePrice);
this.series[0].data = dataSharePrice;
this.$refs.pricesRef.updateSeries([
{
data: dataSharePrice,
},
]);
// console.log(this.$refs);
},
// timer() {},
},
mounted() {},
async created() {
await this.getData();
setTimeout(() => {
this.updateSeriesData();
// console.log('done');
}, 3000);
/* ; */
// this.timer();
},
beforeDestroy() {
// clearInterval(this.timer);
},
};
</script>
<style scoped>
/* #chart {
background-color: #18212f;
opacity: 1;
background-size: 7px 7px;
background-image: repeating-linear-gradient(
45deg,
#111726 0,
#111726 0.7000000000000001px,
#18212f 0,
#18212f 50%
);
} */
</style>
You can specify each stroke width separately by passing array
stroke: {
curve: 'smooth',
lineCap: 'butt',
colors: undefined,
width: [2,0],
},
Related
I have an application with nuxt.js as a framework and it's running well in development mode. However, when I deployed to the server for production, it's show "window is not defined".
I think it's because highcharts-vue.min.js module not loaded in components so shows this error but I'm not sure about that. I attach some code and screen shoot results after deploying on the server
<template>
<highcharts class="hc" :options="chartOptions" ref="chart">
</highcharts>
</template>
<script>
import {Chart} from 'highcharts-vue'
export default {
name:"ForecastCuaca",
components: {
highcharts: Chart
},
data() {
return {
data_cuaca:[],
chartOptions: {
chart: {
type: 'spline',
backgroundColor: 'transparent',
marginTop:100
},
title: {
text: 'Prakiraan Cuaca Kota Kupang',
style:{
"color": "#ebeefd",
"fontSize": "22px"
}
},
subtitle: {
text: 'Source: openweathermap.org',
style:{
"color": "#ebeefd",
}
},
xAxis: {
categories: ['Tanggal'],
labels:{
style:{
color:"#ebeefd"
}
}
},
yAxis: {
title: {
text: 'Suhu'
},
labels: {
formatter: function () {
return this.value + '°';
},
style:{
color:"#ebeefd"
}
},
style:{
"color": "#ebeefd",
}
},
tooltip: {
formatter: function () {
return 'Suhu : ' + this.y + '° C<br /><b>' + this.x + '</b>';
}
},
plotOptions: {
spline: {
marker: {
radius: 4,
lineColor: '#666666',
lineWidth: 1
}
}
},
series: [{
name: 'Kota Kupang',
marker: {
symbol: 'square'
},
data: [
10
],
style:{
"color": "#ebeefd",
}
}
],
credits:{
enabled:false
}
},
title: '',
}
},
methods:{
generate_data(datax){
const self = this;
self.data_cuaca = datax
self.chartOptions.xAxis.categories = []
self.chartOptions.series[0].data = []
let ganjil = 0;
for (let index = 0; index < self.data_cuaca.length; index++) {
ganjil++;
const element = self.data_cuaca[index];
self.chartOptions.xAxis.categories.push(element.waktu_indonesia)
if (ganjil % 2 == 1) {
const iconx = element.weather[0].icon+'.png';
const data_series = {
y:element.main.temp,
marker: {
symbol: "url(http://openweathermap.org/img/w/"+iconx+")"
}
}
self.chartOptions.series[0].data.push(data_series)
}else{
self.chartOptions.series[0].data.push(element.main.temp)
}
}
}
}
}
</script>
I have difficult situation with updates dynamically data on charts. I created vue component that must render analytics from axios. There are several functions (methods) which parse arrived jsons from several API.
I created draw() - method for render every charts.
draw() {
if (this.mychart) {
this.mychart.destroy();
}
const ctx = document.getElementById('main-chart');
this.mychart = new Chart(ctx,
{
type: 'line',
data: {
labels: this.labels,
datasets: this.datacollection
},
options: {
legend: {
display: true,
position: 'bottom',
},
responsive: true,
scales: {
xAxes: [{
type: "time",
display: true,
scaleLabel: {
display: false,
},
ticks: {
major: {
fontStyle: "bold",
fontColor: "#FF0000"
}
}
}],
yAxes: [
{
id: 'y1',
type: 'linear',
position: 'left',
display: false
},
{
id: 'y2',
type: 'linear',
position: 'right',
display: false
},
{
id: 'y3',
type: 'linear',
position: 'left',
display: false
},
{
id: 'y4',
type: 'linear',
position: 'right',
display: false
},
{
id: 'y5',
type: 'linear',
position: 'left',
display: false
},
{
display: false,
gridLines: {
display: false
},
scaleLabel: {
display: true,
labelString: this.labelY
},
ticks: {
min: 0, // it is for ignoring negative step.
beginAtZero: true,
stepSize: 100
}
}]
}
}
});
},
All operations for calculating (parsing) data I do in mounted hook.
Also added in mounted hook nextTick() for delay render charts before data finish parsing.
async mounted() {
await this.loadIncomings(this.clubsId),
await this.loadAvgIncomings(this.clubsId),
await this.loadAvgPayments(this.clubsId),
await this.loadAvgSchedule(this.clubsId),
await this.loadTrainings(this.clubsId)
this.$nextTick(() => {
this.draw()
})
},
Now if internet connection is fast - charts render at one time. If you refresh page - you must waiting approximately 5-20 seconds for parsing data, and after this - appear graphs.
But, if I have bad connection, some axios requests finish with errors, and appear not all charts. And also I must waiting longer for parsing.
Finally, I have situation, that when I refresh page - several seconds page is empty. If connection is bad- not all charts render.
After this I have several questions:
1)How I could start render some finished data by chartjs in first seconds?
I mean not waiting when all data will come and calculated. I would like , that my charts render step by step. I want see y-axis and x-axis after I click refresh window.
Now I am using nextTick() but it is like 2nd step, where 1st step - is parsing data (may be I don't correctly understand)
I found some answers on similar question with render dynamic data, and people offered use chart.update(). But I can't get it. Where I must input this? If you look at my component, I have special method - draw(). If input in final string in my method with parsing data like : this.draw.mychart.update() or this.mychart.update() - I receive error in browser.
For example this function:
async loadIncomings(clubsId) {
try {
for (let clubId in clubsId) {
clubId = clubsId[clubId]
let dateFrom = this.dateFrom
let dateTo = this.dateTo
let groupBy = 'month'
let potential = true
let definitely = true
await this.$store.dispatch('loadIncomings', { clubId, dateFrom, dateTo, groupBy, potential, definitely }) // here I am waiting data from store (in store I use axios)
this.draftData = this.$store.state.incomings
if (this.labels.length === 0) {
this.getDates()
}
this.flagStartDate = true
await this.getIncomings(clubId)
this.flagStartDate = false
}
this.getIncomingsTotal()
this.draw.mychart.update() // here I am trying to refresh charts like advice from forums
} catch (e) {
console.error(e)
}
},
As you can see, this.getIncomingsTotal() - is last method for parsing data. After him, I am trying to update chart. But it's doesn't work.
Analytics-test.vue?b2a7:177 TypeError: Cannot read properties of undefined (reading 'update')
at VueComponent.loadIncomings (Analytics-test.vue?b2a7:175:1)
at async VueComponent.mounted (Analytics-test.vue?b2a7:498:1)
2)Also I use vue2-datepicker. I want set range dateFrom/dateTo. But when I choose date - charts doesn't change.
I have watch() , where I can monitoring dates dateFrom() and dateTo(). And also I am trying to rechart graphs with new dates - but nothing changes.
watch: {
dateFrom() {
console.log('dateFrom changed to', this.dateFrom)
this.draw()
},
dateTo() {
console.log('dateTo changed to', this.dateTo)
this.draw()
}
},
Under I show you my component:
<template>
<div class="container">
<h3>Прибыль/посещаемость</h3>
<date-picker v-model="dateFrom" valueType="date"></date-picker>
<date-picker v-model="dateTo" valueType="date"></date-picker>
<canvas id="main-chart"></canvas>
</div>
</template>
<script>
import Chart from 'chart.js';
import DatePicker from 'vue2-datepicker';
import 'vue2-datepicker/index.css';
export default {
name: 'Analytics-test',
components: {
DatePicker
},
data: () => ({
dateFrom: new Date('2021-12-01'),
dateTo: new Date(),
flagStartDate: false,
chartData: null,
labels: [],
dataset: {},
draftData: null,
data: [],
datacollection: [],
clubsId: ['5c3c5e12ba86198828baa4a7', '5c3c5e20ba86198828baa4c5', '60353d6edbb58a135bf41856', '61e9995d4ec0f29dc8447f81', '61e999fc4ec0f29dc844835e'],
}),
methods: {
draw() {
if (this.mychart) {
this.mychart.destroy();
}
const ctx = document.getElementById('main-chart');
this.mychart = new Chart(ctx,
{
type: 'line',
data: {
labels: this.labels,
datasets: this.datacollection
},
options: {
legend: {
display: true,
position: 'bottom',
},
responsive: true,
elements: {
line: {
// tension: 0, // disables bezier curves
// bezierCurve: false
}
},
scales: {
xAxes: [{
type: "time",
display: true,
// gridLines: {
// display: false
// },
scaleLabel: {
display: false,
// labelString: 'Time'
},
ticks: {
major: {
fontStyle: "bold",
fontColor: "#FF0000"
}
}
}],
yAxes: [
{
id: 'y1',
type: 'linear',
position: 'left',
display: false
},
{
id: 'y2',
type: 'linear',
position: 'right',
display: false
},
{
id: 'y3',
type: 'linear',
position: 'left',
display: false
},
{
id: 'y4',
type: 'linear',
position: 'right',
display: false
},
{
id: 'y5',
type: 'linear',
position: 'left',
display: false
},
{
display: false,
gridLines: {
display: false
},
scaleLabel: {
display: true,
labelString: this.labelY
},
ticks: {
min: 0, // it is for ignoring negative step.
beginAtZero: true,
stepSize: 100 // if i use this it always set it '1', which look very awkward if it have high value e.g. '100'.
}
}]
}
}
});
},
// Выручка
incomingsClub(clubId) {
switch (clubId) {
case '5c3c5e12ba86198828baa4a7':
return { label: "Выручка Фрунзенской", borderColor: "#3e95cd", fill: false }
case '5c3c5e20ba86198828baa4c5':
return { label: "Выручка Чернышевской", borderColor: "#8e5ea2", fill: false };
case '60353d6edbb58a135bf41856':
return { label: "Выручка Василеостровской", borderColor: "#e8c3b9", fill: false };
case '61e9995d4ec0f29dc8447f81':
return { label: "Выручка Московской", borderColor: "#3cba9f", fill: false };
case '61e999fc4ec0f29dc844835e':
return { label: "Выручка Лесной", borderColor: "#c45850", fill: false };
case 'all':
return { label: "Выручка сети", borderColor: "#8e8786", fill: false };
default:
return 'Неизвестный клуб';
}
},
async loadIncomings(clubsId) {
try {
for (let clubId in clubsId) {
clubId = clubsId[clubId]
let dateFrom = this.dateFrom
let dateTo = this.dateTo
let groupBy = 'month'
let potential = true
let definitely = true
await this.$store.dispatch('loadIncomings', { clubId, dateFrom, dateTo, groupBy, potential, definitely })
this.draftData = this.$store.state.incomings
if (this.labels.length === 0) {
this.getDates()
}
this.flagStartDate = true
await this.getIncomings(clubId)
this.flagStartDate = false
}
this.getIncomingsTotal()
// this.draw.mychart.update()
} catch (e) {
console.error(e)
}
},
getDates() {
for (let item in this.draftData) {
if (item === 'items') {
for (let elem in this.draftData[item]) {
this.labels.push(this.draftData[item][elem].date.slice(0, 7))
}
}
}
},
bindDataDates(indexDate) {
return Array(indexDate).fill(null);
},
getIncomings(clubId) {
for (let item in this.draftData) {
if (item === 'items') {
for (let elem in this.draftData[item]) {
let positionDate = this.labels.indexOf(this.draftData[item][elem].date.slice(0, 7))
if (this.flagStartDate && positionDate > 0) {
let zerroArray = this.bindDataDates(positionDate)
this.data = this.data.concat(zerroArray)
}
this.data.push(this.draftData[item][elem].amount)
this.flagStartDate = false
}
this.dataset.data = this.data
Object.assign(this.dataset, this.incomingsClub(clubId))
Object.assign(this.dataset, { yAxisID: 'y1' })
this.datacollection.push(this.dataset)
this.data = []
this.dataset = {}
}
}
},
getIncomingsTotal() {
for (let item in this.datacollection) {
if (!this.data.length) {
this.data = this.datacollection[item].data
continue
}
const firstArr = this.data
const secondArr = this.datacollection[item].data;
this.data = []
let length;
if (firstArr.length >= secondArr.length) {
length = firstArr.length;
} else {
length = secondArr.length;
}
for (let i = 0; i < length; i++) {
const a = firstArr[i] === undefined ? 0 : firstArr[i];
const b = secondArr[i] === undefined ? 0 : secondArr[i];
this.data.push(a + b);
}
}
this.dataset.data = this.data
Object.assign(this.dataset, this.incomingsClub('all'))
Object.assign(this.dataset, { yAxisID: 'y1' })
this.datacollection.push(this.dataset)
this.data = []
this.dataset = {}
},
// Средняя сумма за жизнь
avgIncomingsClub(clubId) {
omitted..
},
getDatesAvgIncome() {
omitted..
},
async loadAvgIncomings(clubsId) {
omitted..
},
getAvgIncomings(clubId) {
omitted..
},
// Среднее кол-во оплат
avgPaymentsClub(clubId) {
omitted..
},
async loadAvgPayments(clubsId) {
omitted..
},
getAvgPayments(clubId) {
omitted..
},
// Посещаемость
avgAttendanceClub(clubId) {
omitted..
},
async loadAvgSchedule(clubsId) {
omitted..
},
getAvgAttendance(clubId) {
omitted..
},
// Тренировок
participantsCountClub(clubId) {
omitted..
},
async loadTrainings(clubsId) {
omitted..
},
async getParticipantsCount(clubId) {
omitted..
},
watch: {
dateFrom() {
console.log('dateFrom changed to', this.dateFrom)
this.draw()
},
dateTo() {
console.log('dateTo changed to', this.dateTo)
this.draw()
}
},
async mounted() {
await this.loadIncomings(this.clubsId),
await this.loadAvgIncomings(this.clubsId),
await this.loadAvgPayments(this.clubsId),
await this.loadAvgSchedule(this.clubsId),
await this.loadTrainings(this.clubsId)
this.$nextTick(() => {
this.draw()
})
},
</script>
<style>
.container form {
display: flex;
}
</style>
I skipped code in other functions because it's doesn't matter. Situation with other the same.
I am trying to integrate datepicker in my chart. But after selecting dateTo or dateFrom - nothing changes.
I have used construction this.chart.update() in watch.
I logged this.chart.update(), and I see following:
What I am doing wrong?
Why my chart don't update?
If put in watch just draw() - charts will be update, but dateTo or dateFrom - will be old (not that I select in datepicker).
<template>
<div class="container">
<h3>Прибыль/посещаемость</h3>
<date-picker v-model="dateFrom" valueType="date"></date-picker>
<date-picker v-model="dateTo" valueType="date"></date-picker>
<canvas ref="mainChart"></canvas>
</div>
</template>
<script>
import Chart from 'chart.js';
import DatePicker from 'vue2-datepicker';
import 'vue2-datepicker/index.css';
export default {
name: 'Analytics-test',
components: {
DatePicker
},
data: () => ({
dateFrom: new Date('2021-11-01'),
dateTo: new Date(),
flagStartDate: false,
chartData: null,
mychart:null,
labels: [],
dataset: {},
draftData: null,
data: [],
datacollection: [],
clubsId: ['5c3c5e12ba86198828baa4a7', '5c3c5e20ba86198828baa4c5', '60353d6edbb58a135bf41856', '61e9995d4ec0f29dc8447f81', '61e999fc4ec0f29dc844835e'],
}),
methods: {
draw() {
if (this.mychart) {
this.mychart.destroy();
}
const ctx = this.$refs.mainChart;
this.mychart = new Chart(ctx,
{
type: 'line',
data: {
labels: this.labels,
datasets: this.datacollection
},
options: {
legend: {
display: true,
position: 'bottom',
},
responsive: true,
elements: {
},
scales: {
xAxes: [{
type: "time",
display: true,
scaleLabel: {
display: false,
},
ticks: {
major: {
fontStyle: "bold",
fontColor: "#FF0000"
}
}
}],
yAxes: [
{
id: 'y1',
type: 'linear',
position: 'left',
display: false
},
{
id: 'y2',
type: 'linear',
position: 'right',
display: false
},
{
id: 'y3',
type: 'linear',
position: 'left',
display: false
},
{
id: 'y4',
type: 'linear',
position: 'right',
display: false
},
{
id: 'y5',
type: 'linear',
position: 'left',
display: false
},
{
display: false,
gridLines: {
display: false
},
scaleLabel: {
display: true,
labelString: this.labelY
},
ticks: {
min: 0,
beginAtZero: true,
stepSize: 100
}
}]
}
}
});
},
participantsCountClub(clubId) {
switch (clubId) {
case '5c3c5e12ba86198828baa4a7':
return { label: "Тренировок на Фрунзенской", borderColor: "#3e95cd", fill: false }
case '5c3c5e20ba86198828baa4c5':
return { label: "Тренировок на Чернышевской", borderColor: "#8e5ea2", fill: false };
case '60353d6edbb58a135bf41856':
return { label: "Тренировок на Василеостровской", borderColor: "#e8c3b9", fill: false };
case '61e9995d4ec0f29dc8447f81':
return { label: "Тренировок на Московской", borderColor: "#3cba9f", fill: false };
case '61e999fc4ec0f29dc844835e':
return { label: "Тренировок на Лесной", borderColor: "#c45850", fill: false };
default:
return 'Неизвестный клуб';
}
},
async loadTrainings(clubsId) {
try {
for (let clubId in clubsId) {
clubId = clubsId[clubId]
let dateFrom = this.dateFrom
let dateTo = this.dateTo
let groupBy = 'month'
await this.$store.dispatch('loadAvgSchedule', { clubId, dateFrom, dateTo, groupBy })
this.draftData = this.$store.state.avgShedule
if (this.labels.length === 0) {
this.getDatesAvgIncome()
}
this.flagStartDate = true
await this.getParticipantsCount(clubId)
this.flagStartDate = false
}
} catch (e) {
console.error(e)
}
},
async getParticipantsCount(clubId) {
for (let item in this.draftData) {
let positionDate = this.labels.indexOf(this.draftData[item].date.slice(0, 7))
if (this.flagStartDate && positionDate > 0) {
let zerroArray = await this.bindDataDates(positionDate)
this.data = this.data.concat(zerroArray)
}
this.data.push(this.draftData[item].participantsCount)
this.flagStartDate = false
}
this.dataset.data = this.data
Object.assign(this.dataset, this.participantsCountClub(clubId))
Object.assign(this.dataset, { yAxisID: 'y5', hidden: true })
this.datacollection.push(this.dataset)
this.data = []
this.dataset = {}
},
//omitted other functions..
},
watch: {
dateFrom() {
console.log('dateFrom changed to', this.dateFrom),
console.log('this.mychart', this.mychart),
this.mychart.update()
},
dateTo() {
console.log('dateTo changed to', this.dateTo)
this.mychart.update()
}
},
async mounted() {
await this.loadIncomings(this.clubsId),
await this.loadAvgIncomings(this.clubsId),
await this.loadAvgPayments(this.clubsId),
await this.loadAvgSchedule(this.clubsId),
await this.loadTrainings(this.clubsId)
this.$nextTick(() => {
this.draw()
})
},
}
</script>
<style>
.container form {
display: flex;
}
</style>
I set dateTo and dateFrom in functions(for example loadTrainings()), before it creates request to store (in store this function create axios request to API).
let dateFrom = this.dateFrom
let dateTo = this.dateTo
let groupBy = 'month'
await this.$store.dispatch('loadAvgSchedule', { clubId, dateFrom, dateTo, groupBy })
Hello i am trying to display different charts using the chartjs by calling the API. Below code shows how i have formatted the chart.vue
Chart.vue:
<template>
<div class="chart-container" style="position: relative; height: 40vh; width:100%;">
<slot name="test1"></slot>
<slot name="test2"></slot>
</div>
</template>
<script>
export default {
name: 'charts',
data () {
return {
date: [],
challenge: [],
data: []
}
},
mounted () {
this.check(8, 'chart_8')
this.check(7, 'chart_7')
},
methods: {
check (id, name) {
this.$http.get(`/api_chart/${ id }/full`)
.then((response) => {
this.date = response.data.date
this.challenge = response.data.challenge
this.data = this.date.map((date, index) => ({
x: new Date(date * 1000),
y: this.challenge[index]
}))
const ctx = document.getElementById([name]).getContext('2d')
let myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: 'Challenge',
data: this.data,
borderColor: ' #EA5455',
}
]
},
options: {
lineTension: 0,
maintainAspectRatio: false,
scales: {
yAxes: [
{
scaleLabel: {
display: false
},
ticks: {
beginAtZero: true,
callback (value) {
return `${value}%`
}
}
}
],
xAxes: [
{
type: 'time',
time: {
unit: 'month'
},
scaleLabel: {
display: true,
}
}
]
}
}
})
})
}
}
}
</script>
App.vue:
<template>
<div class="In order to display chart1">
<chart-display> <canvas slot="test1" id="chart_7" ></canvas> </chart-display>
</div>
<div class="In order to display chart1">
<chart-display> <canvas slot="test2" id="chart_8" ></canvas> </chart-display>
</div>
</template>
<script>
import chart-display from './Chart.vue'
export default {
component: {chart-display}
}
</script>
As you can see i have shared my Chart.vue and App.vue, i am able to see my chart in the browser, but whenever i run the code or refresh the page, the charts flickers and stops. And then in my console i get below error:
Please someone help me to get rid of this issue, and please tell me if any changes i should do in my code to solve it. Please send me the modification code.
As I wrote in my comment, the charts are rendered twice. This causes flickering.
// every time you use <chart-display>, 2 charts are rendered, this means chart 1 renders
// itself and chart 2, char 2 renders itself and chart 1, this is a bad pattern in Vue in general
mounted() {
this.check(8, "chart_8");
this.check(7, "chart_7");
}
Make the following changes:
ChartDisplay.vue
<template>
<div
class="chart-container"
style="position: relative; height: 40vh; width: 100%"
>
<canvas ref="chart_7"></canvas>
<canvas ref="chart_8"></canvas>
</div>
</template>
<script>
import Chart from "chart.js";
export default {
name: "ChartDisplay",
data() {
return {
date: [],
challenge: [],
data: [],
// save charts in an array
charts: [],
// charts options
options: {
lineTension: 0,
maintainAspectRatio: false,
scales: {
yAxes: [
{
scaleLabel: {
display: false,
},
ticks: {
beginAtZero: true,
callback(value) {
return `${value}%`;
},
},
},
],
xAxes: [
{
type: "time",
time: {
unit: "month",
},
scaleLabel: {
display: true,
},
},
],
},
},
};
},
mounted() {
this.render(7, this.$refs.chart_7);
this.render(8, this.$refs.chart_8);
},
methods: {
render(id, ctx) {
this.fetchData(id).then((response) => {
let data = response.date.map((date, index) => ({
x: new Date(date * 1000),
y: response.challenge[index],
}));
this.charts.push(
new Chart(ctx, {
type: "line",
data: {
datasets: [
{
label: "Challenge",
data: data,
borderColor: " #EA5455",
},
],
},
options: this.options,
})
);
});
},
fetchData(id) {
return this.$http.get(`/api_chart/${ id }/full`);
},
},
beforeDestroy() {
this.charts.forEach((chart) => chart.destroy());
},
};
</script>
<style >
[v-cloak] {
display: none;
}
</style>
App.vue
<template>
<div>
<div class="In order to display chart1">
<chart-display/>
</div>
</div>
</template>
<script>
import ChartDisplay from "./ChartDisplay.vue";
export default {
components: { ChartDisplay },
};
</script>
See it on sandbox
I found several errors on your code. I fix them in Sandbox
For Chat.vue :
I rename the file as ChartDisplay.vue as similar as the component name
import chart.js package for using Chart() function
I use a demo API
<template>
<div
class="chart-container"
style="position: relative; height: 40vh; width: 100%"
>
<slot name="test1"></slot>
<slot name="test2"></slot>
</div>
</template>
<script>
import Chart from "chart.js";
export default {
name: "ChartDisplay",
data() {
return {
date: [],
challenge: [],
data: [],
};
},
mounted() {
this.check(8, "chart_8");
this.check(7, "chart_7");
},
methods: {
check(id, name) {
fetch(
"https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs"
)
.then((response) => response.json())
.then((response) => {
this.date = response.date;
this.challenge = response.challenge;
this.data = this.date.map((date, index) => ({
x: new Date(date * 1000),
y: this.challenge[index],
}));
const ctx = document.getElementById([name]).getContext("2d");
new Chart(ctx, {
type: "line",
data: {
datasets: [{
label: "Challenge",
data: this.data,
borderColor: " #EA5455",
}, ],
},
options: {
lineTension: 0,
maintainAspectRatio: false,
scales: {
yAxes: [{
scaleLabel: {
display: false,
},
ticks: {
beginAtZero: true,
callback(value) {
return `${value}%`;
},
},
}, ],
xAxes: [{
type: "time",
time: {
unit: "month",
},
scaleLabel: {
display: true,
},
}, ],
},
},
});
});
},
},
};
</script>
For App.vue
Your import should not carry any hyphen.
component should be components
render the component once to avoid flikering
<template>
<div>
<div class="In order to display chart1">
<chart-display>
<canvas slot="test1" id="chart_7"></canvas>
<canvas slot="test2" id="chart_8"></canvas>
</chart-display>
</div>
</div>
</template>
<script>
import ChartDisplay from "./ChartDisplay.vue";
export default {
components: {
ChartDisplay
},
};
</script>
I'm trying to use the Drilldown in Map (vue-Highchart), but cannot get it working.
like this: https://www.highcharts.com/maps/demo/map-drilldown
Anyone have any examples of this in Vue.js? Please.
Tks.
Here is simple example of drilldown functionality(with vue-highcharts) which provides drilldown and drillup event from Vue-instance:
Vue.use(VueHighcharts, { Highcharts: Highcharts });
// helper script to load external script
let loadScript = function(url, onLoad){
var scriptTag = document.createElement('script');
scriptTag.src = url;
scriptTag.onload = onLoad;
scriptTag.onreadystatechange = onLoad;
document.body.appendChild(scriptTag);
};
// simple chart options
var options = {
chart: {},
title: {
text: 'Highcharts-Vue Map Drilldown Example'
},
subtitle: {
text: '',
floating: true,
align: 'right',
y: 50,
style: {
fontSize: '16px'
}
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle'
},
colorAxis: {
min: 0,
minColor: '#E6E7E8',
maxColor: '#005645'
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
plotOptions: {
map: {
states: {
hover: {
color: '#EEDD66'
}
}
}
},
drilldown: {
activeDataLabelStyle: {
color: '#FFFFFF',
textDecoration: 'none',
textOutline: '1px #000000'
},
drillUpButton: {
relativeTo: 'plotBox',
position: {
x: 70,
y: 280
}
}
},
series: [{
data: Highcharts.geojson(Highcharts.maps['countries/us/us-all']).map((d, i) => {
d.drilldown = true;
// set value just for example
d.value = i;
return d;
}),
name: 'USA',
dataLabels: {
enabled: true,
format: '{point.properties.postal-code}'
}
}]
};
let vm = new Vue({
el: '#app',
data: {
isLoading: false,
options: options
},
created() {
// prepare events for chart from Vue instance
this.options.chart.events = {
drilldown: this.drilldown.bind(this),
drillup: this.drillup.bind(this)
}
},
methods: {
drilldown(e) {
let { chart } = this.$refs.highcharts;
if (!e.seriesOptions) {
mapKey = 'countries/us/' + e.point.properties['hc-key'] + '-all';
if (Highcharts.maps[mapKey]) {
this.prepareDrilldownData(mapKey, e.point);
return;
}
this.isLoading = true;
loadScript('https://code.highcharts.com/mapdata/' + mapKey + '.js', () => {
this.isLoading = false;
this.prepareDrilldownData(mapKey, e.point);
});
}
chart.setTitle(null, { text: e.point.name });
},
drillup(e) {
let { chart } = this.$refs.highcharts;
chart.setTitle(null, { text: '' });
},
prepareDrilldownData(mapKey, point) {
let { chart } = this.$refs.highcharts;
data = Highcharts.geojson(Highcharts.maps[mapKey]).map((d, i) => {
// set value just for example
d.value = i;
return d;
});
chart.addSeriesAsDrilldown(point, {
name: point.name,
data: data,
dataLabels: {
enabled: true,
format: '{point.name}'
}
});
}
}
});
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<script src="https://code.highcharts.com/maps/highmaps.js"></script>
<script src="https://code.highcharts.com/maps/modules/drilldown.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-highcharts/dist/vue-highcharts.min.js"></script>
<script src="https://code.highcharts.com/mapdata/countries/us/us-all.js"></script>
<div id="app">
<highmaps ref="highcharts" :options="options"></highmaps>
<div v-if="isLoading" style="text-align: center; margin-top: 15px; font-size: 20px;">Loading...</div>
</div>
There is also jsfiddle if you want.