Discover: SidebarFilter Timeframes div & slider done.
This commit is contained in:
@@ -6,9 +6,17 @@
|
||||
<span class="material-symbols-outlined mr-2 text-base">info</span>
|
||||
<p>Select or fill in a time range.</p>
|
||||
</div>
|
||||
<Chart type="line" :data="chartData" :options="chartOptions" class="h-3/5" />
|
||||
<!-- <Chart type="line" :data="chartData" :options="chartOptions" class="h-3/5" ref="TimeChart" /> -->
|
||||
<div class="chartContainer">
|
||||
<!-- <Chart type="line" :data="chartData" :options="chartOptions" class="h-3/5" ref="TimeChart" /> -->
|
||||
<canvas id="chartCanvasId"></canvas>
|
||||
<div id="chart-mask-left"></div>
|
||||
<div id="chart-mask-right"></div>
|
||||
</div>
|
||||
|
||||
<div class="px-2">
|
||||
<Slider v-model="selectArea" :step="1" :min="1" :max="timeFrameTotal" range class="mx-2" id="canvas"/>
|
||||
<!-- <Slider v-model="selectArea" :step="1" :min="1" :max="timeFrameTotal" range class="mx-2"/> -->
|
||||
<Slider v-model="selectArea" :step="1" :min="0" :max="100" range class="mx-2" @change="changeSelectArea($event)"/>
|
||||
<br/>
|
||||
{{ selectArea }}<br/>
|
||||
total: {{ timeFrameData.length }}<br/>
|
||||
@@ -20,7 +28,6 @@
|
||||
</div>
|
||||
<!-- <Calendar v-model="date" @date-select.stop="eee($event)" /> -->
|
||||
</div>
|
||||
<canvas id="myChart"></canvas>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
@@ -28,7 +35,10 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import AllMapDataStore from '@/stores/allMapData.js';
|
||||
import getMoment from 'moment';
|
||||
import Chart from 'chart.js/auto'
|
||||
import { timeRange, yTimeRange } from '@/module/timeframes.js';
|
||||
import { Chart, registerables } from 'chart.js';
|
||||
import 'chartjs-adapter-date-fns';
|
||||
import "chart.js/auto";
|
||||
|
||||
export default{
|
||||
setup() {
|
||||
@@ -42,13 +52,15 @@ export default{
|
||||
// timeFrameData: [],
|
||||
chartOptions: null,
|
||||
selectArea: [1, 10],
|
||||
date: null
|
||||
date: null,
|
||||
chart: null,
|
||||
canvasId: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// Set Slider Time Range,滑塊範圍: 最小值 + data(10 個) + 最大值
|
||||
timeFrameData: function(){
|
||||
let data = [...this.filterTimeframe.data];
|
||||
let data = this.filterTimeframe.data.map(i=>({x:i.x,y:i.y}))
|
||||
// y 軸斜率計算請參考 ./public/timeFrameSlope 的圖
|
||||
// x 值為 0 ~ 11,
|
||||
// 將三的座標(ax, ay), (bx, by), (cx, cy)命名為 (a, b), (c, d), (e, f)
|
||||
@@ -85,7 +97,12 @@ export default{
|
||||
y: mf,
|
||||
})
|
||||
|
||||
let xVal = timeRange(data[0].x, data[data.length-1].x, 100);
|
||||
let yVal = yTimeRange(data, 100); // y 還沒做切分份數
|
||||
let timeData = xVal.map((x, index) => ({ x, y: yVal[index] }));
|
||||
|
||||
return data;
|
||||
// return timeData;
|
||||
},
|
||||
timeFrameTotal: function() {
|
||||
return this.timeFrameData.length;
|
||||
@@ -94,9 +111,12 @@ export default{
|
||||
// !!畫面顯示的時間,資料轉換,在這邊最後一個步驟做就好!!
|
||||
let labels = this.timeFrameData.map(time => getMoment(time.x).format("YYYY-MM-DD"));
|
||||
let chartData = this.timeFrameData.map(item => {
|
||||
return item.y
|
||||
// x: getMoment(item.x).format("YYYY-MM-DD"),
|
||||
})
|
||||
// return item.y
|
||||
return {
|
||||
x: getMoment(item.x).format("YYYY-MM-DD"),
|
||||
y: item.y,
|
||||
}
|
||||
})
|
||||
|
||||
const start = this.selectArea[0]-1;
|
||||
const end = this.selectArea[1]-1;
|
||||
@@ -105,11 +125,12 @@ export default{
|
||||
|
||||
return {
|
||||
// 要呈現的資料
|
||||
labels,
|
||||
// labels:'Data',
|
||||
datasets: [
|
||||
{
|
||||
label: 'Case', // 資料的標題標籤
|
||||
data: chartData,
|
||||
// data: chartData,
|
||||
data: this.timeFrameData,
|
||||
fill: true,
|
||||
showLine: false,
|
||||
tension: 0.4,
|
||||
@@ -118,24 +139,111 @@ export default{
|
||||
spanGaps: true,
|
||||
segment: {
|
||||
backgroundColor: ctx => inside(ctx, 'rgb(0,153,255)') || outside(ctx, 'rgb(203, 213, 225)'),
|
||||
// backgroundColor: ctx => inside(ctx, 'rgb(245,40,145)') || outside(ctx, 'rgb(250, 196, 224)'),
|
||||
},
|
||||
x: 'x',
|
||||
y: 'y',
|
||||
},
|
||||
]
|
||||
};
|
||||
},
|
||||
options: function() {
|
||||
const max = this.filterTimeframe.y_axis.max * 1.1;
|
||||
return {
|
||||
onResize: (chart, size) => {
|
||||
this.resizeMask(chart, 0.38, 0.72);
|
||||
},
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
layout: {
|
||||
padding: {
|
||||
top: 16,
|
||||
left: 8,
|
||||
right: 8,
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: false, // 圖例
|
||||
filler: {
|
||||
propagate: false
|
||||
},
|
||||
},
|
||||
animations: false, // 取消動畫
|
||||
interaction: {
|
||||
intersect: false,
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
ticks: {
|
||||
color: '#0f172a',
|
||||
display: true,
|
||||
},
|
||||
grid: {
|
||||
display: false, // 隱藏 x 軸網格
|
||||
},
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true, // scale 包含 0
|
||||
max: max,
|
||||
ticks: { // 設定間隔數值
|
||||
display: false, // 隱藏數值,只顯示格線
|
||||
stepSize: max / 4,
|
||||
},
|
||||
grid: {
|
||||
color: 'rgba(100,116,139)',
|
||||
z: 1,
|
||||
},
|
||||
border: {
|
||||
display: false, // 隱藏左側多出來的線
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
config: function() {
|
||||
const data = {
|
||||
datasets: [
|
||||
{
|
||||
label: 'Case',
|
||||
data: this.timeFrameData,
|
||||
fill: 'start',
|
||||
showLine: false,
|
||||
tension: 0.4,
|
||||
backgroundColor: 'rgba(0,153,255)',
|
||||
pointRadius: 0,
|
||||
x: 'x',
|
||||
y: 'y',
|
||||
}
|
||||
]
|
||||
};
|
||||
return {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: this.options,
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
eee(e){
|
||||
console.log(e);
|
||||
},
|
||||
/**
|
||||
* Set bar chart Options
|
||||
*/
|
||||
setChartOptions() {
|
||||
// 找出 y 軸最大值,乘以 1.1 讓圖的上方多一點空間
|
||||
const max = this.filterTimeframe.y_axis.max * 1.1;
|
||||
// 給取並取得 chart canvas 的 ID
|
||||
// this.$nextTick(() => {
|
||||
// const canvasId = this.$refs.TimeChart.$el;
|
||||
// const chartCanvasId = canvasId.querySelector('canvas');
|
||||
// chartCanvasId.setAttribute('id', 'chartCanvas');
|
||||
// });
|
||||
// console.log(chartCanvasId);
|
||||
// 找出 y 軸最大值,乘以 1.1 讓圖的上方多一點空間
|
||||
const max = this.filterTimeframe.y_axis.max * 1.1;
|
||||
|
||||
return { // 自訂屬性設定
|
||||
const config = { // 自訂屬性設定
|
||||
// onResize: (chart, size) => {
|
||||
// this.resizeMask(chart, 0.38, 0.72);
|
||||
// },
|
||||
// responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
aspectRatio: 0.6,
|
||||
layout: {
|
||||
@@ -148,14 +256,19 @@ export default{
|
||||
plugins: {
|
||||
legend: false, // 圖例
|
||||
filler: {
|
||||
propagate: false
|
||||
}
|
||||
propagate: false
|
||||
},
|
||||
},
|
||||
animations: false, // 取消動畫
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
time: {
|
||||
tooltipFormat: 'DD T',
|
||||
},
|
||||
ticks: {
|
||||
color: '#0f172a',
|
||||
display: true,
|
||||
},
|
||||
grid: {
|
||||
display: false, // 隱藏 x 軸網格
|
||||
@@ -178,13 +291,154 @@ export default{
|
||||
},
|
||||
},
|
||||
};
|
||||
// const myChart = new Chart(chartCanvasId, config);
|
||||
// this.resizeMask(myChart, 0.38, 0.72);
|
||||
// myChart.destroy()
|
||||
|
||||
return config
|
||||
},
|
||||
resizeMask(chart, from, to) {
|
||||
console.log('resizeMask');
|
||||
if (chart.chartArea === undefined) return;
|
||||
this.resizeLeftMask(chart, from);
|
||||
this.resizeRightMask(chart, to);
|
||||
},
|
||||
resizeLeftMask(chart, from) {
|
||||
console.log('resizeLeftMask');
|
||||
const canvas = document.getElementById("chartCanvasId");
|
||||
const mask = document.getElementById("chart-mask-left");
|
||||
console.log(canvas);
|
||||
mask.style.left = `${canvas.offsetLeft + chart.chartArea.left}px`;
|
||||
mask.style.width = `${chart.chartArea.width * from}px`;
|
||||
mask.style.top = `${canvas.offsetTop + chart.chartArea.top}px`;
|
||||
mask.style.height = `${chart.chartArea.height}px`;
|
||||
},
|
||||
resizeRightMask(chart, to) {
|
||||
console.log('resizeRightMask');
|
||||
const canvas = document.getElementById("chartCanvasId");
|
||||
const mask = document.getElementById("chart-mask-right");
|
||||
mask.style.left = `${canvas.offsetLeft + chart.chartArea.left + chart.chartArea.width * to}px`;
|
||||
mask.style.width = `${chart.chartArea.width * (1 - to)}px`;
|
||||
mask.style.top = `${canvas.offsetTop + chart.chartArea.top}px`;
|
||||
mask.style.height = `${chart.chartArea.height}px`;
|
||||
},
|
||||
createChart(start, end) {
|
||||
const max = this.filterTimeframe.y_axis.max * 1.1;
|
||||
|
||||
const data = {
|
||||
datasets: [
|
||||
{
|
||||
label: 'Case',
|
||||
data: this.timeFrameData,
|
||||
fill: 'start',
|
||||
showLine: false,
|
||||
tension: 0.4,
|
||||
backgroundColor: 'rgba(0,153,255)',
|
||||
pointRadius: 0,
|
||||
x: 'x',
|
||||
y: 'y',
|
||||
}
|
||||
]
|
||||
};
|
||||
const options = {
|
||||
onResize: (chart, size) => {
|
||||
this.resizeMask(chart, start, end);
|
||||
},
|
||||
responsive: true,
|
||||
maintainAspectRatio: false,
|
||||
layout: {
|
||||
padding: {
|
||||
top: 16,
|
||||
left: 8,
|
||||
right: 8,
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: false, // 圖例
|
||||
filler: {
|
||||
propagate: false
|
||||
},
|
||||
},
|
||||
animations: false, // 取消動畫
|
||||
interaction: {
|
||||
intersect: false,
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
ticks: {
|
||||
color: '#0f172a',
|
||||
display: true,
|
||||
},
|
||||
grid: {
|
||||
display: false, // 隱藏 x 軸網格
|
||||
},
|
||||
},
|
||||
y: {
|
||||
beginAtZero: true, // scale 包含 0
|
||||
max: max,
|
||||
ticks: { // 設定間隔數值
|
||||
display: false, // 隱藏數值,只顯示格線
|
||||
stepSize: max / 4,
|
||||
},
|
||||
grid: {
|
||||
color: 'rgba(100,116,139)',
|
||||
z: 1,
|
||||
},
|
||||
border: {
|
||||
display: false, // 隱藏左側多出來的線
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
const config = {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: options,
|
||||
};
|
||||
this.canvasId = document.getElementById("chartCanvasId");
|
||||
this.chart = new Chart(this.canvasId, config);
|
||||
this.resizeMask(this.chart, start, end);
|
||||
},
|
||||
/**
|
||||
* 滑塊改變的時候
|
||||
* @param {array} e [1, 100]
|
||||
*/
|
||||
changeSelectArea(e) {
|
||||
// const canvas = document.getElementById("chartCanvasId");
|
||||
// window.chartCanvasId.destroy();
|
||||
// const chart = new Chart(canvas, this.config);
|
||||
// const chart = new Chart(this.canvasId, this.config);
|
||||
|
||||
// this.resizeMask(this.chart, e[0]/10, e[1]/10);
|
||||
this.chart.destroy()
|
||||
this.createChart(e[0]*0.01, e[1]*0.01)
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.chartOptions = this.setChartOptions();
|
||||
this.selectArea = [1, this.timeFrameTotal];
|
||||
Chart.register(...registerables);
|
||||
this.createChart(0.38, 0.72);
|
||||
// this.chartOptions = this.setChartOptions();
|
||||
// this.selectArea = [1, this.timeFrameTotal];
|
||||
this.selectArea = [38, 72]
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.chart-container {
|
||||
position: relative;
|
||||
margin: 2rem 4rem;
|
||||
padding: 20px 40px;
|
||||
border: 1px solid black;
|
||||
width: 60%;
|
||||
height: 60%;
|
||||
}
|
||||
#chartCanvas {
|
||||
border: 1px solid red !important;
|
||||
}
|
||||
#chart-mask-left, #chart-mask-right {
|
||||
position: absolute;
|
||||
background-color: rgb(255, 255, 255, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user