I've been looking for a solution to this but I cannot seem to find one for linking an edge label to another GraphViz Dot Graph. For example, if I have a graph called 'mydotimage2.svg' produced from the following:
digraph G
{
graph [compound = true];
subgraph cluster_0
{
node [style = bold];
"A" "B" "C";
}
subgraph cluster_1
{
node [style = bold];
"One" "Two" "Three";
}
"A" -> "One" [lhead = cluster_1, ltail = cluster_0, label = "Falafel", href = "~/workspace/GraphViz/mydotimage1.svg"]
}
If I create the 'mydotimage2.svg' SVG image in my terminal via:
dot -T svg mydotimage2.dot > mydotimage2.svg
The image opens just fine in my browser, and the edge label from A to One in the produced image is clickable, but does not open mydotimage1.svg which is in the same GraphViz directory as well. Does anyone know how to do this? I would really appreciate it. Thanks in advance.
You should use relative paths.
That is, instead of href = "~/workspace/GraphViz/mydotimage1.svg" use href = "./mydotimage1.svg"
BTW, instead of using pipe redirection(>) you can specify desired output file name as a parameter to the dot.
Just append -omydotimage2.svg to the command line.
Where "mydotimage2.svg" is the file name you want to write to.
This is what I observe on my machine, I guess it's a general problem:
graphviz does expand the tilde ~ to but it does not remove the tilde. In my case I see /home/rainer/~/workspace/GraphViz/mydotimage1.svg as image location when I click on the hyperlink in the graph. That obviously doesn't exist. Looks like a bug to me...
The solution / workaround is to replace the ~ in the script with your home folder path, in my case
href = "/home/rainer/workspace/GraphViz/mydotimage1.svg"
which works as expected.
Related
Working with Scala.js, I have created some SVG elements like Text, Line, Rect, and now I am trying to set the style attribute with code like this, where element is of type svg.Stylable:
element.style.fillOpacity = "0.0"
element.style.stroke = "yellow"
element.style.strokeWidth = "2"
I tried different variations of above code, but the desired style does not realize, and when I inspect the element in the Browser, the style attribute is an empty String (""). I am able to set other attributes with no problem (e.g. x, y, width, height).
How do I set the style? Thanks!
For SVG modications in Scala.js I normally use the d3 library (scala.js facade: https://github.com/spaced/scala-js-d3).
Then u can use:
d3.select("#mySvgElement").attr("style", "stroke:yellow; stroke-width:2") // etc.
*Edit: mySvgElement would be the ID of the element i want to change the style for. You can also other different kind of selectors.
Maybe I miss something from the documentation. Blessed.js (the curses-like library for node) comes with any kind of boxes / input / output / mouse utilities and seems wonderful, but how can I set a single character on the screen?
For example, having created the screen like this:
const blessed = require('blessed');
const screen = blessed.screen({
smartCSR: true
});
how can I use screen to display, say, the character 'A' in position [4, 5] (fuorth character of the fifth row)?
Thanks
Use their text widget. Create one and add it to the screen.
let anA = blessed.text({content:'A', top:4, left:5}) // create a text widget
screen.insert(anA) // add it to the screen
screen.render(); // render the screen
I've barely worked with it, there might be a simpler way. But forgetting to render is what me got most of the time.
I'd like to create choropleth map of Czech Republic. Inspired by this article http://bl.ocks.org/mbostock/4060606, I have created this
http://jsfiddle.net/1duds8tz/2/
var width = 960;
var height = 500;
var svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
var offset = [width / 2, height / 2];
var projection = d3.geo.mercator().scale(6000).center([15.474, 49.822]).translate(offset);
var path = d3.geo.path().projection(projection);
queue().defer(d3.json, "..map.geojson").await(ready);
function ready(error, reg) {
var group = svg.selectAll("g").data(reg.features).enter().append("g");
group.append("path").attr("d", path).attr("fill", "none").attr("stroke", "#222");
}
When I tried to fill svg path with some color, I ended on this
http://jsfiddle.net/1duds8tz/3/
group.append("path").attr("d", path).attr("fill", "red").attr("stroke", "#222");
There are odd values in path d attribute.
My GeoJSON data must be somehow faulty but I can't figure what is wrong.
Everything looks right here: https://gist.github.com/anonymous/4e51227dd83be8c2311d
Your geoJSON is corrupted and as a result your polygons are being drawn as the interiors of an infinitely bounded polygon. That's why when you attempt to give a fill to the path, it goes beyond the extent of the screen but still displays the border just fine. I tried to reverse the winding order of your coordinates array, and that seemed to fix all of them except for "Brno-venkov", which might be the source of your problems (especially given its administrative shape).
I'd suggest going back to where you created the original GeoJSON and try to re-export it with simplification. If you want to reverse the coordinates on your GeoJSON to correct the winding order, that's pretty simple:
geodata = d3.selectAll("path").data();
for (x in geodata) {geodata[x].geometry.coordinates[0] = geodata[x].geometry.coordinates[0].reverse()}
But this won't fix the problem polygon, nor will not reversing its coordinates.
In case you are familiar with svg manipulation you can try geojson2svg. This allows you manipulate svg in standard way but you have to code a little more. In case your application requires d3 for many other purpose then d3 is best solution.
I've got exactly the same problem with Mapzen's .geojson files.
.reverse()-ing isn't good enough, if you can't make sure all your data has the same winding order.
I solved it with this one:
https://www.npmjs.com/package/geojson-rewind
You'll need to have npm & require available
Install it, and save it to your project
npm i -g geojson-rewind
Import it, to make it useable
var rewind = require('geojson-rewind');
Use it on the data, in this case:
req = rewind(req);
Tip: If you are working with static data, you can do this only once on the console, and you're good to go.
Here's the fiddle: http://jsfiddle.net/DevChefOwen/CZ6Dp/
var text = g.append("text")
.style("font-size",30)
.style("fill","#000")
.attr("dy",0)
.append("textPath")
.attr("xlink:href","#yyy")
.style("text-anchor","left") // using "end", the entire text disappears
.text("some text");
I've tried a number of different things to no avail. The left align is the easy part. If you did a middle, though, you see only "text" instead of "some text", implying that "some" is just hidden because it went "out of span" for the given arc.
If, however, I added:
.attr("startOffset","39%")
(as in here: http://jsfiddle.net/DevChefOwen/2H99c/)
It would look right aligned, but outside of programmatically trying to get the width/height of the text element and look for sharp changes in width/height (which seems wrong and likely error-prone), I can't seem to find a way to right align the text.
I've also tried using an SVG path (essentially a curved arc line) and the same disappearing act happens with the text when "text-anchor" is set to "left".
Thanks ahead for your time!
The question is somewhat confusing matters. The issue isn't aligning text at the end of the path -- that's easy to do with "text-anchor"="end" and "startOffset"="100%".
However, using those settings with the path created by the d3 arc function, you end up with the text cornering around the end of the inside curve and the left straight edge, to the end of the path as defined by the arc function:
http://jsfiddle.net/CZ6Dp/8/
The real issue is that the path that you want the text to be aligned along (the outside arc of the shape) is only one segment of the path that defines the shape.
(By the way, "left" and "right" are not valid values for the "text-anchor" property, and will just be ignored).
The answer by #defghi1977 gives one way to approach the problem, by figuring out the length of the path segment that you do want to use and adjusting the start offset accordingly.
Another way to approach the problem is to create a separate path (not drawn on screen) that represents only the part of the path that you want to be used for positioning text.
There are a number of possible ways to create a path that only represents the outside arc (some example code here). #defghi1977's approach of grabbing it from the existing path with regular expressions is probably the most efficent for your situation. But instead of just creating a temporary element to calculate a length, I actually have to add the new path to the DOM so it can be used as the reference path for the <textPath> element. (Which I suppose is the downside to this approach -- twice as many DOM elements!)
var path = g.append("svg:path")
.attr("d", arct)
.style("fill","#ccc")
.attr("transform", "translate("+cfg.w/2+","+cfg.h/2+")")
.each(function(d,i) {
var justArc = /(^.+?)L/;
//grab everything up to the first Line statement
var thisSelected = d3.select(this);
var arcD = justArc.exec( thisSelected.attr("d") )[1];
defs.append("path")
.attr("id", "yyy") //normally the id would be based on the data or index
.attr("d", arcD)
.attr("transform", thisSelected.attr("transform") );
//if you can avoid using transforms directly on the path element,
//you'll save yourself having to repeat them for the text paths...
});
var text = g.append("text")
.style("font-size",30)
.style("fill","#000")
.attr("dy",0)
.append("textPath")
.attr("xlink:href","#yyy")
.style("text-anchor","end")
.attr("startOffset","100%")
.text("some text");
http://jsfiddle.net/CZ6Dp/9/
Again, factoring in the extra DOM load #defghi1977's method is probably slightly preferrable, although this version has the benefit of not being dependent on browser support for getTotalLength. But as far as I know that method is fairly well implemented.
So just consider this an alternate approach for completeness' sake.
This path is constructed by 4(or 5) path segments.
So, this probrem will be solved to get first arc path length.
But I don't know how to get sub path length by using d3.js, thus I use svgdom directly.
I tried to fix your code. If this code is not what you hope, I'm sorry.
path-anchor attribute to end.
define function to get startOffset value.
var path = g.append("svg:path")
.attr("id","yyy")
.attr("d", arct)
.style("fill","#ccc")
.attr("transform", "translate("+cfg.w/2+","+cfg.h/2+")");
var text = g.append("text")
.style("font-size",30)
.style("fill","#000")
.attr("dy",0)
.append("textPath")
.attr("xlink:href","#yyy")
//.style("text-anchor","left") // using "end", the entire text disappears
.attr("text-anchor", "end")
.text("some text")
.attr("startOffset",function(){
var d = document.getElementById("yyy").getAttribute("d");
var tmp = document.createElementNS("http://www.w3.org/2000/svg" ,"path");
//get the arc segment of path
var arc = d.match(/(^.+?)L/)[1];
tmp.setAttribute("d", arc);
//return offset position
return tmp.getTotalLength();
});
I think the confusion comes from the meaning of text-anchor - it's not "relative to where on the parent will I justify" but rather "what part of me should I align to the start".
You're right to try to use startOffset to move the origin. Since the outer radius of your path is longer than the inner radius, the correct start offset is a little more than half of the path (around 53%).
Just a little more twiddling with your settings and you should have it. Here's a fiddle with my interpretation of what you're looking for.
I am making my first application for BlackBerry (OS 6.0+) and I have to define a screen like in the image below. I have read about RichList but its not allowed to be added below the other components.
What I want is the part (list) below the wide ButtonField. The white boxes should contain images and the scribbles in front of it should contain text. This "list items" are populated dynamically.
As you can see, this very-much resembles the layout of a RichList, but I can't seem to add it to the VerticalFieldManager that I have used as the main container of components.
So if anyone can help me get this screen, I'm really grateful! Thanks in advance.
You need to implement ListFieldCallback and overwrite all methods. There you will see "drawListRow" method. You need to draw Images on left and text on write on this method index wise. like this:-
ListData ld = (ListData) rows.elementAt(index);
g.drawText(ld.name, 30+extraSpaceDelete, y
+ (listItemHeight - g.getFont().getHeight()) / 2);
g.drawText(ld.address, 30+extraSpaceDelete, (y
+ (listItemHeight - g.getFont().getHeight()) / 2)+(g.getFont().getAscent()+10));
g.drawBitmap(0, y + listItemH - 3, Display.getWidth(), 3,
separator_line, 0, 0);