how to capture x axis and y-axis value in anychart - reactjs

I want to capture the x-axis and y-axis values when I click on axes in the console I want to show the values when I click on axes.
example this way :
chart.listen("click",function(){
chart.xAxis("{%value}");
console.log(xAxis.value(0));
});
It's not showing any value in the console I just want to get value when I click on xAxis or yAxis.

You can setup a click handler for individual labels, e.g.:
const xAxis = chart.xAxis();
xAxis.labels().listen('click', function (e) {
const labelIndex = e.labelIndex;
const label = this.getLabel(labelIndex);
const value = xAxis.scale().ticks().get()[labelIndex];
console.log(value);
});
You can see it in action in this playground (click on any xAxis label and its value will be logged to the console)

Related

d3.js Tooltip do not receive data properly

I have d3 line chart with two lines full with events and made a html tooltip to show some data from these events on mousemove. Its working fine until the moment when you switch to show only one line, than the tooltip doesnt receive any data. Ive log the data and it is coming to the tooltip, but tooltip is not receiving it for some reason. Check the code bellow:
const tooltip = d3.select('.Tooltip')
.style('visibility', 'hidden')
.style('pointer-events', 'none')
function mousemove (event) {
// recover coordinate we need
const mouse = d3.pointer(event, this)
const [xm, ym] = (mouse)
const mouseWindows = d3.pointer(event, d3.select(this))
const [xmw, ymw] = (mouseWindows)
const i = d3.least(I, i => Math.hypot(xScale(X[i]) - xm, yScale(Y[i]) - ym)) // closest point
path.style('stroke-width', ([z]) => Z[i] === z ? strokeWidthHovered : strokeWidth).filter(([z]) => Z[i] === z).raise()
dot.attr('transform', `translate(${xScale(X[i])},${yScale(Y[i])})`)
// console.log(O[i]) <-- this is the data for the current selected event and its fine after
changing the line shown
tooltip
.data([O[i]])
.text(d => console.log(d)) <-- here i log what is coming from data and doesn`t return anything
.style('left', `${tooltipX(xScale(X[i]), offSetX)}px `)
.style('top', `${tipY}px`)
.style('visibility', 'visible')
.attr('class', css.tooltipEvent)
.html(d => chartConfig.options.tooltip.pointFormat(d))
When you call tooltip.data([0[i]]), d3 returns a selection of elements already associated with your data, which does not make sense for your tooltip. If you already computed the value you want to show (I assume it is O[i]), then simply set the text or the html of the tooltip:
tooltip.html(chartConfig.options.tooltip.pointFormat(O[i]);

Get Stock Chart Crosshair yAxis Price onClick

I have a stock chart and I would like to get the value shown in the yAxis label that the crosshairs create when clicking in a plot. Essentially I want to know what the price is on the yAxis for the current location of my mouse when I click. So lets say the crosshairs yAxis label is showing 20, when I click, I want to put that 20 into a variable. So how can I "get" the crosshair's yAxis value? Thanks
const yAxis = plot.yAxis();
plot.listen('click', function (e) {
console.log(e)
//this will get the first label on the y Axis, this is 12
//I dont want the yAxis of the chart labels, I want the crosshair yAxis label
const value = yAxis.scale().ticks().get()[0];
console.log(value)
//prints 12
var value = chart.crosshair().yLabel()
//I dont know what to query to get the "value" of the label
console.log(value)
});
Yes, it is possible to get yAxis label value.
You can do so by acessing the plot's crosshair object.
//Create variable for label value
let yAxisLabelValue = 0;
//Handling click event
plot.listen("click", (e) => {
let label = plot.crosshair().yLabel();
let labelValue = label.text();
//Asigning current value to a variable
yAxisLabelValue = labelValue;
});
Feel free to try out on the playground how to interact with a crosshair object.

Is there a better approach to implementing Google Sheet's like cell functionality?

I'm building out a system in React that has tabular data with cells. Those cells are editable via contentEditable divs. It's functionally similar to google sheets. I'm working on the functionality where single click on the cell allows the user to override the current value of the cell and double clicking allows them to edit the value.
The functionality involved is basically this:
When single click on cell override the current value. (No cursor visible?)
When double click on cell allow the user to edit the current value. (Cursor visible, can move left and right of chars with arrowKeys)
When double clicked into the cell reformat value (removes trailing zero's for cents: 8.50 becomes 8.5)
When double clicked start the caret position at the end of the input.
When user clicks out of the cells reformat the current value to its appropriate format (example is a price cell)
My cell component looks like this:
(Note* useDoubleClick() is a custom hook I wrote that works perfectly fine and will call single/double click action accordingly)
export default function Cell({ name, value, updateItem }) {
const [value, setValue] = useState(props.value), // This stays uncontrolled to prevent the caret jumps with content editable.
[isInputMode, setIsInputMode] = useState(false),
cellRef = useRef(null);
// Handle single click. Basically does nothing right now.
const singleClickAction = () => {
if(isInputMode)
return;
}
// Handle double click.
const doubleClickAction = () => {
// If already input mode, do nothing.
if(isInputMode) {
return;
}
setIsInputMode(true);
setCaretPosition(); // Crashing page sometimes [see error below]
reformatValue();
}
// It's now input mode, set the caret position to the length of the cell's innerText.
const setCaretPosition = () => {
var range = document.createRange(),
select = window.getSelection();
range.setStart(cellRef.current.childNodes[0], cellRef.current.innerText.length);
range.collapse(true);
selectObject.removeAllRanges();
selectObject.addRange(range);
}
// Reformat innerText value to remove trailing zero's from cents.
const reformatValue = () => {
var updatedValue = parseFloat(value);
setValue(updatedValue);
}
const onClick = useDoubleClick(singleClickAction, doubleClickAction);
/*
* Handle input change. Pass innerText value to global update function.
* Because we are using contentEditable and render "" if !isInputMode
* we have override functionality.
*/
const onInput = (e) => {
props.updateItem(props.name, e.target.innerText);
}
// When cell is blurred, reset isInputMode
const onBlur = () => {
setIsInputMode(false);
cellRef.current.innerText = ""; // Without this single click will not override again after blur.
}
return (
<div
data-placeholder={value} // to view current value while isInputMode is false
class="cell-input"
contentEditable="true"
onClick={onClick}
onInput={onInput}
onBlur={onBlur}
ref={cellRef}
>
{isInputMode ? value : ""}
</div>
)
}
And here is some css so that the user can see the current value while isInputMode is false:
.cell-input {
:empty:before {
content: attr(data-placeholder);
}
:empty:focus:before {
content: attr(data-placeholder);
}
}
Now here are the issues I'm running into.
When I call the setCaretPosition function, there are no childNodes because I'm rendering the empty value ("") and crashes the page sometimes with the error- TypeError: Argument 1 ('node') to Range.setStart must be an instance of Node.
I have a $ inside cells that contain a price and I was setting that in the css with ::before and content: '$', but now I can't because of the data-placeholder snippet.
When double clicking into cell the cursor is not visible at all. If you click the arrows to move between characters it then becomes visible.
This solution has me pretty close to my desired output so I feel pretty good about it, but I think there might be a better way to go about it or a few tweaks within my solution that will be a general improvement. Would love to hear some ideas.

How to get coordinates (x,y) from a svg and put a text tag with a value

I'm trying to do a web app on React to write guitar tabs, i'm doing the tabs with SVG. I think i know how to get the coords but the problem is i don't know how to put that text tag with a value, because it doesn't have a value attribute (i think so)
my function:
// Doesn't work
// Suppose that i want to add a 2
const clicked = (evt) =>{
const { currentTarget: svg, pageX, pageY } = evt
const coords = svg.getBoundingClientRect() //<----- get the coords
const text = document.createElementNS('http://www.w3.org/2000/svg','text') //<--- create the svg
text.setAttribute('x', `$pageX - coords.x`) //<----- set the attributes X and Y with the mouse coords
text.setAttribute('y', `$pagey - coords.y`)
text.setAttribute('value', "2") //<----- It doesn't work
svg.appendChild(text)
}
heres other function, but to put circles:
//IT WORKS
clicked(evt) {
const {currentTarget: svg, pageX, pageY} = evt;
const coords = svg.getBoundingClientRect();
const circle = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
circle.setAttribute('cx', `${pageX - coords.x}`);
circle.setAttribute('cy', `${pageY - coords.y}`);
circle.setAttribute('r', '5');
svg.appendChild(circle);
}
Text is not an attribute, it's content so you want to replace
text.setAttribute('value', "2")
with
text.appendChild(document.createTextNode("2"))

Getting (X,Y) point on mouse click on chart

I am using react Chartjs's scatter chart to plot a line chart for a set of X,Y points.
I am trying to get the X and Y points when user right clicks anywhere on the chart by passing following function to onClick.
options={
...
onClick: function(event) {
let activeElement = Ref.current.chartInstance.getElementAtEvent(
event
);
let res =
Ref.current.chartInstance.data.datasets[
activeElement[0]._datasetIndex
].data[activeElement[0]._index];
}
}
But this only works when I click on plotted line on the existing point and not when I click anywhere in the chart. If I click anywhere else other the line, returned activeElement will be empty list.
How can I get X and Y regardless of where I click in chart area?
onClick: (e) => {
const canvasPosition = Chart.helpers.getRelativePosition(e, chart);
// replace .x. and .y. with the id of your axes below
const dataX = chart.scales.x.getValueForPixel(canvasPosition.x);
const dataY = chart.scales.y.getValueForPixel(canvasPosition.y);
},

Resources