Cleaned up and made to a module

This commit is contained in:
2016-01-18 16:04:56 +08:00
parent d9483dc4d7
commit ed1e415666
14 changed files with 470 additions and 209 deletions
-5
View File
@@ -1,5 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="0" y="-256" width="1024" height="768" xlink:href="panels.svg" />
</svg>

Before

Width:  |  Height:  |  Size: 241 B

-11
View File
@@ -1,11 +0,0 @@
<svg width="256" height="256" viewBox="0 0 256 256" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="main" >
<foreignObject x="-512" y="-512" width="1024" height="768" xmlns="http://www.w3.org/2000/svg">
<iframe x="0" y="0" width="100%" height="100%" src="panels.svg" xmlns="http://www.w3.org/1999/xhtml" >
</iframe>
</foreignObject>
</svg>

Before

Width:  |  Height:  |  Size: 435 B

-5
View File
@@ -1,5 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="-512" y="-256" width="1024" height="768" xlink:href="./panels.svg" />
</svg>

Before

Width:  |  Height:  |  Size: 246 B

-5
View File
@@ -1,5 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="-256" y="-256" width="1024" height="768" xlink:href="panels.svg" />
</svg>

Before

Width:  |  Height:  |  Size: 244 B

-5
View File
@@ -1,5 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="-768" y="-256" width="1024" height="768" xlink:href="panels.svg" />
</svg>

Before

Width:  |  Height:  |  Size: 244 B

-5
View File
@@ -1,5 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 256 256" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<image x="-512" y="0" width="1024" height="768" xlink:href="panels.svg" />
</svg>

Before

Width:  |  Height:  |  Size: 241 B

+8 -7
View File
@@ -1,20 +1,21 @@
{
"name": "gen-svg-cube",
"version": "0.0.5",
"description": "Render and download svg cubes using webdriver",
"main": "render.js",
"name": "svg2cube",
"version": "0.0.6",
"description": "Fold a svg panel into a cube and take images at isometric angles",
"main": "svg2cube.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node render.js svgCube.html",
"debug": "NODE_DEBUG=request,webdriver,chromedriver DEBUG=true node render.js svgCube.html"
"start": "node svg2cube.js inputs/panels.svg",
"debug": "NODE_DEBUG=request,webdriver,chromedriver DEBUG=true node svg2cube.js inputs/panels.svg"
},
"repository": "git@gitlab.com:wassname/svg2Cube.git",
"author": "wassname@wassname.org",
"private": true,
"license": "ISC",
"license": "MIT",
"dependencies": {
"chromedriver": "^2.20.0",
"fs": "0.0.2",
"gm": "^1.21.1",
"jquery": "^2.2.0",
"path": "^0.12.7",
"system": "^1.0.4",
+11 -12
View File
@@ -1,40 +1,39 @@
gen-svg-cube
This package makes isometric cubes. It takes in svg's and renders them from a given side
at a given resolution.
This package makes isometric cubes. It takes in svg's and renders them from a given side at a given resolution.
# Quickstart
TODO
# Screenshots
## Input:
<img src="images/input.png" style="max-width: 20em;"></img>
## Output:
<img src="images/result.png" style="max-width: 20em;"></img>
## GUI
<img src="images/gui.png" style="max-width: 20em;"></img>
# Installation
`npm i`
# Usage
From the command line:
`npm start`
```sh
nde svg2cube-cli.js inputs/panels.svg
```
# TODO
Or in node:
```js
var svg2cube = require('./svg2cube.js');
svg2cube('inputs/panels.svg',{rotateY: 45, size:256});
```
# Author
wassname.org
# License
ISC
MIT
-128
View File
@@ -1,128 +0,0 @@
'use strict';
/**
* Node js script to render and download svg cubes using webdriver
*/
var webdriverio = require('webdriverio');
var path = require('path');
var globby = require('globby');
var gm = require('gm');
var SvgCube = require('./SvgCube.js');
// var $ = require('jquery');
var chromedriver = require('chromedriver');
var childProcess = require('child_process');
// get inputs
if (process.argv.length < 3 || process.argv.length > 4) {
console.log('Command: ', process.argv);
console.log('Usage: node rasterize.js svgCube.html panel.svg');
return;
} else {
var input = process.argv[2];
var outfile = process.argv[3];
console.log('input:', input);
}
// see if we are in debug mode
var debug = process.env.DEBUG || false;
// start server chromedriver for selenium
var binPath = chromedriver.path;
var childArgs = ['--url-base=/wd/hub', '--whitelisted-ips="*"'];
if (debug){childArgs.push('--verbose');}
var chromeInstance = childProcess.execFile(binPath, childArgs, function (err, stdout, stderr) {
if (err) {
console.error('[webdriver]', err, stdout, stderr);
} else {
console.log('[webdriver]', stdout, stderr);
}
});
// define client
var options = {
host: "localhost",
port: 9515,
desiredCapabilities: {
browserName: 'chrome',
chromeOptions: {
binary: '/usr/bin/chromium'
}
}
};
var client = webdriverio.remote(options);
var bounds;
// get input file and components
var file = input;
var address = path.join(process.cwd(), file);
var ext = path.extname(file);
var url = 'file://' + path.join(process.cwd(), file);
var outfile = outfile? outfile:address.replace(ext, '.png');
console.info('Converting ', file, url, '->', outfile);
// start client
client.init()
.url(url)
// inject code into page
.execute(function () {
var cube1, text;
cube1 = new SvgCube.SvgCube({
rotateX: 45,
svgPanel: 'inputs/panels.svg',
clipCircle: false,
stroke: {
'stroke': 'black', // stroke color for outline
'stroke-width': 0, // outline width
},
size: 444,
});
text = cube1.getBounds();
// Get dimensions of each pane and make it accesable to webdriver
$('#dimensions').attr('value', 1);
$('#dimensions').text(JSON.stringify(text));
})
.waitForVisible('.front', 5000)
// get image boundries from html
.execute(function () {
return $('#dimensions').text();
})
.then(text => {
console.info('[svg2Cube] dimensions', text);
try {
bounds = JSON.parse(text.value);
} catch (e) {
console.warn(text);
}
})
// take a screen shot crop using graphics magic
.screenshot()
.then(res => {
var imgBuffer = new Buffer(res.value, 'base64');
/** Crop it using graphicks magic */
gm(imgBuffer)
.crop(
bounds.right.max - bounds.left.min,
bounds.bottom.max - bounds.top.min,
bounds.left.min,
bounds.top.min
)
.write(outfile, function (err) {
if (!err) {console.log('done');}
});
})
.end()
.then(function(){
// close the browser server
if (chromeInstance !== null){
chromeInstance.kill();
}
});
+13
View File
@@ -0,0 +1,13 @@
/** command line interface for svg2cube. Usage `node svg2cube panel.svg` **/
var svg2cube = require('./svg2cube.js');
if (process.argv.length < 3 || process.argv.length > 4) {
console.log('Command: ', process.argv);
console.log('Usage: node rasterize.js panel.svg');
return;
} else {
var input = process.argv[2];
var outfile = process.argv[3];
console.log('input:', input, 'output:', outfile);
}
svg2cube(input,outfile);
+302
View File
@@ -0,0 +1,302 @@
'use strict';
/**
* Frontend js file to generate an cube of svg's
*/
(function (exports) {
exports.SvgCube = function (svgPanel, options) {
// Inputs and options
var defaultOptions = {
rotateX: 30, // isometric angle
rotateY: 45,
rotateZ: 0,
perspective: 0, // doesn't do anything usefull
scaleX: 1.00,
scaleY: 1.00, // flatten
scaleZ: 1.00, // push face
size: 400,
verbose: false,
// outline
drawOutline: false,
drawShading: false,
borderRadius: 0,
stroke: {
"stroke": 'black', // stroke color for outline
"stroke-width": 0, // outline width
},
// cube
topRot: 0, // rotation of top image in degrees
topShad: 0, // shading for top
leftRot: 0,
leftShad: 0.0,
rightRot: 0,
rightShad: 0.0,
backRot: 0,
backShad: 0.0,
bottomRot: 0,
bottomShad: 0.0,
frontRot: 0,
frontShad: 0.0,
};
// add defaults, 2 levels deep
options = options || {};
for (var opt in defaultOptions) {
if (defaultOptions.hasOwnProperty(opt) && !options.hasOwnProperty(opt)) {
options[opt] = defaultOptions[opt];
}
for (var opt2 in defaultOptions[opt]) {
if (defaultOptions[opt].hasOwnProperty(opt2) && !options[opt].hasOwnProperty(opt2)) {
options[opt][opt2] = defaultOptions[opt][opt2];
}
}
}
options.svgPanel = svgPanel;
this.options = options;
console.log(svgPanel);
// legacy compat
if (options.flatten !== undefined) {
options.scaleY = 1 - options.flatten;
}
if (options.angle !== undefined) {
options.rotateX = options.angle;
}
if (!options.drawOutline) {
options.stroke['stroke-width'] = 0;
}
this.init();
};
exports.SvgCube.prototype.init = function () {
this.rotateX = this.options.rotateX;
this.w = this.options.size; // input image width
this.h = this.options.size;
this.f = 1 - this.options.scaleY;
this.rot = this.rotateX * Math.PI / 180;
this.padding = this.options.padding || 0; // pading fraction
this.cw = this.w; // we will keep same width but change height
this.ch = this.h * 5; //(this.h + Math.sqrt(2)*this.h * Math.tan(this.rot)) - this.h / 2 * (this.f); //canvas height full
// create SVG element
var o = this.options;
/** Write sides if they have not already been written **/
if ($('body>.cube').length === 0) {
var cube = $('<div class="cube cube2"></div>');
var imageFront = $('' +
'<b width="256" height="256" class="front tint">' +
'<svg class="face" width="100%" height="100%" viewBox="0 0 256 256" version="1.1"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink">' +
' <image x="-512" y="-256" width="1024" height="768" xlink:href="' + o.svgPanel + '" />' +
'</svg>' +
'</b>');
cube.append(imageFront);
var imageL = $('' +
'<b width="256" height="256" class="left tint">' +
'<svg class="face" width="100%" height="100%" viewBox="0 0 256 256" version="1.1"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink">' +
' <image x="-256" y="-256" width="1024" height="768" xlink:href="' + o.svgPanel + '" />' +
'</svg>' +
'</b>');
cube.append(imageL);
var imageRight = $('' +
'<b width="256" height="256" class="right tint">' +
' <svg class="face" width="100%" height="100%" viewBox="0 0 256 256" version="1.1"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink">' +
' <image x="-768" y="-256" width="1024" height="768" xlink:href="' + o.svgPanel + '" />' +
' </svg>' +
'</b>');
cube.append(imageRight);
var imageTop = $('' +
'<b width="256" height="256" class="top tint">' +
'<svg class="face" width="100%" height="100%" viewBox="0 0 256 256" version="1.1"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink">' +
' <image x="-512" y="0" width="1024" height="768" xlink:href="' + o.svgPanel + '" />' +
'</svg>' +
'</b>');
cube.append(imageTop);
var imageBack = $('' +
'<b width="256" height="256" class="back tint">' +
'<svg class="face" width="100%" height="100%" viewBox="0 0 256 256" version="1.1"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink">' +
' <image x="0" y="-256" width="1024" height="768" xlink:href="' + o.svgPanel + '" />' +
'</svg>' +
'</b>');
cube.append(imageBack);
var imageBottom = $('' +
'<b width="256" height="256" class="bottom tint">' +
'<svg class="face" width="100%" height="100%" viewBox="0 0 256 256" version="1.1"' +
' xmlns="http://www.w3.org/2000/svg"' +
' xmlns:xlink="http://www.w3.org/1999/xlink">' +
' <image x="0" y="0" width="1024" height="768" xlink:href="' + o.svgPanel + '" />' +
'</svg>' +
'</b>');
cube.append(imageBottom);
$('body').append(cube);
}
// Now we generate some css to put everything in good positions
var transitions = 0.1;
var styleStr = '' +
'<style id="projection"> ' +
' .cube { ' +
' height: ' + this.ch + 'px; ' +
' width: ' + this.cw + 'px; ' +
' } ' +
' .face { ' +
' height: ' + o.size + 'px; ' +
' width: ' + o.size + 'px; ' +
' } ' +
' .cube { ' +
' position: absolute; ' +
' -webkit-transform: translate(' + this.cw / 2 + 'px,' + 0 * this.ch / 2 + 'px) perspective(-' + o.perspective + 'px) rotateX(-' + o.rotateX + 'deg) rotateY(' + o.rotateY + 'deg) rotateZ(' + o.rotateZ + 'deg) scaleX(' + o.scaleX + ') scaleY(' + o.scaleY + ') scaleZ(' + o.scaleZ + '); ' +
' -webkit-transform-style: preserve-3d; ' +
' -webkit-transition: ' + transitions + 's; ' +
' } ' +
' .back { ' +
' transform: translateZ(-' + o.size / 2 + 'px) rotateY(180deg); ' +
' } ' +
' .right { ' +
' transform: rotateY(-270deg) translateX(' + o.size / 2 + 'px); ' +
' transform-origin: center right; ' +
' } ' +
' .left { ' +
' transform: rotateY(270deg) translateX(-' + o.size / 2 + 'px); ' +
' transform-origin: center left; ' +
' } ' +
' .top { ' +
' transform: rotateX(-90deg) translateY(-' + o.size / 2 + 'px); ' +
' transform-origin: top center; ' +
' } ' +
' .bottom { ' +
' transform: rotateX(90deg) translateY(' + o.size / 2 + 'px); ' +
' transform-origin: bottom center; ' +
' } ' +
' .front { ' +
' transform: translateZ(' + o.size / 2 + 'px); ' +
' } ' +
' /* custom orientation/rotation settings for each image */ ' +
' .back>svg{ ' +
' transform: rotate(' + o.backRot + 'deg); ' +
' } ' +
' .front>svg{ ' +
' transform: rotate(' + o.frontRot + 'deg); ' +
' } ' +
' .right>svg{ ' +
' transform: rotate(' + o.rightRot + 'deg); ' +
' } ' +
' .left>svg{ ' +
' transform: rotate(' + o.leftRot + 'deg); ' +
' } ' +
' .top>svg{ ' +
' transform: rotate(' + 90 + o.topRot + 'deg); ' +
' } ' +
' .bottom>svg{ ' +
' transform: rotate(' + o.bottomRot + 'deg); ' +
' } ' +
' b{ ' +
' position:absolute; ' +
' transition: all ' + transitions + 's linear; ' +
' } ' +
' /* outline */ ' +
' .face { ' +
' box-sizing: border-box; ' +
' border: ' + o.stroke['stroke-width'] + 'px solid ' + o.stroke.stroke + '; ' +
' } ' +
' /* shade in sides */ ' +
' .wrap { ' +
' overflow: hidden; ' +
' width: ' + o.size + 'px; ' +
' margin: 0 auto; ' +
' } ' +
' .tint { ' +
' position: absolute; ' +
' } ' +
' .tint:before { ' +
' content: ""; ' +
' display: block; ' +
' position: absolute; ' +
' top: 0; ' +
' bottom: 0; ' +
' left: 0; ' +
' right: 0; ' +
' } ' +
' .tint:hover:before { background: none; } ' +
' .tint.top:before { background: rgba(0,0,0, ' + o.topShad + ');} ' +
' .tint.left:before { background: rgba(0,0,0, ' + o.leftShad + ');} ' +
' .tint.right:before { background: rgba(0,0,0, ' + o.rightShad + ');} ' +
' .tint.back:before { background: rgba(0,0,0, ' + o.backShad + '); } ' +
' .tint.front:before { background: rgba(0,0,0, ' + o.frontShad + '); } ' +
' .tint.bottom:before { background: rgba(0,0,0, ' + o.bottomShad + '); } ' +
' /* curved cube. Need something block seeing through, and also extra faces, 1 px in, so inside looks uniform color. Only work for one main color */ ' +
' /*.face { ' +
' border-radius: ' + o.borderRadius + 'px; ' +
' } ' +
' .mid { ' +
' background-color: #e3e2db; /* make stroke color TODO */ ' +
' border-radius: 0px; ' +
' }*/ ' +
' </style>';
$('head>#projection').remove();
$('head').append($(styleStr));
};
/**
* Get the bounds of the images for a screenshot
* uses $.position to get min,max of each side of the image
* @return {object} object.dimension.[min|max] e.g. object.left.min
*/
exports.SvgCube.prototype.getBounds = function () {
var bounds = {};
$('.cube>b').each(function () {
var pos = this.getBoundingClientRect();
for (var dim in pos) {
if (dim in pos) {
// init
if (bounds[dim] === undefined) {
bounds[dim] = {
'max': pos[dim],
'min': pos[dim]
};
} else {
// get max and min
bounds[dim].max = Math.max(bounds[dim].max, pos[dim]);
bounds[dim].min = Math.min(bounds[dim].min, pos[dim]);
}
}
}
});
return bounds;
};
exports.SvgCube.prototype.update = function () {
this.init();
console.log(this.getBounds());
};
})(typeof exports === 'undefined' ? this['SvgCube'] = {} : exports);
Executable
+131
View File
@@ -0,0 +1,131 @@
'use strict';
/**
* Node js script to render and download svg cubes using webdriver
*/
var webdriverio = require('webdriverio');
var path = require('path');
var gm = require('gm');
var chromedriver = require('chromedriver');
var childProcess = require('child_process');
var SvgCube = require('./svgcube.js');
var debug = process.env.DEBUG || false;
const converterFileName = 'file://'+path.resolve(__dirname, "./svgCube.html");
console.log(converterFileName);
const binPath = chromedriver.path;
var childArgs = ['--url-base=/wd/hub', '--whitelisted-ips="*"'];
if (debug) {
childArgs.push('--verbose');
}
/**
* Convert an svg panel with 6 sides into a image of the folded cube. The out
* images are png.
* @param {string} svgPanel file name of svgpanel
* @param {string} outfile output filename
* @param {object} options See svgCube.js for full options
* @return {undefined}
*/
module.exports = function (svgPanel, outfile, options) {
// start server chromedriver for selenium
var chromeInstance = childProcess.execFile(binPath, childArgs, function (err, stdout, stderr) {
if (err) {
console.error('[webdriver]', err, stdout, stderr);
} else {
console.log('[webdriver]', stdout, stderr);
}
});
// define client
var webdriverOptions = {
host: "localhost",
port: 9515,
desiredCapabilities: {
browserName: 'phantonjs',
}
};
var client = webdriverio.remote(webdriverOptions);
var bounds;
// get input file and components
var address = path.join(process.cwd(), svgPanel);
var ext = path.extname(svgPanel);
outfile = outfile ? outfile : address.replace(ext, '.png');
svgPanel = 'file://'+path.resolve(__dirname,svgPanel);
console.info('Converting ', svgPanel, '->', outfile);
options = options ? options: {};
// start client
client.init()
.windowHandleMaximize()
.getViewportSize()
.then(function(size) {
// set a reasonable size based on viewport size
var minSize = Math.min(size.width, size.height)/2;
if (!options.size){
options.size = minSize;
} else if (options.size && options.size > minSize){
console.warn('Pane size '+options.size+' to big for viewport '+size+', setting to '+minSize);
options.size = minSize;
}
})
.url(converterFileName)
// inject code into page
.execute(function (svgPanel,options) {
var cube1 = new SvgCube.SvgCube(svgPanel, options);
return cube1.getBounds();
},svgPanel,options)
.then(text => {
// rendered dimensions are returned
console.info('[svg2Cube] dimensions', text);
bounds = text.value;
})
// take a screen shot crop using graphics magic
.screenshot()
.then(res => {
var imgBuffer = new Buffer(res.value, 'base64');
/** Crop it using GraphicsMagick */
gm(imgBuffer)
.crop(
bounds.right.max - bounds.left.min,
bounds.bottom.max - bounds.top.min,
bounds.left.min,
bounds.top.min
)
.write(outfile, function (err) {
if (!err) {
console.log('done');
}
});
})
.end()
.then(function () {
// close the browser server
if (chromeInstance !== null) {
chromeInstance.kill();
}
});
};
// get inputs
if (process.argv.length < 3 || process.argv.length > 4) {
console.log('Command: ', process.argv);
console.log('Usage: node rasterize.js panel.svg');
return;
} else {
var input = process.argv[2];
var outfile = process.argv[3];
console.log('input:', input, 'output:', outfile);
}
module.exports(input,outfile);
+3 -23
View File
@@ -1,40 +1,20 @@
<!-- Non gui version of svgCube_gui.html for webdriver converions to svg -->
<!-- Empty html page to load client side scripts. It's then used by webdrive to insert and render -->
<html>
<head>
<meta charset="utf-8">
<title>svg2Cube</title>
</head>
<body>
<div style="display: none;" id="dimensions">
</input>
</div>
</body>
<script type="text/javascript" src="node_modules/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="SvgCube.js"></script>
<script type="text/javascript" src="svg2cube-frontend.js"></script>
<script>
// var cube1
// window.onload = function() {
// cube1 = new SvgCube.SvgCube({
// rotateX: 45,
// svgPanel: 'inputs/panels.svg',
// clipCircle: false,
// stroke: {
// "stroke": 'black', // stroke color for outline
// "stroke-width": 0, // outline width
// },
// size: 444,
// });
// var text = cube1.getBounds();
//
// // Get dimensions of each pane and make it accesable to webdriver
// $('#dimensions').attr('value', 1)
// $('#dimensions').text(JSON.stringify(text))
// }
</script>
</html>
+2 -3
View File
@@ -21,7 +21,7 @@
<script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="projectSVG.js"></script>
<script src="svg2cube-frontend.js"></script>
<script>
var cube1
@@ -35,9 +35,8 @@
window.onload = function() {
cube1 = new SvgCube.SvgCube({
cube1 = new SvgCube.SvgCube('inputs/panels.svg', {
rotateX: 45,
svgPanel: 'inputs/panels.svg',
clipCircle: false,
stroke: {
"stroke": 'black', // stroke color for outline