remove Google Charts dependency from telemetry template

This commit is contained in:
e7d 2023-06-09 18:28:25 +02:00
parent 0fcb7c1afc
commit 0f5bd684c7
No known key found for this signature in database
GPG Key ID: F320BE007C0B8881
7 changed files with 92 additions and 110 deletions

View File

@ -754,22 +754,22 @@ class Gamepad {
* Loads the template script and stylesheet * Loads the template script and stylesheet
*/ */
loadTemplateAssets() { loadTemplateAssets() {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = `templates/${this.type}/template.css`;
this.$gamepad.appendChild(link);
const script = document.createElement('script'); const script = document.createElement('script');
script.async = true; script.async = true;
script.src = `templates/${this.type}/template.js`; script.src = `templates/${this.type}/template.js`;
script.onload = () => { script.onload = () => {
// initialize the template // initialize the template
this.template = new this.templateClass(); this.template = new this.TemplateClass();
// enqueue the initial display refresh // enqueue the initial display refresh
this.startTemplate(); this.startTemplate();
} }
this.$gamepad.appendChild(script); this.$gamepad.appendChild(script);
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = `templates/${this.type}/template.css`;
this.$gamepad.appendChild(link);
} }
/** /**

View File

@ -1,4 +1,4 @@
window.gamepad.templateClass = class DebugTemplate { window.gamepad.TemplateClass = class DebugTemplate {
/** /**
* Instanciates a new debug template * Instanciates a new debug template
*/ */

View File

@ -1,4 +1,4 @@
window.gamepad.templateClass = class DualShock4Template { window.gamepad.TemplateClass = class DualShock4Template {
/** /**
* Instanciates a new DualShock 4 controller template * Instanciates a new DualShock 4 controller template
*/ */

View File

@ -1,4 +1,4 @@
window.gamepad.templateClass = class DualSenseTemplate { window.gamepad.TemplateClass = class DualSenseTemplate {
/** /**
* Instanciates a new DualSense controller template * Instanciates a new DualSense controller template
*/ */

View File

@ -1,5 +1,5 @@
<div id="telemetry" class="controller"> <div id="telemetry" class="controller">
<div id="chart"></div> <canvas id="chart"></canvas>
<div id="meters"> <div id="meters">
<div id="clutch" class="meter"> <div id="clutch" class="meter">
<div class="bar"></div> <div class="bar"></div>

View File

@ -1,4 +1,4 @@
gamepad.templateClass = class TelemetryTemplate { window.gamepad.TemplateClass = class TelemetryTemplate {
/** /**
* Instanciates a new telemetry template * Instanciates a new telemetry template
*/ */
@ -7,7 +7,7 @@ gamepad.templateClass = class TelemetryTemplate {
this.gamepad = window.gamepad; this.gamepad = window.gamepad;
this.loadSelectors(); this.loadSelectors();
this.loadUrlParams(); this.loadParams();
if (!this.AXES.some((axis) => this[axis].index)) { if (!this.AXES.some((axis) => this[axis].index)) {
this.wizard(); this.wizard();
@ -71,6 +71,7 @@ gamepad.templateClass = class TelemetryTemplate {
loadSelectors() { loadSelectors() {
this.$telemetry = document.querySelector('#telemetry'); this.$telemetry = document.querySelector('#telemetry');
this.$chart = this.$telemetry.querySelector('#chart'); this.$chart = this.$telemetry.querySelector('#chart');
this.chartContext = this.$chart.getContext('2d');
this.$meters = this.$telemetry.querySelector('#meters'); this.$meters = this.$telemetry.querySelector('#meters');
this.$clutch = this.$telemetry.querySelector('#clutch'); this.$clutch = this.$telemetry.querySelector('#clutch');
this.$clutchBar = this.$clutch.querySelector('.bar'); this.$clutchBar = this.$clutch.querySelector('.bar');
@ -90,17 +91,18 @@ gamepad.templateClass = class TelemetryTemplate {
/** /**
* Loads the params from the URL * Loads the params from the URL
*/ */
loadUrlParams() { loadParams() {
this.withChart = gamepad.getUrlParam('chart') !== 'false'; this.withChart = gamepad.getUrlParam('chart') !== 'false';
this.historyLength = gamepad.getUrlParam('history') || 5000; this.chartColors = {
clutch: '#2D64B9',
brake: '#A52725',
throttle: '#0CA818',
}
this.historyLength = +(gamepad.getUrlParam('history') || 5000);
this.withMeters = gamepad.getUrlParam('meters') !== 'false'; this.withMeters = gamepad.getUrlParam('meters') !== 'false';
this.withSteering = gamepad.getUrlParam('steeringIndex') !== null; this.withSteering = gamepad.getUrlParam('steeringIndex') !== null;
this.angle = gamepad.getUrlParam('angle') || 360; this.angle = gamepad.getUrlParam('angle') || 360;
this.frequency = gamepad.getUrlParam('fps') || 60; this.frequency = gamepad.getUrlParam('fps') || 60;
this.AXES.forEach((axis) => { this.AXES.forEach((axis) => {
this[axis] = { this[axis] = {
type: (gamepad.getUrlParam(`${axis}Type`) || 'axis').replace('axis', 'axe'), type: (gamepad.getUrlParam(`${axis}Type`) || 'axis').replace('axis', 'axe'),
@ -129,95 +131,46 @@ gamepad.templateClass = class TelemetryTemplate {
} }
} }
async setupChart() {
if (!this.withChart) return;
return new Promise((resolve) => {
const script = document.createElement('script');
script.async = true;
script.src = `https://www.gstatic.com/charts/loader.js`;
script.onload = () => {
if (!google || !google.visualization) {
this.loadGoogleCharts(resolve);
return;
}
this.drawChart(resolve);
};
this.gamepad.$gamepad.appendChild(script);
});
}
/** /**
* Initializes the live chart * Set the canvas size to the actual pixel size with pixel ratio * 2
*/ */
async init() { scaleChart() {
this.interval = 1000 / this.frequency; const { width, height } = this.$chart.getBoundingClientRect();
this.length = this.historyLength / this.interval; const pixelRatio = window.devicePixelRatio;
console.log(pixelRatio);
this.setupTemplate(); this.$chart.width = width * pixelRatio * 2;
await this.setupChart(); this.$chart.height = height * pixelRatio * 2;
this.chartContext.scale(pixelRatio, pixelRatio);
this.running = true; this.$chart.style.width = `${width}px`;
this.update(); this.$chart.style.height = `${height}px`;
}
/**
* Loads the Google Charts library
*/
loadGoogleCharts(resolve) {
google.charts.load('current', { packages: ['corechart', 'line'], });
google.charts.setOnLoadCallback(this.drawChart.bind(this, resolve));
} }
/** /**
* Draws the live chart with the initial data and starts the draw update loop * Draws the live chart with the initial data and starts the draw update loop
*/ */
drawChart(resolve) { setupChart() {
if (!this.withChart) return;
this.scaleChart();
const now = Date.now(); const now = Date.now();
const initialData = [['time', 'clutch', 'brake', 'throttle']]; this.chartData = [];
for (let index = now - this.historyLength; index < now; index += this.interval) { for (let timestamp = now - this.historyLength; timestamp < now; timestamp += this.interval) {
initialData.push([index, 0, 0, 0]); this.chartData.push({ timestamp, clutch: 0, brake: 0, throttle: 0 });
} }
this.data = google.visualization.arrayToDataTable(initialData); }
this.options = {
backgroundColor: 'transparent', /**
chartArea: { * Initializes the live chart
left: 0, */
top: 0, init() {
width: '100%', this.interval = 1000 / this.frequency;
height: '100%', this.length = this.historyLength / this.interval;
backgroundColor: 'transparent',
}, this.setupTemplate();
hAxis: { this.setupChart();
textPosition: 'none',
gridlines: { this.running = true;
color: 'transparent', this.update();
},
viewWindow: {
min: now - this.historyLength,
max: now
}
},
vAxis: {
textPosition: 'none',
gridlines: {
color: 'transparent',
},
minValue: 0,
maxValue: 100,
viewWindow: {
min: 2,
max: 102,
}
},
colors: ['#2D64B9', '#A52725', '#0CA818'],
legend: 'none',
tooltip: {
trigger: 'none'
}
};
this.chart = new google.visualization.LineChart(document.querySelector('#chart'));
this.chart.draw(this.data, this.options);
resolve();
} }
/** /**
@ -228,29 +181,58 @@ gamepad.templateClass = class TelemetryTemplate {
const gamepad = this.gamepad.getActive(); const gamepad = this.gamepad.getActive();
const [clutch, brake, throttle, steering] = this.AXES.map((axis) => this.toAxisValue(gamepad, axis)); const [clutch, brake, throttle, steering] = this.AXES.map((axis) => this.toAxisValue(gamepad, axis));
if (this.withChart) this.updateChart(clutch, brake, throttle); if (this.withChart) this.drawChart(clutch, brake, throttle);
if (this.withMeters) this.updateMeters(clutch, brake, throttle); if (this.withMeters) this.updateMeters(clutch, brake, throttle);
if (this.withSteering) this.updateSteering(steering); if (this.withSteering) this.updateSteering(steering);
window.setTimeout(this.update.bind(this), this.interval); window.setTimeout(() => this.update(), this.interval);
} }
/** /**
* Updates the live chart with the latest data * Updates the data used to draw the cart
*
* @param {number} now
* @param {number} clutch
* @param {number} brake
* @param {number} throttle
*/
updateChartData(now, clutch, brake, throttle) {
let remove = 0;
for (let index = 0; index < this.chartData.length - 1; index++) {
if (this.chartData[index].timestamp < now - this.historyLength) {
remove++;
} else {
break;
}
}
this.chartData.splice(0, remove);
this.chartData.push({ timestamp: now, clutch, brake, throttle });
}
/**
* Draws the whole chart wuth the latest data
* *
* @param {number} clutch * @param {number} clutch
* @param {number} brake * @param {number} brake
* @param {number} throttle * @param {number} throttle
*/ */
updateChart(clutch, brake, throttle) { drawChart(clutch, brake, throttle) {
const now = Date.now(); const now = Date.now();
this.data.removeRows(0, this.data.getFilteredRows([{ column: 0, maxValue: now - this.historyLength }]).length); this.updateChartData(now, clutch, brake, throttle);
this.data.addRow([now, clutch, brake, throttle]);
this.options.hAxis.viewWindow = { this.chartContext.clearRect(0, 0, this.$chart.width, this.$chart.height);
min: now - this.historyLength, this.AXES.forEach((axis) => {
max: now if (axis === 'steering') return;
}; this.chartContext.beginPath();
this.chart.draw(this.data, this.options); this.chartData.forEach((entry, index) => {
const x = (entry.timestamp + this.historyLength - now) / this.historyLength * this.$chart.width;
const y = (101 - (entry[axis] || 0)) * this.$chart.height / 100;
this.chartContext[index === 0 ? 'moveTo' : 'lineTo'](x, y);
});
this.chartContext.lineWidth = 4;
this.chartContext.strokeStyle = this.chartColors[axis];
this.chartContext.stroke();
});
} }
/** /**

View File

@ -1,4 +1,4 @@
window.gamepad.templateClass = class XboxOneTemplate { window.gamepad.TemplateClass = class XboxOneTemplate {
/** /**
* Instanciates a new Xbox One controller template * Instanciates a new Xbox One controller template
*/ */