Setting connector (edge) points in mxgraph - javascript

I'm trying to import a diagram in our custom format to mxgraph, but am stuck on setting the points on the connector. I've tried called the functions in mxEdgeStyle like ElbowConnector:
ElbowConnector(view.getState(edge), model.getSource(edge), model.getTarget(edge), points)
where points is the array of point I want to set. I get the feeling I'm calling entirely the wrong function, or am I using it incorrectly?

The edge styles are style like the other key/value styles. In the link you provide to the API specifications, the top example tells you how to use it:
var style = stylesheet.getDefaultEdgeStyle();
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector;

Related

Sankey-diagram PowerBI custom visual with color nodes and ordering

The sankey diagram of PowerBI has many possibilities but as you can read on the github site there are some important limitations. The first is that it is not possible to color the nodes. In addition, it is also not possible to change the order of the nodes (both source and destination).
Attached is an example PowerBI file in which a sankey is displayed. In this file is indicated which colors the nodes should have and what the order of the nodes should be.
The best solution is of course to use PowerBI to indicate the colors as in this example with the links. But probably it is easier to indicate the colors of the nodes (names) in the code itself with a hard value this would also be a nice alternative. Same holds for the ordering of the nodes
I looked at the colorscale function of d3 to link it to fillcolor. But I got an error message that the string values cannot be linked to colorscale.
The Github page with the code can be found here:
https://github.com/microsoft/powerbi-visuals-sankey
I think this line of code should change:
nodeFillColor = this.colorHelper.isHighContrast ? this.colorHelper.getThemeColor() : this.colorPalette.getColor(index.toString()).value;
console.log(nodeFillColor);
nodeStrokeColor = this.colorHelper.getHighContrastColor("foreground", nodeFillColor);
The colors are now based on a theme color. Hopefully it is possible to link the nodes (name) to a color instead of a theme.
Hopefully you can help me and other users of the Sankey.
It looks like if you need to inject some 3rd party color values (whether hex or some other format) you can use the ColorHelper instance at play in the code you highlighted to "cheat". The following example can be found in the powerbi documentation here: https://github.com/microsoft/powerbi-visuals-utils-colorutils/blob/master/docs/api/colorUtils.md#calculatehighlightcolor
import ColorUtility = powerbi.extensibility.utils.color;
let yellow = "#FFFF00",
yellowRGB = ColorUtility.parseColorString(yellow);
ColorUtility.calculateHighlightColor(yellowRGB, 0.8, 0.2);
// returns: '#CCCC00'
Ultimately I think it comes down to this one helper method:
ColorUtility.parseColorString('<colorhex>')
I don't know exactly the best way to plug it in to what you're doing, but you might try generating a random hex color and plugging it in to see what comes out the other side.
// thanks Paul Irish: https://www.paulirish.com/2009/random-hex-color-code-snippets/
let randcolor = '#'+Math.floor(Math.random()*16777215).toString(16)
// Then to replace the example code you had in your question...
nodeFillColor = this.colorHelper.parseColorString(randcolor)
nodeStrokeColor = this.colorHelper.getHighContrastColor("foreground", nodeFillColor);

Chart.js 2.2.x - How to access the pixel coordinate of a point in my dataset

I'm creating a plugin for my chart (in ChartJS 2.2.2), and for that I need the pixel position of each point of my dataset.
When inspecting the chart.config.data.datasets[0]._meta[0], I get back the following object:
But when I access the x field directly in my plugin code, the values returned are different. The commands:
chart.config.data.datasets[0]._meta[0].dataset._children[0]._model.x and
chart.config.data.datasets[0]._meta[0].data[0]._model.x (which yields the same value when looking it up in the chrome debugger) both return x = 3 instead of 44.67.
Why is this happening? What is the proper way to access the pixel coordinate of a point in my dataset?
The plugin is called multiple times, I was debugging only the initial values for the coordinates. Turns out the last calls were made with the correct value for X (44.67). I think this was happening because initially the canvas containing the chart was hidden (using ng-hide), only after init it was being shown.
It was rendered correctly though.

Search for and zoom in to a scatter plot point (Highcharts, react.js)

I'm using the highcharts library in react.js and it's working great. However, I'm plotting ~15,000 scattered points and it's a bit tricky finding the one I want among all that. I'd like to be able to search for a specific point, since each point has its own unique name property along with its x and y coordinates (not id, but I could put the name as id if that made the solution easier). When the point is found, the graph should zoom in a bit, since at default zoom level there's quite a few overlaps of points so just making it blink/bigger/something wouldn't help much. I've looked through the Highcharts API docs but I can't find anything that will do a manual zoom into specified coordinates.
I found the mapZoom function, but that's only for maps, and... well, this isn't a map. It's a scatter plot.
Also, since this is react, it's a bit tricky to see how I can access the chart object to do stuff with it, since the only time it exists is when it's being returned to be rendered:
var CosinePlot = React.createClass({
componentDidMount: function() {
let chart = this.refs.chart.getChart();
},
render: function() {
return <ReactHighcharts config={plotConfig} isPureConfig={true}/>;
}
});
If you know exact point you want to zoom in, simply get it's x and y. Then zoom into that point using chart.xAxis[0].setExtremes(min, max) and chart.yAxis[0].setExtremes(min, max).
And regarding accessing the chart object, I guess you are using this this wrapper. There is an explanation how to retrieve that chart object here.

Create SVGPoint inside an element with user coordinate

I have a small project (to learn SVG) running (using javascript).
I would like to be able to track a point in a shape with its own user coordinate system. My idea is to find the coordinates of the point within the shape, then create an SVGPoint, so that I can pass on that element. I have seen the method create SVGPoint in examples, but it seems it is used in the context of the 'SVG_root' (that is, document.documentElement.createSVGPoint() works).
When I use (in Firefox)
inSvgObj.createSVGPoint()
where inSVGObj is a element, the web console says "TypeError: inSvgObj.createSVGPoint is not a function". Is it possible to create an SVG point within the to subsequently set with values representing coordinates in that 's user coordinate system?
EDIT (after considernig Robert Longson's answer):
Given that SVGPoint is created only within an "SVG root" and that I have been unable to find a way to move that to within another element, I have found more convenient to use a different svg element type: SVGMatrix. In case it helps someone (as I have spent some time trying to deal with this),It is possible to manipulate analogue values inside an SVG Point by creating an SVGMatrix that would work as a simulated point (for the purposes of coordinates. To that endthe methods .createSVGMatrix(), getCTM() and.multiply() (this last from SVGMatrix) are used. To illustrate that, I will include a (js) function that takes 4 arguments: x-coordinate in user coordinate system (ucs) to transform, y-coordinate is that ucs, object whose ucs is the want we want to transform and an object in the ucs we want to transform to; and returns am object with thrre poperties the x-coordinate in the transformed ucs, its y-coordinate and 1 (for consistency with SVG Recommendations).
function coorUcsAToUcsB(ucsAx,ucsAy,svgObjUcsA,svgObjUcsB){
var ctmUcsA=svgObjUcsA.getCTM();
var ctmUcsB=svgObjUcsB.getCTM().inverse();
var mtx=document.getElementsByTagName('svg')[0].createSVGMatrix();
mtx.e=ucsAx;
mtx.f=ucsAy;
var simulSvgP=ctmUcsB.multiply(ctmUcsA.multiply(mtx)); //1
return {"x":simulSvgP.e,"y":simulSvgP.f,"z":1};
}
//1 this line creates an svg matrix with 1st and 2nd column at 0, 3rd with coordinates of ucsB from the analogue svg matrix with coordinates in ucsA - it takes the coordinates in ucsA to viewport's cs and from there to coordinates in ucsB. For the matrix operation explanation, see this.
Any comments, in particular having overlooked a existing method that does the same or any drawbacks, will be more than welcome.
You create the SVG Point using the root element creation but once you've done that you can set whatever values in it you want. When you assign those values to an object the object will interpret them in its coordinate system.

apply all transform matrices

I am looking for a possibly fast way to apply all transform matrices of a given svg-graphic. In other words: the algorithm should remove all "transform" attributes and transform all coordinates of the graphic to absolute coordinates.
Is their any library that can do this, or is their any SVGDomInterface method that coulld do that?
EDIT::
If I call the consolidate method like this:
$.each( svg.find( 'path' ), function( i ){
this.transform.baseVal.consolidate();
});
nothing happens, if i call it like this:
$.each( svg.find( 'path' ), function( i ){
this.transform.animVal.consolidate();
});
i get this error:
So, how should i use the "consolidate" method, on which elements shall I call it?
Greetings
philipp
Here's a jsFiddle with some javascript library code (based in part on Raphael.js) to bake the transforms into all paths' data:
http://jsfiddle.net/ecmanaut/2Wez8/
(Not sure what's up with Opera here, though; it's usually best in class on SVG. I may be stumbling in some way the other browsers are more forgiving about.)
The consolidate method only reduces the list of matrices to a single matrix. And the error you get on the animVal example is because you are not allowed to modify the animated values (consolidate destructively modifies the transform list).
To answer your question, no there's no existing method in SVG DOM that applies the transforms by modifying the values of paths etc. There are options in Inkscape (and Illustrator too IIRC) for applying transforms like that.
If you're looking for a library or utility that does this you can try SVG Cleaner.
SVG Cleaner didn't seem to apply all transforms for me, but Inkscape does. Here's the command line I use when I need to apply one:
inkscape copy-of-file.svg --select=id-of-node \
--verb=EditCut --verb=EditPaste \
--verb=FileSave --verb=FileClose
Assuming you have "Transforms -> Store transformation" set to "Optimized" in inkscape's prefs (I believe it is on by default), this will apply it and produce the wanted result. Be sure you operate on a copy of your input file, as the operation replaces your original file!
If you are running this on a mac, you may want to first do this in your shell:
alias inkscape=/Applications/Inkscape.app/Contents/Resources/bin/inkscape
Better use EditPasteInPlace instead of EditPaste. EditPaste pastes at the mouse location, which is not the location of the node.
In order to retreive the path relative to some other, parent DOM node (e.g. the SVG root container), you can use the technique here.
It uses SVG.getTransformToElement which calculates the transform between a parent and some node on the SVG tree. The returned object contains methods to return the inverse of the transform, etc, to do practical things with it.
How to determine size of Raphael object after scaling & rotating it?
I dont know exactly what you are trying to achieve, but this has the power to do it.

Categories

Resources