commit 4fd737e3e1df5ed979a4850f149c9f212ffd2b55 Author: Is Isilon Date: Sun Nov 15 10:08:32 2015 +0800 init diff --git a/2c_css_svgs.css b/2c_css_svgs.css new file mode 100644 index 0000000..271b9f1 --- /dev/null +++ b/2c_css_svgs.css @@ -0,0 +1,43 @@ + +.grass { + background-image: url(2c_css_svgs.png); + background-position: 0px 0px; + width: 256px; + height: 256px; +} + +.manual_good_30 { + background-image: url(2c_css_svgs.png); + background-position: 0px -256px; + width: 1128px; + height: 1128px; +} + +.manualcss_v2 { + background-image: url(2c_css_svgs.png); + background-position: 0px -431px; + width: 1128px; + height: 1128px; +} + +.manualcss_v2c { + background-image: url(2c_css_svgs.png); + background-position: 0px -606px; + width: 1128px; + height: 1128px; +} + +.manualcss_v2d { + background-image: url(2c_css_svgs.png); + background-position: 0px -1734px; + width: 1128px; + height: 1128px; +} + +.manuallcss_2b { + background-image: url(2c_css_svgs.png); + background-position: 0px -2862px; + width: 1128px; + height: 1128px; +} + diff --git a/back.svg b/back.svg new file mode 100644 index 0000000..e1b67bc --- /dev/null +++ b/back.svg @@ -0,0 +1,2384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/bottom.svg b/bottom.svg new file mode 100644 index 0000000..e1b67bc --- /dev/null +++ b/bottom.svg @@ -0,0 +1,2384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..5d62050 --- /dev/null +++ b/bower.json @@ -0,0 +1,16 @@ +{ + "name": "2c_css_svgs", + "description": "", + "main": "", + "moduleType": [], + "license": "Unlicences", + "homepage": "", + "private": true, + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/convert.sh b/convert.sh new file mode 100644 index 0000000..b595bcd --- /dev/null +++ b/convert.sh @@ -0,0 +1,6 @@ +cairosvg manual_good_30.svg -o manual_good_30.png + + +for i in *.svg; do cairosvg $i -o `echo $i | sed -e 's/\.svg$/1.png/'`; done +for i in *.svg; do rsvg-convert -a $i -o `echo $i | sed -e 's/\.svg$/2.png/'`; done +for i in *.svg; do phantomjs rasterise.js $i `echo $i | sed -e 's/\.svg$/3.png/'`; done diff --git a/front.svg b/front.svg new file mode 100644 index 0000000..6c383d5 --- /dev/null +++ b/front.svg @@ -0,0 +1,2469 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/grass.png b/grass.png new file mode 100644 index 0000000..14c5c7d Binary files /dev/null and b/grass.png differ diff --git a/grass.svg b/grass.svg new file mode 100644 index 0000000..1a59791 --- /dev/null +++ b/grass.svg @@ -0,0 +1,2612 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/left.svg b/left.svg new file mode 100644 index 0000000..b87a0ff --- /dev/null +++ b/left.svg @@ -0,0 +1,2439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/manual_good_30.png b/manual_good_30.png new file mode 100644 index 0000000..cbbdff9 Binary files /dev/null and b/manual_good_30.png differ diff --git a/manual_good_30.svg b/manual_good_30.svg new file mode 100644 index 0000000..2991222 --- /dev/null +++ b/manual_good_30.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + diff --git a/manualcss2.png b/manualcss2.png new file mode 100644 index 0000000..b577087 Binary files /dev/null and b/manualcss2.png differ diff --git a/manualcss2.svg b/manualcss2.svg new file mode 100644 index 0000000..6631cba --- /dev/null +++ b/manualcss2.svg @@ -0,0 +1,56 @@ + + https://en.wikipedia.org/wiki/Isometric_projection + + + + + + + + + + + diff --git a/projectSVG (3rd copy).js b/projectSVG (3rd copy).js new file mode 100644 index 0000000..33017ed --- /dev/null +++ b/projectSVG (3rd copy).js @@ -0,0 +1,457 @@ +'use strict'; + +try{ + var Snap = require('snapsvg'); +} catch(e) {}; +var SvgCube = function (options) { + + // Inputs and options + var defaultOptions = { + angle: 30, + size: 64, + verbose: false, + // outline + drawOutline: true, + drawShading: true, + clipCircle: false, + stroke: { + "arrow-end": 'none', + "stroke": 'black', // stroke color for outline + "stroke-width": Math.sqrt(options.size)/2, // outline width + "stroke-linecap": "round", + "stroke-linejoin": "round", + "fill": "none", + }, + // cube + flatten: 0, // fraction to vertically flatten the cube + topUrl: '', // url for image in top of cuve + topRot: 0, // rotation of top image in degrees + topShad: 0, // shading for top + leftUrl: '', + leftRot: 0, + leftShad: 0.1, + rightUrl: '', + rightRot: 0, + rightShad: 0.3, + svgNS: "http://www.w3.org/2000/svg", + padding: 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]; + } + } + } + this.options = options + + this.angle = options.angle + + this.w = options.size; // input image width + this.h = options.size; + this.f = options.flatten + + this.rot = this.angle * Math.PI / 180 + this.padding = options.padding; // pading fraction + + + this.cw = this.w; // we will keep same width but change height + this.ch = (1 + this.padding) * (this.h / 2 + this.h * Math.tan(this.rot)) -this.h/2*(1-this.f); //canvas height full + + // create SVG element + this.paper = Snap(this.cw, this.ch); + this.svg=this.paper.node + var o = this.options; + + var style = document.createElement('style'); + this.paper.defs.appendChild(style) + var styleStr = ` ` + console.log(styleStr); + style.innerHTML= styleStr + +} + +/* drawing measurements as a function of padding */ +SvgCube.prototype.measurements= function(p){ + if (p===undefined){ + p=0; + } + + var f = this.options.flatten + + var tBox = this.imageT.getBBox() + var lBox = this.imageL.getBBox() + var rBox = this.imageR.getBBox() + + return { + // measurements + uf : 1-f, + p : 0, // lw/2, // padding + + tw: this.cw-p/2, // right side. adjust by half line thickness to keep line in canvas + th: tBox.height-p/2, // height of square, and dist to middle + + mw: this.cw/2, // middle x + mh: tBox.height/2, // middle of top square + + bh: 0+p/2, // top of picture, bottom y + bw: 0+p/2, // left of picture, bottom of x + + sw: this.cw-p/2,// bottom of cube + sh: this.ch-p/2, // right of cube + + lq: -tBox.height/2+this.ch-p/2, // lower quarter of height + uq: tBox.height/2+p/2 // upper quarter + } +} + + +/* + * Adds a svg transform to an element, the transform has the origin of + * xi,yi fraction of the element, so 0.5,0.5 is the middle, + * unlike normalsvg it adds transforms in order of application not reverse order + * Usage: svgTransform(elementImage,'rotate',[45],0.5,0.5) + * This would rotate 45 degrees around center of image + */ +SvgCube.prototype.svgTransform = function (element, op, inputs, xi, yi) { + if (isNaN(xi)) { + xi = 0.5; + } + if (isNaN(yi)) { + yi = 0.5; + } + var svgBox = this.svg.getClientRects()[0] + // this.paper.getBBox() + var cbox = element.getBoundingClientRect(); + var x = cbox.left + xi * cbox.width -svgBox.left; + var y = cbox.top + yi * cbox.height -svgBox.top; + // + var matrix = this.svg.createSVGMatrix() + matrix = matrix.translate(x, y) + matrix = matrix[op].apply(matrix, inputs); + matrix = matrix.translate(-x, -y); + + var transform = this.svg.createSVGTransform(); + transform.setMatrix(matrix); + //element.transform.baseVal.appendItem(transform); // for reverse order + element.transform.baseVal.insertItemBefore(transform, 0) // normal order +} + +/* + * transform an element to be the left of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toLeft = function (element, angle, xi, yi) { + // half it's width + xi = 0 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -1]) // pixel adjustment HACK + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it, in degrees + this.svgTransform(element, 'skewY', [angle], xi, yi) + +} + +/* + * transform an element to be the right of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toRight = function (element, angle, xi, yi) { + xi = 1 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -2]) // pixel adjustment HACK + // half it's width to fiit in canvas + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it + this.svgTransform(element, 'skewY', [-angle], xi, yi) + +} + +/* + * transform an element to be the top of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toTop = function (element, angle, xi, yi) { + var rot = angle * Math.PI / 180; + this.svgTransform(element, 'translate', [-2, -1]) // pixel adjustment HACK + + // rotate so it's a diamond + this.svgTransform(element, 'rotate', [45], xi, yi) + // squish - along x axis to fit in canvas, along y axis for perspective change + this.svgTransform(element, 'scaleNonUniform', [Math.sin(45 * Math.PI / 180), Math.tan(rot) * Math.sin(45 * Math.PI / 180)], xi, yi) +} + +SvgCube.prototype.moveTop = function (element) { + // align top of cube with top of canvas + var cbox = element.getBoundingClientRect(); + this.svgTransform(element, 'translate', [-cbox.left + this.pPx, -cbox.top + this.pPx]) +} + +/* + * align left of cube with top, + * fit upper-left of left panel with middle-left of top panel + */ +SvgCube.prototype.moveLeft = function (elem, elemT) { + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + // align left + var x = cboxT.left - cboxL.left + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* + * align right of cube with top, + * fit upper-right of right panel with middle-right of top panel + */ +SvgCube.prototype.moveRight = function (elem, elemT) { + // line up left with top, move to half tops height, and to align left + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + + // align right with right + var x = cboxT.right - cboxL.right + + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawOutline = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(lw/2) + + + var tb = this.imageT.getBBox() + var lb = this.imageL.getBBox() + var rb = this.imageR.getBBox() + + // Draw outline of top + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + + // // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + // + // right + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + + // join into set + var pathGroup = this.paper.group(); + pathGroup.append(pathTop); + pathGroup.append(pathLeft); + pathGroup.append(pathRight); + + // set attrs from options + // ref http://raphaeljs.com/reference.html#Element.attr + var blackList = ['url','target','src','title'] + for (var a in this.options.stroke){ + if (this.options.stroke.hasOwnProperty(a) && blackList.indexOf(a)<0){ + pathGroup.attr(a,this.options.stroke[a]); + } + } + this.outline=pathGroup; +} + + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawShading = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(0); + var pathGroup = this.paper.g(); + + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + pathGroup.append(pathTop); + + // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + pathGroup.append(pathLeft); + + // last line from middle down + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + pathGroup.append(pathRight); + + + // style the set + pathGroup.attr({ + 'stroke': 'none', + 'fill': 'black', + 'stroke-width': 0, + 'stroke-opacity': 0, + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round' + }); + // shade each side, 0 is no shading, 1 is black + pathTop.attr({'fill-opacity': this.options.topShad}); + pathLeft.attr({'fill-opacity': this.options.leftShad}); + pathRight.attr({'fill-opacity': this.options.rightShad}); + this.shading=pathGroup; + +} + +/*clip the cube using an elipse to give rounded corners */ +SvgCube.prototype.clipCircle = function(amount){ + var cp = document.createElementNS("http://www.w3.org/2000/svg","clipPath") + cp.id="cp"; + var rxc=51+4*(1-this.f)*(1-this.f); + var ryc=50-2/Math.sqrt(1-this.f); + cp.innerHTML = '' + this.paper.node.getElementsByTagName("defs")[0].appendChild(cp); + this.paper.node.setAttribute("clip-path","url(#cp)"); +} + + +/* returns svg string */ +SvgCube.prototype.toSVG = function(){ + var svg3 = this.paper.toString(); + //var svg = this.paper.node.outerHTML; + //var svg2 = xmlserializer.serializeToString(this.paper.node); + if (this.paper.node.attributes.getNamedItem("clip-path")){ + // patch svg export to add clip + // HACK I have to add these manually to the export sadly as raphael.export doesn't handle them and also misses some recent change to canvas + svg3=svg3.replace(" + .cube, .cube .face, .cube .face * { + height: ${o.size}px; + width: ${o.size}px; + } + .cube { + position: absolute; + background-color: #f66; + + -webkit-transform: translate(${this.cw/2}px,${0*this.ch/2}px) perspective(${o.perspective}px) rotateX(${o.angle}deg) rotateX(${o.rotateX}deg) rotateY(${o.rotateY}deg) rotateZ(${o.rotateZ}deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + } + + + .cube * { + transform-origin: 0% 100%; + } + + .cube2 .top { + position: relative; + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(0deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + + } + .cube2 .left { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + position: absolute; + + } + .cube2 .right { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateY(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + position: absolute; + } + ` + console.log(styleStr); + style.innerHTML= styleStr + +} + +/* drawing measurements as a function of padding */ +SvgCube.prototype.measurements= function(p){ + if (p===undefined){ + p=0; + } + + var f = this.options.flatten + + var tBox = this.imageT.getBBox() + var lBox = this.imageL.getBBox() + var rBox = this.imageR.getBBox() + + return { + // measurements + uf : 1-f, + p : 0, // lw/2, // padding + + tw: this.cw-p/2, // right side. adjust by half line thickness to keep line in canvas + th: tBox.height-p/2, // height of square, and dist to middle + + mw: this.cw/2, // middle x + mh: tBox.height/2, // middle of top square + + bh: 0+p/2, // top of picture, bottom y + bw: 0+p/2, // left of picture, bottom of x + + sw: this.cw-p/2,// bottom of cube + sh: this.ch-p/2, // right of cube + + lq: -tBox.height/2+this.ch-p/2, // lower quarter of height + uq: tBox.height/2+p/2 // upper quarter + } +} + + +/* + * Adds a svg transform to an element, the transform has the origin of + * xi,yi fraction of the element, so 0.5,0.5 is the middle, + * unlike normalsvg it adds transforms in order of application not reverse order + * Usage: svgTransform(elementImage,'rotate',[45],0.5,0.5) + * This would rotate 45 degrees around center of image + */ +SvgCube.prototype.svgTransform = function (element, op, inputs, xi, yi) { + if (isNaN(xi)) { + xi = 0.5; + } + if (isNaN(yi)) { + yi = 0.5; + } + var svgBox = this.svg.getClientRects()[0] + // this.paper.getBBox() + var cbox = element.getBoundingClientRect(); + var x = cbox.left + xi * cbox.width -svgBox.left; + var y = cbox.top + yi * cbox.height -svgBox.top; + // + var matrix = this.svg.createSVGMatrix() + matrix = matrix.translate(x, y) + matrix = matrix[op].apply(matrix, inputs); + matrix = matrix.translate(-x, -y); + + var transform = this.svg.createSVGTransform(); + transform.setMatrix(matrix); + //element.transform.baseVal.appendItem(transform); // for reverse order + element.transform.baseVal.insertItemBefore(transform, 0) // normal order +} + +/* + * transform an element to be the left of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toLeft = function (element, angle, xi, yi) { + // half it's width + xi = 0 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -1]) // pixel adjustment HACK + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it, in degrees + this.svgTransform(element, 'skewY', [angle], xi, yi) + +} + +/* + * transform an element to be the right of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toRight = function (element, angle, xi, yi) { + xi = 1 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -2]) // pixel adjustment HACK + // half it's width to fiit in canvas + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it + this.svgTransform(element, 'skewY', [-angle], xi, yi) + +} + +/* + * transform an element to be the top of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toTop = function (element, angle, xi, yi) { + var rot = angle * Math.PI / 180; + this.svgTransform(element, 'translate', [-2, -1]) // pixel adjustment HACK + + // rotate so it's a diamond + this.svgTransform(element, 'rotate', [45], xi, yi) + // squish - along x axis to fit in canvas, along y axis for perspective change + this.svgTransform(element, 'scaleNonUniform', [Math.sin(45 * Math.PI / 180), Math.tan(rot) * Math.sin(45 * Math.PI / 180)], xi, yi) +} + +SvgCube.prototype.moveTop = function (element) { + // align top of cube with top of canvas + var cbox = element.getBoundingClientRect(); + this.svgTransform(element, 'translate', [-cbox.left + this.pPx, -cbox.top + this.pPx]) +} + +/* + * align left of cube with top, + * fit upper-left of left panel with middle-left of top panel + */ +SvgCube.prototype.moveLeft = function (elem, elemT) { + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + // align left + var x = cboxT.left - cboxL.left + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* + * align right of cube with top, + * fit upper-right of right panel with middle-right of top panel + */ +SvgCube.prototype.moveRight = function (elem, elemT) { + // line up left with top, move to half tops height, and to align left + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + + // align right with right + var x = cboxT.right - cboxL.right + + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawOutline = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(lw/2) + + + var tb = this.imageT.getBBox() + var lb = this.imageL.getBBox() + var rb = this.imageR.getBBox() + + // Draw outline of top + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + + // // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + // + // right + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + + // join into set + var pathGroup = this.paper.group(); + pathGroup.append(pathTop); + pathGroup.append(pathLeft); + pathGroup.append(pathRight); + + // set attrs from options + // ref http://raphaeljs.com/reference.html#Element.attr + var blackList = ['url','target','src','title'] + for (var a in this.options.stroke){ + if (this.options.stroke.hasOwnProperty(a) && blackList.indexOf(a)<0){ + pathGroup.attr(a,this.options.stroke[a]); + } + } + this.outline=pathGroup; +} + + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawShading = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(0); + var pathGroup = this.paper.g(); + + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + pathGroup.append(pathTop); + + // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + pathGroup.append(pathLeft); + + // last line from middle down + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + pathGroup.append(pathRight); + + + // style the set + pathGroup.attr({ + 'stroke': 'none', + 'fill': 'black', + 'stroke-width': 0, + 'stroke-opacity': 0, + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round' + }); + // shade each side, 0 is no shading, 1 is black + pathTop.attr({'fill-opacity': this.options.topShad}); + pathLeft.attr({'fill-opacity': this.options.leftShad}); + pathRight.attr({'fill-opacity': this.options.rightShad}); + this.shading=pathGroup; + +} + +/*clip the cube using an elipse to give rounded corners */ +SvgCube.prototype.clipCircle = function(amount){ + var cp = document.createElementNS("http://www.w3.org/2000/svg","clipPath") + cp.id="cp"; + var rxc=51+4*(1-this.f)*(1-this.f); + var ryc=50-2/Math.sqrt(1-this.f); + cp.innerHTML = '' + this.paper.node.getElementsByTagName("defs")[0].appendChild(cp); + this.paper.node.setAttribute("clip-path","url(#cp)"); +} + + +/* returns svg string */ +SvgCube.prototype.toSVG = function(){ + var svg3 = this.paper.toString(); + //var svg = this.paper.node.outerHTML; + //var svg2 = xmlserializer.serializeToString(this.paper.node); + if (this.paper.node.attributes.getNamedItem("clip-path")){ + // patch svg export to add clip + // HACK I have to add these manually to the export sadly as raphael.export doesn't handle them and also misses some recent change to canvas + svg3=svg3.replace(" + .cube, .cube .face, .cube .face * { + height: ${o.size}px; + width: ${o.size}px; + } + .cube { + position: absolute; + background-color: #f66; + -webkit-transform: translate(${o.size/2}px,${0}px); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + transform: rotateX(${o.angle}deg) scaleY(${o.flatten}); + } + + .cube * { + transform-origin: 0% 100%; + } + + .cube2 .top { + position: relative; + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(0deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + + } + .cube2 .left { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + position: absolute; + + } + .cube2 .right { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateY(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + position: absolute; + } + ` + console.log(styleStr); + style.innerHTML= styleStr + +} + +/* drawing measurements as a function of padding */ +SvgCube.prototype.measurements= function(p){ + if (p===undefined){ + p=0; + } + + var f = this.options.flatten + + var tBox = this.imageT.getBBox() + var lBox = this.imageL.getBBox() + var rBox = this.imageR.getBBox() + + return { + // measurements + uf : 1-f, + p : 0, // lw/2, // padding + + tw: this.cw-p/2, // right side. adjust by half line thickness to keep line in canvas + th: tBox.height-p/2, // height of square, and dist to middle + + mw: this.cw/2, // middle x + mh: tBox.height/2, // middle of top square + + bh: 0+p/2, // top of picture, bottom y + bw: 0+p/2, // left of picture, bottom of x + + sw: this.cw-p/2,// bottom of cube + sh: this.ch-p/2, // right of cube + + lq: -tBox.height/2+this.ch-p/2, // lower quarter of height + uq: tBox.height/2+p/2 // upper quarter + } +} + + +/* + * Adds a svg transform to an element, the transform has the origin of + * xi,yi fraction of the element, so 0.5,0.5 is the middle, + * unlike normalsvg it adds transforms in order of application not reverse order + * Usage: svgTransform(elementImage,'rotate',[45],0.5,0.5) + * This would rotate 45 degrees around center of image + */ +SvgCube.prototype.svgTransform = function (element, op, inputs, xi, yi) { + if (isNaN(xi)) { + xi = 0.5; + } + if (isNaN(yi)) { + yi = 0.5; + } + var svgBox = this.svg.getClientRects()[0] + // this.paper.getBBox() + var cbox = element.getBoundingClientRect(); + var x = cbox.left + xi * cbox.width -svgBox.left; + var y = cbox.top + yi * cbox.height -svgBox.top; + // + var matrix = this.svg.createSVGMatrix() + matrix = matrix.translate(x, y) + matrix = matrix[op].apply(matrix, inputs); + matrix = matrix.translate(-x, -y); + + var transform = this.svg.createSVGTransform(); + transform.setMatrix(matrix); + //element.transform.baseVal.appendItem(transform); // for reverse order + element.transform.baseVal.insertItemBefore(transform, 0) // normal order +} + +/* + * transform an element to be the left of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toLeft = function (element, angle, xi, yi) { + // half it's width + xi = 0 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -1]) // pixel adjustment HACK + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it, in degrees + this.svgTransform(element, 'skewY', [angle], xi, yi) + +} + +/* + * transform an element to be the right of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toRight = function (element, angle, xi, yi) { + xi = 1 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -2]) // pixel adjustment HACK + // half it's width to fiit in canvas + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it + this.svgTransform(element, 'skewY', [-angle], xi, yi) + +} + +/* + * transform an element to be the top of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toTop = function (element, angle, xi, yi) { + var rot = angle * Math.PI / 180; + this.svgTransform(element, 'translate', [-2, -1]) // pixel adjustment HACK + + // rotate so it's a diamond + this.svgTransform(element, 'rotate', [45], xi, yi) + // squish - along x axis to fit in canvas, along y axis for perspective change + this.svgTransform(element, 'scaleNonUniform', [Math.sin(45 * Math.PI / 180), Math.tan(rot) * Math.sin(45 * Math.PI / 180)], xi, yi) +} + +SvgCube.prototype.moveTop = function (element) { + // align top of cube with top of canvas + var cbox = element.getBoundingClientRect(); + this.svgTransform(element, 'translate', [-cbox.left + this.pPx, -cbox.top + this.pPx]) +} + +/* + * align left of cube with top, + * fit upper-left of left panel with middle-left of top panel + */ +SvgCube.prototype.moveLeft = function (elem, elemT) { + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + // align left + var x = cboxT.left - cboxL.left + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* + * align right of cube with top, + * fit upper-right of right panel with middle-right of top panel + */ +SvgCube.prototype.moveRight = function (elem, elemT) { + // line up left with top, move to half tops height, and to align left + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + + // align right with right + var x = cboxT.right - cboxL.right + + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawOutline = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(lw/2) + + + var tb = this.imageT.getBBox() + var lb = this.imageL.getBBox() + var rb = this.imageR.getBBox() + + // Draw outline of top + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + + // // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + // + // right + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + + // join into set + var pathGroup = this.paper.group(); + pathGroup.append(pathTop); + pathGroup.append(pathLeft); + pathGroup.append(pathRight); + + // set attrs from options + // ref http://raphaeljs.com/reference.html#Element.attr + var blackList = ['url','target','src','title'] + for (var a in this.options.stroke){ + if (this.options.stroke.hasOwnProperty(a) && blackList.indexOf(a)<0){ + pathGroup.attr(a,this.options.stroke[a]); + } + } + this.outline=pathGroup; +} + + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawShading = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(0); + var pathGroup = this.paper.g(); + + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + pathGroup.append(pathTop); + + // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + pathGroup.append(pathLeft); + + // last line from middle down + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + pathGroup.append(pathRight); + + + // style the set + pathGroup.attr({ + 'stroke': 'none', + 'fill': 'black', + 'stroke-width': 0, + 'stroke-opacity': 0, + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round' + }); + // shade each side, 0 is no shading, 1 is black + pathTop.attr({'fill-opacity': this.options.topShad}); + pathLeft.attr({'fill-opacity': this.options.leftShad}); + pathRight.attr({'fill-opacity': this.options.rightShad}); + this.shading=pathGroup; + +} + +/*clip the cube using an elipse to give rounded corners */ +SvgCube.prototype.clipCircle = function(amount){ + var cp = document.createElementNS("http://www.w3.org/2000/svg","clipPath") + cp.id="cp"; + var rxc=51+4*(1-this.f)*(1-this.f); + var ryc=50-2/Math.sqrt(1-this.f); + cp.innerHTML = '' + this.paper.node.getElementsByTagName("defs")[0].appendChild(cp); + this.paper.node.setAttribute("clip-path","url(#cp)"); +} + + +/* returns svg string */ +SvgCube.prototype.toSVG = function(){ + var svg3 = this.paper.toString(); + //var svg = this.paper.node.outerHTML; + //var svg2 = xmlserializer.serializeToString(this.paper.node); + if (this.paper.node.attributes.getNamedItem("clip-path")){ + // patch svg export to add clip + // HACK I have to add these manually to the export sadly as raphael.export doesn't handle them and also misses some recent change to canvas + svg3=svg3.replace(" + .cube, .cube .face, .cube .face * { + height: ${o.size}px; + width: ${o.size}px; + } + .cube { + position: absolute; + background-color: #f66; + + -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); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + } + + + .cube * { + transform-origin: 0% 100%; + } + + .cube2 .top { + position: relative; + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(0deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + + } + .cube2 .left { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + position: absolute; + + } + .cube2 .right { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateY(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + position: absolute; + } + ` + console.log(styleStr); + style.innerHTML= styleStr + +} + +/* drawing measurements as a function of padding */ +SvgCube.prototype.measurements= function(p){ + if (p===undefined){ + p=0; + } + + var f = this.options.flatten + + var tBox = this.imageT.getBBox() + var lBox = this.imageL.getBBox() + var rBox = this.imageR.getBBox() + + return { + // measurements + uf : 1-f, + p : 0, // lw/2, // padding + + tw: this.cw-p/2, // right side. adjust by half line thickness to keep line in canvas + th: tBox.height-p/2, // height of square, and dist to middle + + mw: this.cw/2, // middle x + mh: tBox.height/2, // middle of top square + + bh: 0+p/2, // top of picture, bottom y + bw: 0+p/2, // left of picture, bottom of x + + sw: this.cw-p/2,// bottom of cube + sh: this.ch-p/2, // right of cube + + lq: -tBox.height/2+this.ch-p/2, // lower quarter of height + uq: tBox.height/2+p/2 // upper quarter + } +} + + +/* + * Adds a svg transform to an element, the transform has the origin of + * xi,yi fraction of the element, so 0.5,0.5 is the middle, + * unlike normalsvg it adds transforms in order of application not reverse order + * Usage: svgTransform(elementImage,'rotate',[45],0.5,0.5) + * This would rotate 45 degrees around center of image + */ +SvgCube.prototype.svgTransform = function (element, op, inputs, xi, yi) { + if (isNaN(xi)) { + xi = 0.5; + } + if (isNaN(yi)) { + yi = 0.5; + } + var svgBox = this.svg.getClientRects()[0] + // this.paper.getBBox() + var cbox = element.getBoundingClientRect(); + var x = cbox.left + xi * cbox.width -svgBox.left; + var y = cbox.top + yi * cbox.height -svgBox.top; + // + var matrix = this.svg.createSVGMatrix() + matrix = matrix.translate(x, y) + matrix = matrix[op].apply(matrix, inputs); + matrix = matrix.translate(-x, -y); + + var transform = this.svg.createSVGTransform(); + transform.setMatrix(matrix); + //element.transform.baseVal.appendItem(transform); // for reverse order + element.transform.baseVal.insertItemBefore(transform, 0) // normal order +} + +/* + * transform an element to be the left of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toLeft = function (element, angle, xi, yi) { + // half it's width + xi = 0 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -1]) // pixel adjustment HACK + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it, in degrees + this.svgTransform(element, 'skewY', [angle], xi, yi) + +} + +/* + * transform an element to be the right of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toRight = function (element, angle, xi, yi) { + xi = 1 + yi = 1 + if (this.f>0){ + this.svgTransform(element, 'scaleNonUniform', [1,this.f],0.5,0.5) + } + this.svgTransform(element, 'translate', [-1, -2]) // pixel adjustment HACK + // half it's width to fiit in canvas + this.svgTransform(element, 'scaleNonUniform', [1 / 2, 1 / 2], xi, yi) + // skew it + this.svgTransform(element, 'skewY', [-angle], xi, yi) + +} + +/* + * transform an element to be the top of an isometric cube + * Inputs: dom element, angle in degrees, and xi,yi which + * are the transform origin as a fraction of element size + */ +SvgCube.prototype.toTop = function (element, angle, xi, yi) { + var rot = angle * Math.PI / 180; + this.svgTransform(element, 'translate', [-2, -1]) // pixel adjustment HACK + + // rotate so it's a diamond + this.svgTransform(element, 'rotate', [45], xi, yi) + // squish - along x axis to fit in canvas, along y axis for perspective change + this.svgTransform(element, 'scaleNonUniform', [Math.sin(45 * Math.PI / 180), Math.tan(rot) * Math.sin(45 * Math.PI / 180)], xi, yi) +} + +SvgCube.prototype.moveTop = function (element) { + // align top of cube with top of canvas + var cbox = element.getBoundingClientRect(); + this.svgTransform(element, 'translate', [-cbox.left + this.pPx, -cbox.top + this.pPx]) +} + +/* + * align left of cube with top, + * fit upper-left of left panel with middle-left of top panel + */ +SvgCube.prototype.moveLeft = function (elem, elemT) { + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + // align left + var x = cboxT.left - cboxL.left + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* + * align right of cube with top, + * fit upper-right of right panel with middle-right of top panel + */ +SvgCube.prototype.moveRight = function (elem, elemT) { + // line up left with top, move to half tops height, and to align left + var cboxL = elem.getBoundingClientRect(); + var cboxT = elemT.getBoundingClientRect(); + + // align right with right + var x = cboxT.right - cboxL.right + + // align top of left with half height of + var y = cboxT.top - cboxL.top + cboxT.height / 2 + this.svgTransform(elem, 'translate', [x, y]) +} + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawOutline = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(lw/2) + + + var tb = this.imageT.getBBox() + var lb = this.imageL.getBBox() + var rb = this.imageR.getBBox() + + // Draw outline of top + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + + // // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + // + // right + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + + // join into set + var pathGroup = this.paper.group(); + pathGroup.append(pathTop); + pathGroup.append(pathLeft); + pathGroup.append(pathRight); + + // set attrs from options + // ref http://raphaeljs.com/reference.html#Element.attr + var blackList = ['url','target','src','title'] + for (var a in this.options.stroke){ + if (this.options.stroke.hasOwnProperty(a) && blackList.indexOf(a)<0){ + pathGroup.attr(a,this.options.stroke[a]); + } + } + this.outline=pathGroup; +} + + +/* draw outline get line color from option.strokeColor, and width from options.stroke-width */ +SvgCube.prototype.drawShading = function(lw){ + lw=lw||this.options.stroke["stroke-width"]; + var ms = this.measurements(0); + var pathGroup = this.paper.g(); + + var strTop= + 'M'+ms.mw +' '+ms.th +' '+ // Move to bottom + 'L'+ms.bw +' '+ms.mh+' '+ // left + 'L'+ms.mw +' '+ms.bh+ ' '+ // top + 'L'+ms.tw +' '+ms.mh+' '+ // right + 'Z' // close + var pathTop = this.paper.path(strTop); + pathGroup.append(pathTop); + + // outline of left + var strLeft= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.bw +' '+ms.uq+' '+ // left top + 'L'+ms.bw +' '+ms.lq+' '+ // left bottom + 'L'+ms.mw +' '+ms.sh+' '+ // middle bottom + 'Z' + var pathLeft = this.paper.path(strLeft); + pathGroup.append(pathLeft); + + // last line from middle down + var strRight= + 'M'+ms.mw +' '+ms.th+' '+ // middle + 'L'+ms.mw +' '+ms.sh +' '+ // middle bottom + 'L'+ms.tw +' '+ms.lq+' '+ // right bottom + 'L'+ms.tw +' '+ms.uq+' '+ // right top + 'Z' // close + var pathRight = this.paper.path(strRight); + pathGroup.append(pathRight); + + + // style the set + pathGroup.attr({ + 'stroke': 'none', + 'fill': 'black', + 'stroke-width': 0, + 'stroke-opacity': 0, + 'stroke-linecap': 'round', + 'stroke-linejoin': 'round' + }); + // shade each side, 0 is no shading, 1 is black + pathTop.attr({'fill-opacity': this.options.topShad}); + pathLeft.attr({'fill-opacity': this.options.leftShad}); + pathRight.attr({'fill-opacity': this.options.rightShad}); + this.shading=pathGroup; + +} + +/*clip the cube using an elipse to give rounded corners */ +SvgCube.prototype.clipCircle = function(amount){ + var cp = document.createElementNS("http://www.w3.org/2000/svg","clipPath") + cp.id="cp"; + var rxc=51+4*(1-this.f)*(1-this.f); + var ryc=50-2/Math.sqrt(1-this.f); + cp.innerHTML = '' + this.paper.node.getElementsByTagName("defs")[0].appendChild(cp); + this.paper.node.setAttribute("clip-path","url(#cp)"); +} + + +/* returns svg string */ +SvgCube.prototype.toSVG = function(){ + var svg3 = this.paper.toString(); + //var svg = this.paper.node.outerHTML; + //var svg2 = xmlserializer.serializeToString(this.paper.node); + if (this.paper.node.attributes.getNamedItem("clip-path")){ + // patch svg export to add clip + // HACK I have to add these manually to the export sadly as raphael.export doesn't handle them and also misses some recent change to canvas + svg3=svg3.replace(" 5) { + console.log('Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]'); + console.log(' paper (pdf output) examples: "5in*7.5in", "10cm*20cm", "A4", "Letter"'); + console.log(' image (png/jpg output) examples: "1920px" entire page, window width 1920px'); + console.log(' "800px*600px" window, clipped to 800x600'); + phantom.exit(1); +} else { + address = system.args[1]; + output = system.args[2]; + page.viewportSize = { width: 600, height: 600 }; + if (system.args.length > 3 && system.args[2].substr(-4) === ".pdf") { + size = system.args[3].split('*'); + page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: '0px' } + : { format: system.args[3], orientation: 'portrait', margin: '1cm' }; + } else if (system.args.length > 3 && system.args[3].substr(-2) === "px") { + size = system.args[3].split('*'); + if (size.length === 2) { + pageWidth = parseInt(size[0], 10); + pageHeight = parseInt(size[1], 10); + page.viewportSize = { width: pageWidth, height: pageHeight }; + page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight }; + } else { + console.log("size:", system.args[3]); + pageWidth = parseInt(system.args[3], 10); + pageHeight = parseInt(pageWidth * 3/4, 10); // it's as good an assumption as any + console.log ("pageHeight:",pageHeight); + page.viewportSize = { width: pageWidth, height: pageHeight }; + } + } + if (system.args.length > 4) { + page.zoomFactor = system.args[4]; + } + page.open(address, function (status) { + if (status !== 'success') { + console.log('Unable to load the address!'); + phantom.exit(1); + } else { + window.setTimeout(function () { + page.render(output); + phantom.exit(); + }, 200); + } + }); +} diff --git a/right.svg b/right.svg new file mode 100644 index 0000000..b87a0ff --- /dev/null +++ b/right.svg @@ -0,0 +1,2439 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/svg-stylesheet.css b/svg-stylesheet.css new file mode 100644 index 0000000..3181dfd --- /dev/null +++ b/svg-stylesheet.css @@ -0,0 +1,43 @@ + .cube, .cube .face, .cube .face * { + height: 170px; + width: 170px; + } + .cube { + position: relative; + -webkit-transform: translate(11em,11em) + transform: translate(11em,11em) + } + + .cube * { + transform-origin: 0% 100%; + } + + .cube2 .top { + position: relative; + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(0deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + transform: rotateX(45deg) rotateZ(-45deg) rotateX(0deg); + transform-style: preserve-3d; + transition: .25s; + + } + .cube2 .left { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateX(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + transform: rotateX(45deg) rotateZ(-45deg) rotateX(90deg); + transform-style: preserve-3d; + transition: .25s; + position: absolute; + + } + .cube2 .right { + -webkit-transform: rotateX(45deg) rotateZ(-45deg) rotateY(90deg); + -webkit-transform-style: preserve-3d; + -webkit-transition: .25s; + transform: rotateX(45deg) rotateZ(-45deg) rotateY(90deg); + transform-style: preserve-3d; + transition: .25s; + position: absolute; + } diff --git a/test.html b/test.html new file mode 100644 index 0000000..6631cba --- /dev/null +++ b/test.html @@ -0,0 +1,56 @@ + + https://en.wikipedia.org/wiki/Isometric_projection + + + + + + + + + + + diff --git a/test2.html b/test2.html new file mode 100644 index 0000000..8895906 --- /dev/null +++ b/test2.html @@ -0,0 +1,97 @@ + + + + Snap.js isometric SVG + + + +
+ + + + + + + + + + + + + diff --git a/top.svg b/top.svg new file mode 100644 index 0000000..e1b67bc --- /dev/null +++ b/top.svg @@ -0,0 +1,2384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/webdriver_rasterize.js b/webdriver_rasterize.js new file mode 100644 index 0000000..3c6c832 --- /dev/null +++ b/webdriver_rasterize.js @@ -0,0 +1,52 @@ +var webdriverio = require('webdriverio'); + +var path = require('path'); +var fs = require('fs'); +var system = require('system') +var globby = require('globby'); + +var options = { + desiredCapabilities: { + browserName: 'chrome' + } +}; + +var config = { + debug: true +} + +var input = process.argv[2]; +console.log('input:',input); + + +globby(input).then(inputs => { + console.log('glob(',input,') =>', inputs); + for (var i=0; i',outfile); + webdriverio + .remote(options) + .init() + .url(url) + .getTitle().then(function(title) { + console.log('Title is: ' + title); + }) + .saveScreenshot( + [outfile], + function(err, screenshot, response) { + if (config.debug){ + console.log({file,err,screenshot,response}); + } else if (err){ + 'saveScreenshot',console.log(err); + } + } + ) + .end(); + } +}, this) +