In order to make my own markPoint div (since I cannot get Echarts markPoints to show up), I need to get the x,y pixel coordinates of a visual point on a stacked line chart where one series hits a 0 value. But because it is stacked, that 0 point isn't at the bottom of the chart, but somewhere higher sitting on top of other series lower in the stacking order. the echartsInstance.convertToPixel function is responding back with the y pixel coordinate at the bottom of the chart, where absolute 0 would be, but that's not where the series is. It's higher up, even with a 0 value, due to stacking.
Is there anyway, maybe through getModel() or getZr() to find out what the pixel coordinates are for a series (where it actually appears visually after stacking) at a given set of its own x,y values?
OK, let's imagine that you have a bar chart and you want to place the markPoint on the top of second bar, drawing the chart:
var myChart = echarts.init(document.getElementById('main'));
var option = {
xAxis: {
data: ["A", "B", "C"]
},
yAxis: {},
series: [{
name: 'Series1',
type: 'bar',
data: [5, 20, 36],
}]
}
myChart.setOption(option);
Then you should define the markPoint in series config:
// ...
markPoint: {
symbol: 'circle',
symbolSize: 10,
itemStyle: { color: 'black' },
data:[{
// here you defined: x = 'B' and y = '20'
coord: ['B', 20]
}]
}
// ...
Here you can find the full example.
Next. You want to place the div point with pixel coordinates depending on the size of bar. Here you convert the pixel coordinates into Echarts scale:
var [chartX, chartY] = myChart.convertToPixel({ seriesIndex: 0 }, [x, y]);
You need function to draw point on page:
function Point(opts){
var { x,y } = opts;
var canvas = document.getElementById('main');
var point = document.createElement('div');
point.classList.add('point');
var [chartX, chartY] = myChart.convertToPixel({ seriesIndex: 0 }, [x, y]);
point.style.left = chartX + 'px';
point.style.top = chartY + 'px';
return canvas.insertAdjacentElement('afterbegin', point);
}
and then call it:
var p1 = new Point({ x: 'B', y: 20 });
It's all. See full example.
Related
I have a simple echart here with a simple horizontal line defined by the yAxis . My question is is there anyway I can confined the length of the line to a point on the xAxis? I want the line to end at '2017-10-18' instead of the end of the graph or '2017-10-20'
I tried specifying both x and y axis at the same time, but doesn't seem to be working. Any help will be appreciated.
You have 2 options :
Markline
series-line.markLine doc
This is what you used in your example, but replace markline data with that :
markLine: {
data: [[
{
coord: [0, 0.901],
},
{
coord: [4, 0.901]
}
]]
}
data is a list of marklines. To declare a line with specific [[x1, y1], [x2,y2]], you'll have to define a list of points within the list of marklines (that's why there are two brackets in a row).
Graphics
graphic.elements-line doc
Otherwise graphics gives more freedom to draw anything on the graph.
graphic: {
elements: [
{
type: 'group',
left: 'center',
top: 'center',
children: [
{
type: 'line',
x: 20,
shape: {
x1: -250,
y1: -100,
x2: 10,
y2: 40,
},
}
]
}
]
}
But x1,y1,x2 and y2 coordinates are in pixel. If you want it to use the series coordinates, you can use convertToPixel()
myChart.convertToPixel({seriesIndex: 0}, [0,0.901])
Result
In red : markline and in black : graphics
Code
Is there anyway to get leaflet to display values smaller than a meter? For instance, mm (millimeter), or um (micrometer) on the scale control?
Or if there is a plugin that does this?
I have a custom map with a custom CRS that uses virtual microscopy images.
I use the following code to create a map with values less than a meter however the scale control is really wide and doesn't go below a meter:
L.CRS.Meters = L.extend(L.CRS, {
projection: L.extend( L.Projection.LonLat, {
bounds: L.bounds([0, 0], [2160, 4096])
}),
transformation: new L.Transformation(1, 0, -1, 0),
scale: function (zoom) {
return Math.pow(2, zoom);
},
infinite: false
});
var customCRS = L.extend(L.CRS.Simple, {
projection: L.extend( L.Projection.LonLat, {
bounds: L.bounds([0, 0], [2160, 4096])
}),
transformation: new L.Transformation(1, 0, 1, 0),
scale: function (zoom) {
return Math.pow(2, zoom +7);
},
infinite: false
});
var map = L.map('vm', { zoomSnap: 0.2, crs: customCRS}).setView([3, 3], 3);
The specific piece of code that handles the rounding of the scale bar measurement and the (metric) units is the _updateMetric method:
_updateMetric: function (maxMeters) {
var meters = this._getRoundNum(maxMeters),
label = meters < 1000 ? meters + ' m' : (meters / 1000) + ' km';
this._updateScale(this._mScale, label, meters / maxMeters);
},
Note that the implementation of this._getRoundNum() will return an integer number, i.e. 1 minimum.
You might want to replace the implementation of _updateMetric(), to round up a factor of that number, and apply unit suffixes accordingly, e.g.:
L.Control.Scale.include({
_updateMetric: function(maxMeters) {
var maxMilliMeters = maxMeters * 1000,
milliMeters = this._getRoundNum(maxMilliMeters),
label = milliMeters < 1000 ? milliMeters + " mm" : milliMeters / 1000 + " m";
console.log(this._mScale, label, milliMeters / maxMilliMeters);
this._updateScale(this._mScale, label, milliMeters / maxMilliMeters);
}
});
See a working example here.
I have a ECharts line chart where, based on some condition, the series can or can't have the markline. The problem is that, if the actual maximum yaxis value is less then a markline y value, not all the markline will be shown.
I tried to set manually the min/max of my yaxis but nothing changes.
This is how the axis conditions are defined in the option:
axis:[
{
scale: true
}],
xAxis: [{
type: "time"
}],
yAxis: [{
type: "value",
axisLabel: {
formatter: "{value} ° C"
},
scale: true
}]
and this is how I set the min/max yaxis values:
termoLineCharts[index].yAxis.min = minYvalue - 15;
termoLineCharts[index].yAxis.max = maxYValue + 15;
This is the solution: the yaxis option is an array, so in order to set the min and max value I had to do this
optionLineCharts[index].yAxis[0].min = minYvalue;
optionLineCharts[index].yAxis[0].max = maxYValue;
Im trying to adjust the X axis label for Radar chart in highchart and I couldnt fix the 2 labels. when its on small width screen,some labels are not seen completely. attached the screenshot
img
Here is the fiddle link:
https://jsfiddle.net/xs9zb3f6/6/enter code here
can someone help please? I want either the labels to be aligned further inside radar chart or word wrap so that when its on small screen it does not cut the word.
You can write your own function to move labels.
Get bbox of the label element and check if it is inside the container (>= 0 or <= container's width). One caveat in getting bbox - the labels are rotated, so it means that the bbox you get has params of the element which is not rotated yet - in your case when the rotation does not change text width a lot - you can add some pixels to offset that difference.
function moveLabels() {
const ticks = this.xAxis[0].ticks;
const safeDistance = 10;
Object.keys(ticks).forEach(value => {
const label = ticks[value].label;
const bbox = label.getBBox(true);
if (bbox.y >= 0) {
if (bbox.x - safeDistance < 0) {
label.attr({
x: label.xy.x + Math.abs(bbox.x - safeDistance)
})
} else if (bbox.x + bbox.width + safeDistance > this.chartWidth) {
label.attr({
x: label.xy.x - (bbox.x + bbox.width + safeDistance - this.chartWidth)
});
}
}
})
}
Move labels on load/redraw events:
chart: {
polar: true,
type: 'line',
events: {
load: moveLabels,
redraw: moveLabels
}
},
example: https://jsfiddle.net/nd5fob5d/
I have some info which is in this format (speed, frequency, date). What happens is that I need to plot this chart with speed x frequency, but I want to allow the users to use the navigation filtering by the date, which is not appearing on the chart.
Also, I have some info which is not built dynamically, which is the limits of speed x frequency. This info will be fixed as reference points on the plot. So, when I filter the plot info (not the limits), it must always display these limit plots.
You can have an idea by this chart, the area plots show the limits for the points (speed, frequency). Then, I would add points of speed x frequency (x date), and filter then by date.
Can you guys give me some advice on this?
here is a JSFIDDLE
JSFIDDLE
data: [
[0, 20, here is a date], [10, 20,here is a date],
[50, 39.9994, here is a date], [100,49.7494, here is a date]
],
Guys, notice that every element of the array in the series has 3 elements [a, b, c], suppose the third one (c) is a DATE and not a random number as it is right now. I want to be able to use the commented the navigator code to filter this series by this C element, which doesn't in fact appear on the chart you see, it is a hidden element, just to filter the data.
There will be a little tricky, if you want to have a navigator in the same chart. Navigator works only with datetime data and it must be connected with the axis from the main chart.
So, you have data in that format:
var points = [
[5, 9, Date.UTC(2016, 1, 0)],
[65, 6, Date.UTC(2016, 1, 1)],
...
You need two x axes - one which represents the data and the other which is connected to the navigator. The second axis must be visible to work with the navigator and must be connected with the datetime data.
So now, except two x axes, you need two series - one with the actual data, and the other consists of [date, y] values from the first series. The additional data will be visible in the navigator - note, that in the navigator you cannot use scatter series - so it will be converted to line series - to happen it without errors, your data should be sorted by date.
series: [{
id: 'main-series',
data: points.map(function(point) {
return [point[0], point[1], point[2], point[1]]
}),
showInNavigator: false,
xAxis: 1,
keys: ['x', 'y', 'date', 'holdY'] //holdY is for easier hiding points
}, {
xAxis: 0,
data: points.map(function(point) {
return [point[2], point[1]];
}),
showInNavigator: true,
enableMouseTracking: false,
color: 'transparent',
showInLegend: false
}],
xAxis: [{
minRange: 1000 * 3600 * 24,
type: 'datetime',
tickLength: 0,
tickLength: 0,
labels: {
enabled: false
},
}, {
type: 'linear'
}],
The last thing you need a callback which will hide/show points after the extremes in the navigator are set. Hiding/showing depends on the third point's property which is date. There is no directly API to hide/show specific points (except pie), but it can be achieved by setting point's value to null (that is why I preserved the real y in holdY).
events: {
afterSetExtremes: function(e) {
var points = this.chart.get('main-series').points;
points.forEach(function(point) {
point.update({
y: e.min <= point.date && point.date <= e.max ? point.holdY : null
}, false, false);
});
this.chart.redraw();
}
}
example: https://jsfiddle.net/3wuwdonn/1/
I would consider using a navigator as a separate chart, then you wouldn't need the second x axis and series in the main chart and you wouldn't need to make them look invisible.
example with a navigator only chart here: http://jsfiddle.net/f7Y9p/