Increase svg path size on leaflet - svg

I have a path included in an svg tag, I am looking for a way to double the size of the printing path. Here is my code. It does not work. The path is note showing at all when I add this
pathImageStation: "l0.01,-0.01l-3.72,-3.72l-1.06,1.06l2.11,2.11c-0.94,0.36,-1.61,1.26,-1.61,2.33a2.5,2.5,0,0,0,2.5,2.5c0.36,0,0.69,-0.08,1,-0.21v7.21a1,1,0,0,1,-1,1a1,1,0,0,1,-1,-1v-4.5a2,2,0,0,0,-2,-2h-1v-7a2,2,0,0,0,-2,-2h-6a2,2,0,0,0,-2,2v16h10v-7.5h1.5v5a2.5,2.5,0,0,0,2.5,2.5a2.5,2.5,0,0,0,2.5,-2.5v-9.5c0,-0.69,-0.28,-1.32,-0.73,-1.77m-1.77,2.77a1,1,0,0,1,-1,-1a1,1,0,0,1,1,-1a1,1,0,0,1,1,1a1,1,0,0,1,-1,1m-10,8v-4.5h-2l4,-7.5v5h2l-4,7z",
// "l0.01,-0.01l-3.72,-3.72l-1.06,1.06l2.11,2.11c-0.94,0.36,-1.61,1.26,-1.61,2.33a2.5,2.5,0,0,0,2.5,2.5c0.36,0,0.69,-0.08,1,-0.21v7.21a1,1,0,0,1,-1,1a1,1,0,0,1,-1,-1v-4.5a2,2,0,0,0,-2,-2h-1v-7a2,2,0,0,0,-2,-2h-6a2,2,0,0,0,-2,2v16h10v-7.5h1.5v5a2.5,2.5,0,0,0,2.5,2.5a2.5,2.5,0,0,0,2.5,-2.5v-9.5c0,-0.69,-0.28,-1.32,-0.73,-1.77m-1.77,2.77a1,1,0,0,1,-1,-1a1,1,0,0,1,1,-1a1,1,0,0,1,1,1a1,1,0,0,1,-1,1m-10,8v-4.5h-2l4,-7.5v5h2l-4,7z",
pathImageCity:
"h-2v-2h2m0,6h-2v-2h2m-6,-10h-2v-2h2m0,6h-2v-2h2m0,6h-2v-2h2m0,6h-2v-2h2m-6,-6h-2v-2h2m0,6h-2v-2h2m0,6h-2v-2h2m8,-6v-6l-3,-3l-3,3v2h-6v14h18v-10h-6z",
node_figure
.append("svg")
.attr("width","24px")
.attr("height", "24px" )
.attr("viewBox",(d: Node)=>{
const position = layer_point(vis, d);
return `${position.x} ${position.y} 24 24`
})
.append("path")
.attr("d", (d: Node) => {
const position = layer_point(vis, d);
const path =
find_node_type(d) == "city"
? `M${position.x + 8}, ${position.y - 14} ${
vis.value.pathImageCity
}`
: `M${position.x + 10.25}, ${position.y - 22} ${
vis.value.pathImageStation
}`;
return path;
})
.attr("stroke", (d: Node) =>
find_node_type(d) == "city" ? NODE_CITY_COLOR : NODE_HUB_COLOR
);
The path is too small, I added this to increase the size but is not showing at all.
.attr("width","24px")
.attr("height", "24px" )
.attr("viewBox",(d: Node)=>{
const position = layer_point(vis, d);
return `${position.x} ${position.y} 24 24`
})

Related

Using Sharp to turn svg to png corrupts text in node.js

I am using sharp to convert an svg file into png format to upload to a slack workspace.
I found the same issue here
const options = {
d3Module: d3,
selector: '#chart',
container: '<div id="container"><div id="chart"></div></div>'
}
const d3n = new D3Node(options);
const margin = {
top: 10, right: 5, bottom: 30, left: 5
}
const width = 1000 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svgWidth = width + margin.left + margin.right;
const svgHeight = height + margin.top + margin.bottom;
const svg = d3n.createSVG(svgWidth, svgHeight);
const tempData = [{ year: 2020, value: 100 }, { year: 2019, value: 200 }, { year: 2018, value: 30 }, { year: 2017, value: 50 }, { year: 2016, value: 80 }];
const xScale = d3.scaleBand().range([0,width]).padding(0.5);
const yScale = d3.scaleLinear().range([height,0]);
let yMax = d3.max(tempData, (d) => {return d.value})
yMax += yMax * 0.3;
xScale.domain(tempData.map((d) => {return d.year} ))
yScale.domain([0,yMax]);
svg.append('rect')
.attr('width','100%')
.attr('height', '100%')
.style('fill','rgb(28, 35, 51);');
svg.append('text')
.attr('transform','translate(150,0)')
.attr('fill','#85ceff')
.attr('font-size','24px')
.attr('x',50)
.attr('y',50)
.text('Node and D3 Bar chart')
svg.append('g').attr('transform',`translate(${100}, ${100})`);
svg.append('g')
.attr('transform', `translate(50, ${height})`)
.call(d3.axisBottom(xScale))
.append('text')
.attr('y', height-380)
.attr('x',width-500)
.attr('text-anchor','end')
.attr('stroke','black')
.attr('fill','#85ceff')
.attr('font-size','20px')
.text('Year')
svg.append('g')
.attr('transform','translate(50,0)')
.call(d3.axisLeft(yScale).tickFormat((d) => {
return `$${d}`;
}).ticks(5))
.append('text')
.attr('transform','rotate(-90)')
.attr('y',150)
.attr('x',-150)
.attr('dy','-9.1em')
.attr('text-anchor','end')
.attr('stroke','black')
.attr('font-size','20px')
.attr('fill','#85ceff')
.text('Cost')
fs.writeFileSync('out.svg', d3n.svgString());
sharp('out.svg')
.png()
.toFile('sharp.png')
.then((info) => {
console.log("Svg to Png conversion completed", info);
})
.catch((error) => {
console.log(error)
})
However, when I process my svg to png my text gets corrupted and is no longer in the photo. What am I doing wrong here?
To clarify, I am running this server on replit. When I run this code locally, the png is not corrupted. Could the replit server be the issue?
After browsing several Github Issues about this [Link 1, Link 2 , Link 3] , I did more research and discovered that I needed a font-config file and fonts downloaded because the Replit server did not have the fonts installed.
File Structure
- index.js
- api
- fetch.js
- fonts
- fonts.conf
- SourceSansPro-Regular.ttf
fonts.conf
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<dir>/home/runner/gittrack/fonts</dir>
<config></config>
</fontconfig>
Once I added the above changes, I am now getting fonts on my png

Client side D3 line chart from node.js server data

I'm trying to generate data on the server side (Node.JS) and then pass it via res.render to a view.ejs page for use in a simple D3 lineChart. I can hard code the data on the ejs page with a successful chart rendering. But, when I try to pass the data object from Node via res.render, D3.data doesn't seem to recognize the data.
Here is the server side route:
router.get("/view", function(req,res){
let data = [
{evalDate: 1598038171322, evalHypValue: 18},
{evalDate: 1608038171322, evalHypValue: 27},
{evalDate: 1618038171322, evalHypValue: 29},
{evalDate: 1628038171322, evalHypValue: 30},
];
res.render("view",
{
Data: JSON.stringify(data),
});
});
And here is the view.ejs with the D3 code:
<div class="" id="hyp_chart"></div>
<script>
//NOTE: hard coded data works with the D3
//let data = [
// {evalDate: 1598038171322, evalHypValue: 18},
// {evalDate: 1608038171322, evalHypValue: 27},
// {evalDate: 1618038171322, evalHypValue: 29},
// {evalDate: 1628038171322, evalHypValue: 30},
// ];
//But I can't get this next line to use my server side data as input to D3
let data = <%=JSON.parse(Data)%>
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the evalDate / time
var parseTime = d3.timeParse("%Q");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the line
var valueline = d3.line()
.x(function(d) { return x(d.evalDate); })
.y(function(d) { return y(d.evalHypValue); });
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select("#hyp_chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// gridlines in x axis function
function make_x_gridlines() {
return d3.axisBottom(x)
.ticks(5)
}
// gridlines in y axis function
function make_y_gridlines() {
return d3.axisLeft(y)
.ticks(5)
}
// Get the data
// format the data
data.forEach(function(d) {
d.evalDate = parseTime(d.evalDate);
d.evalHypValue = Number(d.evalHypValue);
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.evalDate; }));
y.domain([0, d3.max(data, function(d) { return d.evalHypValue; })]);
// add the X gridlines
svg.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_gridlines()
.tickSize(-height)
.tickFormat("")
)
// add the Y gridlines
svg.append("g")
.attr("class", "grid")
.call(make_y_gridlines()
.tickSize(-width)
.tickFormat("")
)
// add the valueline path.
svg.append("path")
.data([data])
// .datum(dataset)
.attr("class", "line")
.attr("d", valueline);
// add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
</script>
Thank you!!!

phantomjs - render HTML to PDF

I have problems with rendering a HTML file to a PDF file. I pass two arguments to the command line. The first is the HTML input file and the second the PDF output
/var/bin/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /var/www/nodejs/html_to_pdf.js /root/input.html /root/hello.pdf
code
var page = require('webpage').create(),
args = require('system').args,
f = require('fs').open(args[1], 'r');
page.paperSize = {
format : 'A4',
orientation : 'portrait',
margin : {
top : '1cm',
left : '1cm',
bottom : '1cm',
right : '1cm'
}
};
page.content = f.read();
page.setContent(page.content, page);
page.render(args[2]);
phantom.exit();
No errors is returned and no output PDF file?
Here is the input file
http://www.filedropper.com/input_3
I'd suggest rewrite to page.open a file:
var page = require('webpage').create();
var args = require('system').args;
var fs = require('fs');
function getFileUrl(str) {
var pathName = fs.absolute(str).replace(/\\/g, '/');
// Windows drive letter must be prefixed with a slash
if (pathName[0] !== "/") {
pathName = "/" + pathName;
}
return encodeURI("file://" + pathName);
};
page.paperSize = {
format : 'A4',
orientation : 'portrait',
margin : {
top : '1cm',
left : '1cm',
bottom : '1cm',
right : '1cm'
}
};
page.open(getFileUrl(args[1]), function(){
page.render(args[2]);
phantom.exit();
});
getFileUrl is from this answer

How can I connect coordinate points on a map using d3js?

I'm having trouble connecting points with a line on a map using d3. I think that I should use d3.svg.line() to create the points - but when I do it, I simply get a very small blob. Please see the link below for a screenshot of what I've been able to accomplish thus far - I want to connect the black dots with a line. Any help would be much appreciated.
Screenshot
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height*3 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var group = svg.selectAll("g")
.data(data)
.enter()
.append("g")
var projection = d3.geo.mercator().scale(5000).translate([-2000,5900])
var path = d3.geo.path().projection(projection)
var graticule = d3.geo.graticule()
var line = d3.svg.line()
.interpolate("linear")
.x(function(d) { d.geometry.coordinates[0]; })
.y(function(d) { return d.geometry.coordinates[1] ; });
// this returns a parse error
// .x(function(d) { return projection(d.geometry.coordinates[0]); })
// .y(function(d) { return projection(d.geometry.coordinates[1]) ; });
var area = group.append("path")
.attr("d", path)
// .attr("d", line(data))
.attr("class", "area")
})
You have to pass both components of your coordinate to the d3.geo.mercator object, before taking each one separately as your x and y values. Your 'parse error' should go away if you use
.x(function(d) { return projection([d.lon, d.lat])[0]; })
.y(function(d) { return projection([d.lon, d.lat])[1]; });
instead. This post has a more complete example: D3 map Styling tutorial III: Drawing animated paths.
Hopefully once you are drawing the lines in the correct projection, they'll appear as you expect.

Pop-Up Window, Center Screen

I'm using the following code to open a pop-up window in a Google Chrome extension, my one question is, how do I get the pop-up window to open in the centre of the users screen?
<script>
chrome.browserAction.onClicked.addListener(function() {
var left = (screen.width/2)-(w/2);
var top = (screen.height/2)-(h/2);
chrome.windows.create({'url': 'redirect.html', 'type': 'popup', 'width': 440, 'height': 220, 'left': '+left+', 'top': '+top+', } , function(window) {
});
});
</script>
I've also tried this, which resulted in no such luck.
<script>
chrome.browserAction.onClicked.addListener(function() {
chrome.windows.create({'url': 'redirect.html', 'type': 'popup', 'width': 440, 'height': 220, 'left': (screen.width/2)-(w/2), 'top': (screen.height/2)-(h/2), } , function(window) {
});
});
</script>
When you see var obj = {property: value} structure in JS it is an object creation. In your code you are trying to pass an object containing window properties to chrome.windows.create() function.
Correct code should be:
chrome.browserAction.onClicked.addListener(function() {
var w = 440;
var h = 220;
var left = (screen.width/2)-(w/2);
var top = (screen.height/2)-(h/2);
chrome.windows.create({'url': 'redirect.html', 'type': 'popup', 'width': w, 'height': h, 'left': left, 'top': top} , function(window) {
});
});
If you want the centering to also work with a dual monitor, you'll need to get the current window object from the extension and center your popup relative to that. Like so:
chrome.browserAction.onClicked.addListener(function() {
chrome.windows.getCurrent(function(win) {
var width = 440;
var height = 220;
var left = ((screen.width / 2) - (width / 2)) + win.left;
var top = ((screen.height / 2) - (height / 2)) + win.top;
chrome.windows.create({
url: 'redirect.html',
width: width,
height: height,
top: Math.round(top),
left: Math.round(left),
type: 'popup'
});
});
});
chrome.windows.create expects an integer for top and left, so it is recommended to wrap those values in Math.round.
If you want the screen to appear in the middle of the browser (not the center of the screen), and dynamic window size, you can do this.
chrome.windows.getCurrent((tabWindow) => {
const width = Math.round(tabWindow.width * 0.5) // dynamic width
const height = Math.round(tabWindow.height * 0.75) // dynamic height
const left = Math.round((tabWindow.width - width) * 0.5 + tabWindow.left)
const top = Math.round((tabWindow.height - height) * 0.5 + tabWindow.top)
chrome.windows.create( // https://developer.chrome.com/docs/extensions/reference/windows/#method-create
{
focused: true,
url: targetURL,
type: 'popup', // https://developer.chrome.com/docs/extensions/reference/windows/#type-WindowType
width, height,
left, top
},
(subWindow) => {}
)
})
Desc
Image
Show you what is the tabWindow.top and left
And you can use some filters to check whether the window has been created or not, to determine to create a new one, or show the window that you made.
chrome.windows.getAll({populate : true, windowTypes:['popup']}, (windowArray)=>{})
example code
chrome.windows.getCurrent((tabWindow) => { // https://developer.chrome.com/docs/extensions/reference/windows/#type-Window
const targetURL = 'yourTemplates/yourFile.html'
chrome.windows.getAll({populate : true, windowTypes:['popup']}, (windowArray)=>{
const queryURL = `chrome-extension://${chrome.runtime.id}/${targetURL}`
const target = windowArray.find(item=>item.tabs[0].url === queryURL) // ❗ make sure manifest.json => permissions including "tabs"
if (windowArray.length > 0 && target !== undefined) {
// Show the window that you made before.
chrome.windows.update(target.id, {focused: true}) // https://developer.chrome.com/docs/extensions/reference/windows/#method-update
return
}
// Otherwise, Create
const width = Math.round(tabWindow.width * 0.5)
const height = Math.round(tabWindow.height * 0.75)
const left = Math.round((tabWindow.width - width) * 0.5 + tabWindow.left)
const top = Math.round((tabWindow.height - height) * 0.5 + tabWindow.top)
chrome.windows.create( // https://developer.chrome.com/docs/extensions/reference/windows/#method-create
{
focused: true,
url: targetURL,
type: 'popup', // https://developer.chrome.com/docs/extensions/reference/windows/#type-WindowType
width, height,
left, top
},
(subWindow) => {
}
)
})
})
As an addendum to this answer, if you want to retrieve popup dimensions from localstorage--which are saved as strings--this will convert the variables to the necessary integers for the pop-up to work.
var w = parseInt(localStorage.getItem('key'));
var h = parseInt(localStorage.getItem('key'));

Resources