I want to add several vertical marklines to a line chart and allow users to do horizontal dragging, similar to this Highcharts example.
Setting xAxis.axisPointer
is useful in this sense. However, how can I allow the whole vertical line to be dragged on the horizontal line, rather than using the button at the botton as shown below ?
import "./styles.css";
import echarts from "echarts";
const myChart = echarts.init(document.getElementById("app"));
const option = {
xAxis: {
type: "time",
nameLocation: "center",
nameGap: 20,
interval: 420000,
min: 1625741884000,
max: 1625749084000,
axisLabel: {
rotate: 0
},
boundaryGap: ["0%", "0%"],
axisPointer: {
value: 1625742000000,
snap: true,
lineStyle: {
color: "#ff0000",
width: 4
},
handle: {
show: true,
color: "#ff0000"
}
}
},
yAxis: [
{
type: "value",
nameLocation: "center",
nameGap: 8,
interval: 0.33,
min: 1,
max: 5.33,
axisLabel: {
margin: 24,
rotate: 0
}
}
],
series: [
{
id: "test",
name: "Average Time",
yAxisIndex: 0,
data: [
{
value: [1625741884000, 1]
},
{
value: [1625741885000, 1]
},
{
value: [1625741890000, 1]
},
...
],
subSeries: [],
invert: false,
type: "line",
showSymbol: false,
symbolSize: 5,
smooth: false,
color: "#4da6e8",
lineStyle: {}
}
]
};
myChart.setOption(option);
As far as I know, there is no way of having 2 axisPointer
on the same chart. I've been looking for this feature for a while now, but I still can't find a perfect solution. A workaround using graphics
can be used to achieve something similar to what you want, but it's far from perfect. I still share it in case it's of any help to you.
var myChart = echarts.init(document.getElementById('main'));
let base = +new Date(1988, 9, 3);
let oneDay = 24 * 3600 * 1000;
let data = [[base, Math.random() * 300]];
for (let i = 1; i < 20000; i++) {
let now = new Date((base += oneDay));
data.push([+now, Math.round((Math.random() - 0.5) * 20 + data[i - 1][1])]);
}
option = {
grid: {
top: '40px',
bottom: '60px',
left: '50px',
right: '30px'
},
xAxis: {
type: 'time',
boundaryGap: false,
axisLine: {onZero: false},
axisPointer:
{
show: true,
type: 'line',
},
},
yAxis: {
type: 'value',
boundaryGap: [0, '100%']
},
series: [
{
name: 'Fake Data',
type: 'line',
smooth: true,
symbol: 'none',
areaStyle: {},
data: data
}
],
graphic: {
elements: [
{
type: 'group',
left: 'center',
draggable: 'horizontal',
ondrag: function (params) {
var pointInPixel = [params.offsetX, params.offsetY];
var pointInGrid = myChart.convertFromPixel('grid', pointInPixel);
var xTime = new Date(pointInGrid[0])
//get closest value from cursor
var point = data.reduce((prev, curr) => Math.abs(new Date(curr[0]).valueOf() - xTime.valueOf()) < Math.abs(new Date(prev[0]).valueOf() - xTime.valueOf()) ? curr : prev)
//console.log('poi', new Date(pointInGrid[0]), new Date(point[0]), point[1])
var d = document.getElementById('value2');
d.style.left = params.offsetX+'px';
d.innerHTML = point[1]
},
children: [
{
id: 'bar1',
type: 'rect',
top: '30px',
shape: {
width: 2,
height: 685
},
style: {
fill: "#ff0000"
},
cursor: 'ew-resize'
},
{
type: 'circle',
top: '740px',
shape: {
r:10
},
style: {
fill: "#ff0000"
},
}
]
},
{
type: 'group',
left: '150px',
draggable: 'horizontal',
ondrag: function (params) {
var pointInPixel = [params.offsetX, params.offsetY];
var pointInGrid = myChart.convertFromPixel('grid', pointInPixel);
var xTime = new Date(pointInGrid[0])
//get closest value from cursor
var point = data.reduce((prev, curr) => Math.abs(new Date(curr[0]).valueOf() - xTime.valueOf()) < Math.abs(new Date(prev[0]).valueOf() - xTime.valueOf()) ? curr : prev)
//console.log('poi', new Date(pointInGrid[0]), new Date(point[0]), point[1])
var d = document.getElementById('value1');
d.style.left = params.offsetX+'px';
d.innerHTML = point[1]
},
children: [
{
type: 'rect',
top: '30px',
shape: {
width: 2,
height: 685
},
style: {
fill: "#0000ff"
},
cursor: 'ew-resize'
},
]
},
]}
};
myChart .setOption(option)
<html>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.3.2/echarts.min.js"></script>
<div id="main" style="width: 1200px; height:775px;"></div>
<div id="value1" style="background-color: blue; color: white; position: absolute; top: 280px; left: 185px">0</div>
<div id="value2" style="background-color: red; position: absolute; top: 280px; left: 605px">0</div>
</body>
</html>
The graphic.elements.ondrag
function is quite interesting as it allows to get the value of the series along the cursor. Here on the example, the value is displayed in a div that is above the 'cursor', but it can be displayed in a prettier way somewhere else.