I am not sure how the tick placement works with d3 svg axis. I tried playing with the ticks, tickSize options but essentially I get the start and end ticks "sometimes" with random data plotted
http://plnkr.co/edit/i5DBgfWzr2sa8Yugg2A8?p=preview
(Please ignore the angularjs aspect. The part that I am interested in is the following in d3)
var make_x_axis = function () {
return d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(5)
.tickFormat("")
.tickPadding(8);
};
var make_y_axis = function () {
return d3.svg.axis()
.scale(y)
.ticks(6)
.orient("left")
.tickSize(10,10)
.tickPadding(8);
};
How do I always get the start and end ticks rendered for both X and Y axis? I clearly always get the start and end tick lines on both X and y axis (Unsure how that is happening - I do not see a .tick element at that location in the chrome inspector) but the labels are missing. I can find the first and last tick and render a text with the tick label info but clearly I cannot always do it because sometime the axis gives me the start ticks and sometime it does not.
Any help is appreciated.
Thank you
I am not sure I fully understand your question, if you want to remove the ending x-axis ticks, you should set
d3js V3
.outerTickSize(0),
d3js V4 - V6
tickSizeOuter(0)
If you want to customize the ending ticks, you may use
.tickValues(y.ticks(5).concat( y.domain() ));
Have a look at my JSFiddle for a demonstration.
Related
I have a noUiSlider with several handles to allow specifying several contiguous date periods (example = Feb to Apr, May to July, and Aug to Sept). Ideally I would like to have labels that appear centered on the connect divisions to describe what each period relates to (ex. "Current Period", "Next Period"). I was thinking I could do this by setting a centered background image on the noUi-connect divisions.
However, the noUi-connect divisions use transform (translate/scale) styling which results in my background images being scaled which I do not want.
I also thought maybe I could revise the javascript to generate an outer division around each nonUi-connect division, and I would apply the background onto the outer division instead - but I was unable to get the background from the outer division to appear.
Any other ways I could accomplish this? The only other thing I can think of it to have floating divisions defined outside of the noUiSlider object which I would need to reposition whenever I detect changes in the handle positions.
You can add an element outside of the connects and absolutely position it.
A quick version for a slider with two handles (showing the value for the first handle):
var origin = slider.querySelector('.noUi-connects');
var node = document.createElement('div');
node.style.textAlign = 'center';
node.style.position = 'absolute';
node.style.zIndex = '10';
node.style.fontSize = '10px';
origin.appendChild(node);
slider.noUiSlider.on('update', function(values, handle, unencoded, tap, positions) {
node.style.left = positions[0] + '%';
node.style.right = (100 - positions[1]) + '%';
node.innerText = values[0];
});
Just realized another approach is to set the innerHtml of the specific noUi-connect divisions to my label values. Simpler than playing with background images.
But the transform styling still affects the labels, so the end result is not better. Maybe I can load the innerHtml with an inner division that somehow ignores the transform settings but I haven't figure out how to do that yet. transform: none does not make any difference.
GOAL
I am trying to build a signature pad in SVG. You can view
Sample project here.
Description
So far, it works in Chrome, Edge and Opera as desired but, in Firefox, getScreenCTM() doesn't account for the scale.
Research
I went through a bunch of documentation from bugzilla and a couple of posts here in SO such as SVG: GetScreenCTM() for nested SVG is different in Firefox but, still couldn't figure out how to fix my issue.
Problem
I've added a browse check to handle only Firefox (since all other browsers provides the desired result) which allows me to add extra code to fix the problem but, thus far, had no success. (SPSignature:416)
Reproduce the error
To reproduce the error, open the sample link in FireFox than, resize the box so it is at least 20% smaller as in fullscreen. You will see the mouseX/Y position change as scale changes.
I've tried to get the matrix transform from the group tag but, it returns similar result from the SVG. How do I calculate the CTM, so its result is similar/equal to Chrome?
Code
Source code here SPSignature:416
_getCursorPoint(event)
{
const svg = document.querySelector('.spsignature svg');
let pt = svg.createSVGPoint();
pt.x = event.clientX;
pt.y = event.clientY;
// firefox workaround:
if (this._checkBrowser() === 'Firefox') {
const matrix = this._decomposeMatrix(svg.getScreenCTM());
let cood = {
x: event.layerX,
y: event.layerY
};
if (matrix.scaleX < 0.9 || matrix.scaleY < 0.9) {
console.log('%c #todo: fix mouse position for FF on getScreenCTM().', 'background:#c00;color:#fff;padding:3px;');
}
return cood;
}
return pt.matrixTransform(svg.getScreenCTM().inverse());
}
To "fix" the mouse XY problem on FF, I've used the root scale value to allow for the calculation of the cursor XY position.
The scale can be retrieved from the matrix based on https://gist.github.com/2052247.
Also, in FF, I've used the event.layerX and event.layerY instead of event.clientX and event.clientY for the initial mouse coordinate values.
So, instead of using matrixTransform(svg.getScreenCTM().inverse()) to return the calculated XY relative to the SVG, I've used the scale and layerXY to calculate the right XY position.
I'm trying to use moveViewToX to show a chart starting from the last x value, so the user drags the chart to see older data. But it does not move exactly where I expected, I'm moving to the value 2.013 but it's starting before it, then I can't see my last x value which is 2.018. Take a look at the images for better understanding.
[image showing what's happening] [1]: https://i.stack.imgur.com/t0Z4f.png
[image showing what I expected to happen][2]: https://i.stack.imgur.com/U3JhM.png
Here's the part of the code that modifies LineChart
mLineChart.getAxisRight().setEnabled(false);
mLineChart.getDescription().setEnabled(false);
mLineChart.getXAxis().setAvoidFirstLastClipping(true);
mLineChart.setVisibleXRangeMaximum(5);
mLineChart.getXAxis().setGranularity(1);
mLineChart.moveViewToX(2013);
mLineChart.invalidate();
I'd appreaciate any help. Thanks!
You need to set a dragOffsetX, otherwise the chart will not allow you to move past the end of the last value on the x axis.
You can also try specifying the axis maximum:
mLineChart.getXAxis().setAxisMaximum(lastValue + 5)
Is there a way I can get the x-axis to switch from showing hour, to e.g. week days, months .. when zooming out?
Currently my x-axis is configured as such:
xaxis: {
mode: "time",
minTickSize: [1, "second"],
timeformat: "%H:%M:%S",
}
My default the graph looks nice, but when I zoom out enough times, the labels on the xaxis just display "00:00". How can I change the timeformat so that the date is included also? E.g. Tue 27 00:00 or similar.
Here's an example of when the graph is zoomed out a lot (obviously I need to remote some datapoints to make it look smoother..)
You can add a date using the standard specifiers, like %Y-%m-%d. A full list can be found in the API docs under the Time Series Data section.
To get the format to update based on the range, i.e. show HMS when zoomed in but YMD when zoomed out, is trickier. You'll need to listen for the 'plotzoom' event and check the range to see whether the format needs to change. If so, use getOptions() to retrieve and update the plot's options, then call setupGrid & draw to redraw the plot using the new format.
I solved this by making a custom tickFormatter for the X-axis:
In your xaxis options put:
xaxis: {
mode: "time",
tickFormatter: customXAxisFormatter,
...
}
Then your customXAxisFormatter could be eg. :
function customXAxisFormatter(val, axis)
{
var d = new Date(val);
// If time difference is more than 24 hours
if ((axis.max - axis.min) > (24*3600*1000))
return d.strftime("%a<br>%H:%M");
else
return d.strftime("%H:%M");
}
I hope this helps :)
I found this solution.
If type of chart is pie, how specify parameters (x,y) of highlight(x, y)?
Thanks
Sorry for my bad English.
Unfortunately, flot doesn't expose the pie highlighting code to the user. So we are pretty much out of luck, but what may work for you is synthesizing a click event at the appropriate place on the page:
$("#highligher").click(function () {
var e = jQuery.Event('click');
e.pageX = 250; //add a made up x/y coordinate to the click event
e.pageY = 250;
$('#plot canvas:first').trigger(e); //trigger the click event on the canvas
});
Here it is in action: http://jsfiddle.net/ryleyb/mHJm5/
The problem is you have to know where the slice you want to highlight is already. This would be easy enough to set if the graph is static. If it's a dynamic graph, you'd have to dig into the source of the pie code to figure out how to calculate where the pie slice is. It might be easier in that case to just have a copy of all the pie functions and manually draw on the pie overlay.
Just got this working by altering a few things...
I changed highlight and unhighlight in jquery.flot.pie.js to pieHighlight and pieUnhighlight.
Then, after these two lines in jquery.flot.pie.js...
plot.hooks.processOptions.push(function(plot, options) {
if (options.series.pie.show) {
I added...
plot.highlight = pieHighlight;
plot.unhighlight = pieUnhighlight;
We're maintaining selection state outside of the chart (as a backbone model). When a selection event (click) occurs, we set the selected slice in the model. When selection changes, we refresh the chart using a selection color for the pie slices that are selected.
var data = [];
var color = slice.index == selected ? '#FF0000' : '#0000FF';
data.push({label:slice.Label,data:slice.Value,color:color});
The snippet above uses blue for all non-selected slices, red for the selected slice. Your color logic will be more sophisticated.
NOTE: You can also use rgba CSS for the colors, which gives a really nice effect. For example:
var color = slice.index == selected ? 'rgba(0,0,255,1)' : 'rgba(0,0,255,0.5)';