Add shortcode for D3.js JavaScript charting tool #81
Replies: 5 comments 7 replies
-
|
It may be a good idea, but I don't have the time to implement it. I'll keep this discussion open and see how many users want to see it happen. Btw, there is a charting module called ECharts. |
Beta Was this translation helpful? Give feedback.
-
|
Thanks for pointing to https://echarts.hugomods.com/ It worked beautifully: https://acetheseriesexams.com/s7/5/2/1/2/ Unfortunately, in local dev I always need to restart the server, even with caching disabled; otherwise markdown is reloaded instantly but chart remains the same; if I make any change in chart I need to restart Hugo. But it works fine at Netlify; I don't need to clear browser cache. Maybe better to have EChart settings loaded from external file instead of embedded as |
Beta Was this translation helpful? Give feedback.
-
|
This is one real-life example where D3.js outperforms ECharts: Renko Chart. https://observablehq.com/@fil/renko-chart With ECharts I can simulate "bricks" using // Function to generate dates for the past few months
function generateDates(startDate, numDays) {
const dates = [];
const currentDate = new Date(startDate);
for (let i = 0; i < numDays; i++) {
const year = currentDate.getFullYear();
const month = String(currentDate.getMonth() + 1).padStart(2, '0');
const day = String(currentDate.getDate()).padStart(2, '0');
dates.push(`${year}-${month}-${day}`);
currentDate.setDate(currentDate.getDate() + 1);
}
return dates;
}
// Function to generate random integer between min and max (inclusive)
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Function to generate raw data with up and down movements
function generateRawData(dates) {
const rawData = [];
let currentPrice = 100; // Starting price
dates.forEach(date => {
// Randomly decide to go up or down
const direction = Math.random() > 0.5 ? 1 : -1;
// Random step size between 1 and 3
const step = getRandomInt(1, 3);
currentPrice += direction * step;
// Ensure price doesn't go below a certain threshold
if (currentPrice < 50) currentPrice = 50;
rawData.push({ date: date, close: currentPrice });
});
return rawData;
}
// Generate Dates and Raw Data
const numDays = 90; // Approximately 3 months
const startDate = '2023-01-01';
const datesArray = generateDates(startDate, numDays);
const rawData = generateRawData(datesArray);
const brickSize = 2; // Brick size set to 2 points
// Function to Generate Renko Bricks
function generateRenkoBricks(data, brickSize) {
const bricks = [];
if (data.length === 0) return bricks;
let lastBrickClose = data[0].close;
bricks.push({
date: data[0].date,
open: lastBrickClose,
close: lastBrickClose,
high: lastBrickClose,
low: lastBrickClose,
direction: 'neutral'
});
for (let i = 1; i < data.length; i++) {
const price = data[i].close;
let movement = price - lastBrickClose;
while (Math.abs(movement) >= brickSize) {
if (movement > 0) {
// Up Brick
bricks.push({
date: data[i].date,
open: lastBrickClose,
close: lastBrickClose + brickSize,
high: lastBrickClose + brickSize,
low: lastBrickClose,
direction: 'up'
});
lastBrickClose += brickSize;
movement -= brickSize;
} else {
// Down Brick
bricks.push({
date: data[i].date,
open: lastBrickClose,
close: lastBrickClose - brickSize,
high: lastBrickClose,
low: lastBrickClose - brickSize,
direction: 'down'
});
lastBrickClose -= brickSize;
movement += brickSize;
}
}
// Ignore movements less than brickSize
}
return bricks;
}
// Generate Renko Bricks
const renkoData = generateRenkoBricks(rawData, brickSize);
// Prepare Data for ECharts Candlestick
const renkoDates = renkoData.map(item => item.date);
const candlestickData = renkoData.map(item => [item.open, item.close, item.high, item.low]);
// ECharts Option Configuration with Improvements
const option = {
title: {
text: 'Renko Chart with 2-Point Brick Size',
left: 'center',
textStyle: {
fontSize: 18,
fontWeight: 'bold'
}
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
formatter: function (params) {
const data = params[0].data;
return `
<strong>Date:</strong> ${params[0].name}<br/>
<strong>Open:</strong> ${data[0]}<br/>
<strong>Close:</strong> ${data[1]}<br/>
<strong>High:</strong> ${data[2]}<br/>
<strong>Low:</strong> ${data[3]}
`;
}
},
legend: {
data: ['Renko'],
top: '10%',
left: 'center'
},
grid: {
left: '10%',
right: '10%',
bottom: '15%',
containLabel: true
},
dataZoom: [
{
type: 'inside',
start: 0,
end: 100
},
{
show: true,
type: 'slider',
bottom: '5%',
start: 0,
end: 100
}
],
xAxis: {
type: 'category',
data: renkoDates,
boundaryGap: true,
axisLine: { onZero: false },
splitLine: { show: false },
axisTick: { alignWithLabel: true },
axisLabel: {
rotate: 45,
formatter: function (value) {
const dateParts = value.split('-');
return `${dateParts[1]}-${dateParts[2]}`;
}
}
},
yAxis: {
type: 'value',
scale: true,
splitArea: {
show: true
},
axisLabel: {
formatter: '{value}'
}
},
series: [
{
name: 'Renko',
type: 'candlestick',
data: candlestickData,
large: true,
itemStyle: {
color: '#0CF49B', // Up color
color0: '#FD1050', // Down color
borderColor: '#0CF49B',
borderColor0: '#FD1050'
},
markLine: {
symbol: 'none',
data: [
{
yAxis: renkoData[renkoData.length - 1].close,
label: {
formatter: 'Last Close',
position: 'end'
},
lineStyle: {
type: 'dashed',
color: '#FF8C00'
}
}
]
}
}
]
};
return option; |
Beta Was this translation helpful? Give feedback.
-
|
As you mentioned, let's keep discussion open. This collection looks amazing: https://observablehq.com/@fil?page=2 My current solution is this:
In And It works. For comparison, ECharts consists from 45 items (files and folders); sophistication is needed, for example, to integrate with "light" and "dark" Hugo themes, layouts, putting JS at bottom of page, and etc.; but... 45 items. Not so easy. If I can find a better solution, I'll contribute. |
Beta Was this translation helpful? Give feedback.
-
|
This is basic shortcode for JavaScript snippets: And this is example of use, And of course need to import this: Complete example: |
Beta Was this translation helpful? Give feedback.


Uh oh!
There was an error while loading. Please reload this page.
-
I think it is easy; I tried it works but my code is naive; Mermaid can't do it:
https://observablehq.com/@d3/gallery?utm_source=d3js-org&utm_medium=hero&utm_campaign=try-observable
Beta Was this translation helpful? Give feedback.
All reactions