Is there a way to make svg.js work with node.js - node.js

Did someone of you try to make svg.js work with node.js? I tried to use the jsdom module to render svg but jsdom but SVG.supported returns false. Is there a way to make this library work with node.js?
Thanks in advance!
EDIT: Here is my code, I want to make that on Node.js and then probably render the SVG in a pdf or as a png:
var draw = SVG('drawing').size(600, 600)
var image = draw.image('inclusions.png')
image.size(400, 150)
var rect = draw.rect(400, 150).attr({ fill: 'orange' })
for (i = 0; i < 10; i++) {
var point = draw.circle(5)
var xpos = Math.floor((Math.random() * 400) + 1);
var ypos = Math.floor((Math.random() * 150) + 1);
point.x(xpos)
point.y(ypos)
point.fill('black')
}
image.front()

Here is the working example usage of svg.js inside nodejs project,
svgdom is the suggested library from svg.js official website
const window = require('svgdom');
const SVG = require('svg.js')(window);
const document = window.document;
function generateSVGTextLines(width, height, lineList, tAsset) {
var draw = SVG(document.documentElement).size(width, height);
draw.clear();
draw.text(function (add) {
if (lineList) {
for (var i = 0; i < lineList.length; i++) {
add.tspan(lineList[i].text).attr("x", "50%").newLine();
}
}
}).font({
family: tAsset.fontFamily,
size: tAsset.fontHeight,
leading: '1.2em',
anchor: "middle"
}).move(width / 2, 0);
return draw.svg();
}

This link might be helpful: http://techslides.com/save-svg-as-an-image
This documents a client side solution that causes the requisite SVG to be drawn on the end user's browser, rather than on the server, but it provides the end result you want by putting the SVG into an image tag and allowing the user to download it. If keeping the SVG drawing logic secret is a problem, you could use a similar principle by sicing PhantomJS on the generator page and sending the user the image it downloads.

Related

Present canvas interface in shared code on both server and client

I am trying to write shared code (that runs on both server and client) that uses an HTML canvas.
On the client, this should work perfectly fine. On the server, Node doesn't have a canvas (or a DOM), so I'd like to use the node-canvas plugin: https://github.com/Automattic/node-canvas.
However, I can't work out a way to access it that doesn't make webpack try to bundle node-canvas into my client-side code (which crashes webpack). Is there any way of loading node-canvas in such a way that I can reference it with the same code I'll use in the browser and without making webpack crash horribly?
My current effort, which did not work:
canvas.server.js
import Canvas from 'canvas';
const createCanvas = (width, height) => new Canvas(width, height);
export default createCanvas;
canvas.client.js
const createCanvas = (width, height) => {
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
return canvas;
};
export default createCanvas;
canvas.js
let createCanvas;
if (typeof document === 'undefined') {
// SERVER/node
createCanvas = require('./canvas.server.js');
} else {
// BROWSER
createCanvas = require('./canvas.client.js');
}
export default createCanvas;
in use:
import createCanvas from './canvas';
const canvasElement = createCanvas(width, height);
const ctx = canvasElement.getContext('2d');
Unfortunately, webpack still bundles in node-canvas.
Did you try requiring node-canvas only when the code is running in node?
If you do not actually call the require in front-end code, webpack will not bundle it. This means calling the actual require inside aforementioned conditional statement and not at the top of your file. This is important. Also, verify that you did not put node-canvas as an entry point in webpack.
Example:
// let's assume there is `isNode` variable as described in linked answer
let canvas;
if (isNode) {
const Canvas = require('canvas');
canvas = new Canvas(x, y);
else {
canvas = document.getElementById('canvas');
}
// get canvas context and draw on it
Edit after OP provided code example:
I've reproduced the exact structure in this WebpackBin to prove this should be working as explained above. After all, this is a feature of common.js (and other module loaders) and is therefore supported in webpack.
My changes to the code:
Replaced the code in canvas.client.js and canvas.server.js with console.log of what would be called at that line
Fixed wrong use of require with export default (should be require(...).default). Irrelevant, but had to do it to make the code work.
Removed the canvasElement.getContex call. Would not work in the example code and is irrelevant anyway, so there is no point of mocking it.

any code make sure json fully added to canvas?

var json = [];
json.push(json2);
function makeallImage(){
console.log('json length'+json.length);
for (var v = 0; v < json.length; v++){
convertImgToBase64(v, "jpg");
console.log("ksana"+v);
}
}
function convertImgToBase64(number, outputFormat){
var tmpData =
canvas.loadFromJSON(json[number], canvas.renderAll.bind(canvas), function(){
**//need to absolute comfirm it add all object in canvas, load complete json2 //**
canvas.on('object:added', function(e) {
toImg();
});
});
}
function toImg(outputFormat){
var s = document.getElementById("last_Image");
var url = canvas.toDataURL();
var newImg = document.createElement("img"); // create img tag
console.log(newImg);
newImg.src = url;
newImg.width = 100;
newImg.height = 100;
s.appendChild(newImg);
console.log('mpike sto dom');
}
i am using this code to create image to field , problem is if my json object contain image ,it will create empty image. so i figure it out is because loading the src need time and canvas create image before it fully load.
i need to make sure the json fully loaded on canvas first , so i found a fabric code call object:added , which can make sure object added in canvas , but it count object one by one , so if my json cotain 2 object it will create more image.
achievement
1. i need to make sure my json fully load or create in canvas before create image , is they any way to make sure json fully added to canvas?
Demo see my problem using object:added it load multiple image.
You should dump reviver and use just the callback function.
http://jsfiddle.net/v1nmtz02/2/
You will have some difficulties with fabricImages and objects that have a content that is async. That is not yet solved at library level.
function _callback() {
canvas.renderAll();
toImg();
}
function convertImgToBase64(number, outputFormat){
var tmpData = canvas.loadFromJSON(json[number], _callback);
}
Complete snippet:
var canvas = new fabric.Canvas('canvas');
var json2 = '{"objects":[{"type":"circle","originX":"center","originY":"center","left":300,"top":400,"width":200,"height":200,"fill":"rgb(166,111,213)","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":{"color":"#5b238A","blur":20,"offsetX":-20,"offsetY":-10},"visible":true,"clipTo":null,"radius":100},{"type":"rect","originX":"center","originY":"center","left":300,"top":500,"width":150,"height":150,"fill":"#fbb802","overlayFill":null,"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":{"color":"rgba(94, 128, 191, 0.5)","blur":5,"offsetX":10,"offsetY":10},"visible":true,"clipTo":null,"rx":0,"ry":0,"x":0,"y":0}],"background":""}';
var json = [];
json.push(json2);
function makeallImage(){
for (var v = 0; v < json.length; v++){
convertImgToBase64(v, "jpg");
}
}
function _callback() {
canvas.renderAll();
toImg();
}
function convertImgToBase64(number, outputFormat){
var tmpData = canvas.loadFromJSON(json[number], _callback);
}
function toImg(outputFormat){
var s = document.getElementById("last_Image");
var url = canvas.toDataURL();
var newImg = document.createElement("img");
newImg.src = url;
newImg.width = 100;
newImg.height = 100;
s.appendChild(newImg);
}
<script src="http://fabricjs.com/lib/fabric.js"></script>
<canvas id='canvas' width="550" height="550" style="border:#000 1px solid;"></canvas>
<button onclick="makeallImage();">makepng</button>
<div id="last_Image" style="background:red"></div>

Raphael.js path to SVG

I have seen SVG images on wikipedia which you can open in notepad and find the code written inside it. My question is if I make a circle in raphael, can I display it as an svg image in the browser?
var p = paper.circle(10,10,10).attr({fill:'blue'});
then display it as a svg image in my browser. How can I achieve it?
This would only work on browsers that support SVG. I think it fails on IE9 too because it doesn't provide support for .serializeToString() (though there are shims for this).
window.onload = function () {
var paper = Raphael("container", 100, 100);
var p = paper.circle(10,10,10).attr({fill:'blue'});
var textarea = document.getElementById("code")
var serializer = new XMLSerializer();
textarea.value = serializer.serializeToString(paper.canvas);
};​
See demo here: http://jsfiddle.net/BvWkU/
window.onload = function () {
var paper = Raphael("container", 100, 100);
var p = paper.circle(10,10,10).attr({fill:'blue'});
var textarea = document.getElementById("code")
var serializer = new XMLSerializer();
textarea.value = serializer.serializeToString(paper.canvas);
};​

Reading a PNG image in Node.js

Is there an easy way in Node.js to read a PNG file and get the pixels of the image? Something like node-image, but the other way :)
I went through the libraries listed at https://github.com/joyent/node/wiki/modules#wiki-graphics, but they are either simple wrappers around command line tools providing cropping and resizing or complex drawing tools like node-canvas.
This one does both PNG decoding and encoding without native dependancies:
pngjs - PNG encoder/decoder for Node.js with no native dependencies.
An example for inverting the colors of a PNG:
var fs = require('fs'),
PNG = require('pngjs').PNG;
fs.createReadStream('in.png')
.pipe(new PNG())
.on('parsed', function() {
for (var y = 0; y < this.height; y++) {
for (var x = 0; x < this.width; x++) {
var idx = (this.width * y + x) << 2;
// invert color
this.data[idx] = 255 - this.data[idx]; // R
this.data[idx+1] = 255 - this.data[idx+1]; // G
this.data[idx+2] = 255 - this.data[idx+2]; // B
// and reduce opacity
this.data[idx+3] = this.data[idx+3] >> 1;
}
}
this.pack().pipe(fs.createWriteStream('out.png'));
});
I was about to became mad searching, but I found one:
png.js ― A PNG decoder in JS for the canvas element or Node.js.
var PNG = require('png-js');
var myimage = new PNG('myimage.png');
var width = myimage.width;
var height = myimage.height;
myimage.decode(function (pixels) {
//Pixels is a 1D array containing pixel data
});
Please note it's pure JavaScript. Works both in the browser <canvas> and in Node.JS.
There are more properties apart from width and height, see this source.
I think
var myimage = new PNG('myimage.png');
should be
var myimage = new PNG.load('myimage.png');

Image not saving on a Palm device

Updated: webOS version 2.1...
This base64 encoded image data generates the correct data image when I append it to the source of an image, like this:
var img = new Image();
img.src= data
var data = "data:image/png;base64,iVBORw0KGgoAAAANSUh
EUgAAAJYAAACmCAIAAAC3GeEYAAEkgklEQVR4AQD9/wIAADt8Fj5/GUSA IESAIEN/GUd/H0V+IEaEIE
WFHUOEHEqJIE2KIk2KI1GQKFSQLFaQKlaOKVaQKlORLlaYLVaVKFWV KVWUKliWKFiXJlKVIliTJW2oP
m6jOW+kPGqkPmehPWWePWagOmmjP2ykQ2ulQmylRWykQmqmP2qr QGqnP26qSGyvRmquQWyyQGquP2yu
RHSzSHWwSXGxSGytRG+vSG6vSW2vRWquRGqtRGmsQnO1R3Gw SG+rSXavUXWwUnKqR3CuRWquP26zQ3C
yRXK0SHG0SWupR2qoR3CuS2qrQ3CsSG6vS22pR26qSGyq RWetO22uQ2yqP22wRGetP2yyP4TEWgElAB
UrBRYmAx05AidHBB9MCydRDylSGChWGCZUFyFLEyNK Ex5IDBtJBhc/Bx9FDBxDDh5HDyRGExs8DRs4D
B04DRw8Exo6DxMuBw8kAhEeABIYAQ4VABAUAA0S AAwVAg8bAw0bAgwaAxAYAAULAQgQAQcQBQsPAAwQ
AggMAwMLAQAIAAgOBAYOAAsWBg4bChMgDxUk DxcmERopEh8vFBwuExspEhcnDxUpDhcqERUnDhUnDRQ
rDxgsERgvEx8xGQA+fxk7gxU9hBc9ghg/ gR1CgBxBhBtChRxIhyFMiyNMiyNNjiZNiypRkCpSjydRkC
VVkSpTkihYmi9YlC9XlCxVlClYlixW lSpZlS1eli16skJnqDxppj1qpDxmpD9mpD1loj1opz9qqENvq
Udpp0FmqD9npkFtpUVvp0ZvrUVs q0NsrEFtrURsrkBrsT9vskFvrj5srz5ssUJsrkJsrkNtr0NusEVm
qjxrrz5ttkNquEFqtEFu"
I am trying to save the image using my custom service, but it does not save the correct image. Here is the Node.js code for saving the image:
var fs = IMPORTS.require('fs');
var path = IMPORTS.require('path');
var buff = new Buffer(img.substr('data:image/png;base64,'.length), 'base64');
path.exists('/media/internal/wallpapers/', function(exists){
if (exists) {
var id = fs.openSync('/media/internal/wallpapers/i.png', 'w', 666);
var written = fs.writeSync(id, buff,0, buff.length, 0);
fs.closeSync(id);
}
});
The saved version of the image has totally different pixel values.
EDIT
I came to find out that the image data above isn't correct. I am using a PNG library to generate base64 image data of a canvas pixel array. The link is http://www.xarg.org/2010/03/generate-client-side-png-files-using-javascript/.
That is an alternative to canvas.toDataURL();. webOS does not support toDataURL, so I had to use a library.
Here is the code I have used with this library to manipulate my canvas image data as a pixel array:
EditorAssistant.prototype.getDataURL = function(width,height,pixelArray) {
var p = new PNGlib(height, width, 256); // Construcor takes height, weight and color-depth.
var background = p.color(0, 0, 0, 0);
var k = 0;
for (var j = 0; j<height; j++) {
for (var i =0; i<width; i++) {
var x =i;
var y =j;
p.buffer[p.index(x,y)] = p.color(pixelArray[k], pixelArray[k+1], pixelArray[k+2]);
k+=4;
}
}
return 'data:image/png;base64,'+p.getBase64() ;
}
Does this library work and where am I doing it wrong?
libpng.js only supports 256 color images, so that may be the problem. There are other base64 encoding utilities which may work as expected.

Resources