maher-tradingview-api
Version:
Tradingview instant stocks API, indicator alerts, trading bot, and more !
182 lines (163 loc) • 6.17 kB
JavaScript
// Enhanced Chart Renderer with better performance and features
class EnhancedChartRenderer {
constructor(options = {}) {
this.options = {
animations: true,
responsiveAnimationDuration: 500,
tooltips: true,
crosshair: true,
zoom: true,
...options
};
this.charts = new Map();
}
renderPriceChart(canvasId, labels, values, symbol, additionalOptions = {}) {
const ctx = document.getElementById(canvasId)?.getContext('2d');
if (!ctx) return null;
const gradientFill = ctx.createLinearGradient(0, 0, 0, ctx.canvas.height);
gradientFill.addColorStop(0, 'rgba(0, 136, 204, 0.3)');
gradientFill.addColorStop(1, 'rgba(0, 136, 204, 0.05)');
const chartOptions = {
type: 'line',
data: {
labels: labels,
datasets: [{
label: symbol,
data: values,
borderColor: '#0088cc',
backgroundColor: gradientFill,
borderWidth: 2,
fill: true,
pointRadius: 0,
pointHoverRadius: 4,
pointHoverBackgroundColor: '#0088cc',
pointHoverBorderColor: '#fff'
}]
},
options: {
animation: {
duration: this.options.animations ? this.options.responsiveAnimationDuration : 0
},
responsive: true,
maintainAspectRatio: false,
interaction: {
intersect: false,
mode: 'index'
},
plugins: {
legend: {
display: true,
position: 'top',
rtl: true,
labels: {
font: {
family: 'Arial'
}
}
},
tooltip: {
enabled: this.options.tooltips,
rtl: true,
mode: 'index',
intersect: false,
callbacks: {
label: (context) => {
return `${context.dataset.label}: ${context.parsed.y.toFixed(2)}`;
}
}
},
crosshair: {
enabled: this.options.crosshair,
line: {
color: '#666',
width: 1,
dashPattern: [5, 5]
}
},
zoom: {
enabled: this.options.zoom,
mode: 'x',
sensitivity: 3,
speed: 0.1
}
},
scales: {
x: {
grid: {
display: false
},
ticks: {
maxRotation: 0,
autoSkip: true,
maxTicksLimit: 10
}
},
y: {
position: 'right',
grid: {
color: 'rgba(0, 0, 0, 0.05)'
},
ticks: {
callback: (value) => value.toFixed(2)
}
}
}
}
};
const finalOptions = this.mergeChartOptions(chartOptions, additionalOptions);
const chart = new Chart(ctx, finalOptions);
this.charts.set(canvasId, chart);
return chart;
}
mergeChartOptions(baseOptions, additionalOptions) {
return this.deepMerge(baseOptions, additionalOptions);
}
deepMerge(target, source) {
const isObject = (obj) => obj && typeof obj === 'object';
if (!isObject(target) || !isObject(source)) {
return source;
}
Object.keys(source).forEach(key => {
const targetValue = target[key];
const sourceValue = source[key];
if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
target[key] = targetValue.concat(sourceValue);
}
else if (isObject(targetValue) && isObject(sourceValue)) {
target[key] = this.deepMerge(Object.assign({}, targetValue), sourceValue);
}
else {
target[key] = sourceValue;
}
});
return target;
}
updateChart(canvasId, newData, newLabels) {
const chart = this.charts.get(canvasId);
if (!chart) return;
chart.data.labels = newLabels;
chart.data.datasets[0].data = newData;
chart.update('none'); // Using 'none' for better performance
}
destroyChart(canvasId) {
const chart = this.charts.get(canvasId);
if (chart) {
chart.destroy();
this.charts.delete(canvasId);
}
}
addIndicator(canvasId, indicator) {
const chart = this.charts.get(canvasId);
if (!chart) return;
chart.data.datasets.push(indicator);
chart.update();
}
removeIndicator(canvasId, indicatorId) {
const chart = this.charts.get(canvasId);
if (!chart) return;
chart.data.datasets = chart.data.datasets.filter(dataset => dataset.id !== indicatorId);
chart.update();
}
}
// Export the enhanced renderer
window.EnhancedChartRenderer = new EnhancedChartRenderer();