svg viewbox

This commit is contained in:
Andy Bunce 2012-09-16 22:51:14 +01:00
parent 74916f723f
commit 41d29c6036
6 changed files with 374 additions and 23 deletions

View file

@ -100,13 +100,14 @@ else
(:~ post process svg :)
declare %private function get-svg($dot as xs:string) as node(){
let $svgx:=gr:dot($dot,())
return gr:autosize($svgx)
return gr:autosize($svgx)
};
declare function render($template,$locals){
let $sidebar:=<div>
<a href="/graphxq/viewbox/viewBox.svg">viewbox work</a>
<ul>
<div>Smples:</div>
<div>Samples:</div>
<li> <a href="dot?src=graphxq/samples/process.gv">process</a></li>
<li><a href="/restxq/graphxq/dot?src=graphxq/samples/unix.gv">unix</a></li>
<li> <a href="/restxq/graphxq/dot?src=graphxq/samples/root.gv">root (slow)</a></li>

View file

@ -51,9 +51,9 @@ declare %private function dot1( $dot as xs:string) as node(){
let $ver:=$s/comment()[1]/fn:normalize-space()
let $title:=$s/comment()[2]/fn:normalize-space()
let $svg:=$s/*
return <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
{$svg/@* except ($svg/@width,$svg/@height,$svg/@preserveAspectRatio),
return <svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" >
{$svg/@* ,
<metadata>
<rdf:RDF
xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"

View file

@ -0,0 +1,171 @@
/*****
*
* ViewBox.js
*
* copyright 2002, Kevin Lindsey
*
*****/
ViewBox.VERSION = "1.0";
/*****
*
* constructor
*
*****/
function ViewBox(svgNode) {
if ( arguments.length > 0 ) {
this.init(svgNode);
}
}
/*****
*
* init
*
*****/
ViewBox.prototype.init = function(svgNode) {
var viewBox = svgNode.getAttributeNS(null, "viewBox");
var preserveAspectRatio = svgNode.getAttributeNS(null, "preserveAspectRatio");
if ( viewBox != null && viewBox != "" ) {
var params = viewBox.split(/\s*,\s*|\s+/);
this.x = parseFloat( params[0] );
this.y = parseFloat( params[1] );
this.width = parseFloat( params[2] );
this.height = parseFloat( params[3] );
} else {
// NOTE: Need to put an SVGResize event handler on the svgNode to keep
// these values in sync with the window size or should add additional
// logic (probably a flag) to getTM() so it will know to use the window
// dimensions instead of this object's width and height properties
this.x = 0;
this.y = 0;
this.width = innerWidth;
this.height = innerHeight;
}
this.setPAR(preserveAspectRatio);
};
/*****
*
* getTM
*
*****/
ViewBox.prototype.getTM = function() {
var svgRoot = svgDocument.documentElement;
var matrix = svgDocument.documentElement.createSVGMatrix();
var windowWidth = svgRoot.getAttributeNS(null, "width");
var windowHeight = svgRoot.getAttributeNS(null, "height");
if (windowWidth != null && windowWidth != "") {
windowWidth = parseFloat(windowWidth);
} else {
if (window.innerWidth) {
windowWidth = innerWidth;
} else {
windowWidth = document.documentElement.viewport.width;
}
}
if (windowHeight != null && windowHeight != "") {
windowHeight = parseFloat(windowHeight);
} else {
if (window.innerHeight) {
windowHeight = innerHeight;
} else {
windowHeight = document.documentElement.viewport.height;
}
}
var x_ratio = this.width / windowWidth;
var y_ratio = this.height / windowHeight;
matrix = matrix.translate(this.x, this.y);
if ( this.alignX == "none" ) {
matrix = matrix.scaleNonUniform( x_ratio, y_ratio );
} else {
if ( x_ratio < y_ratio && this.meetOrSlice == "meet" ||
x_ratio > y_ratio && this.meetOrSlice == "slice" )
{
var x_trans = 0;
var x_diff = windowWidth*y_ratio - this.width;
if ( this.alignX == "Mid" )
x_trans = -x_diff/2;
else if ( this.alignX == "Max" )
x_trans = -x_diff;
matrix = matrix.translate(x_trans, 0);
matrix = matrix.scale( y_ratio );
}
else if ( x_ratio > y_ratio && this.meetOrSlice == "meet" ||
x_ratio < y_ratio && this.meetOrSlice == "slice" )
{
var y_trans = 0;
var y_diff = windowHeight*x_ratio - this.height;
if ( this.alignY == "Mid" )
y_trans = -y_diff/2;
else if ( this.alignY == "Max" )
y_trans = -y_diff;
matrix = matrix.translate(0, y_trans);
matrix = matrix.scale( x_ratio );
}
else
{
// x_ratio == y_ratio so, there is no need to translate
// We can scale by either value
matrix = matrix.scale( x_ratio );
}
}
return matrix;
}
/*****
*
* get/set methods
*
*****/
/*****
*
* setPAR
*
*****/
ViewBox.prototype.setPAR = function(PAR) {
// NOTE: This function needs to use default values when encountering
// unrecognized values
if ( PAR ) {
var params = PAR.split(/\s+/);
var align = params[0];
if ( align == "none" ) {
this.alignX = "none";
this.alignY = "none";
} else {
this.alignX = align.substring(1,4);
this.alignY = align.substring(5,9);
}
if ( params.length == 2 ) {
this.meetOrSlice = params[1];
} else {
this.meetOrSlice = "meet";
}
} else {
this.align = "xMidYMid";
this.alignX = "Mid";
this.alignY = "Mid";
this.meetOrSlice = "meet";
}
};

View file

@ -0,0 +1,168 @@
<?xml version="1.0" standalone="no"?>
<svg onload="init(evt)"
viewBox="10 10 500 400" preserveAspectRatio="xMidYMid meet"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
font-size="10pt">
<script type="text/ecmascript" xlink:href="ViewBox.js"/>
<script type="text/ecmascript"><![CDATA[
var svgns = "http://www.w3.org/2000/svg";
var svgRoot;
var viewBox;
var cursor;
var lastAlign;
var lastMeetOrSlice;
function init(e) {
if ( window.svgDocument == null )
svgDocument = e.target.ownerDocument;
svgRoot = svgDocument.documentElement;
viewBox = new ViewBox(svgDocument.documentElement);
cursor = svgDocument.getElementById("cursor");
lastAlign = svgDocument.getElementById("xMidYMid");
lastMeetOrSlice = svgDocument.getElementById("meet");
}
function setAlign(e) {
var align = e.target.id;
var meetOrSlice = lastMeetOrSlice.id;
var PAR = align + " " + meetOrSlice;
svgRoot.setAttributeNS(null, "preserveAspectRatio", PAR);
viewBox.setPAR(PAR);
lastAlign.setAttributeNS(null, "fill", "grey");
e.target.setAttributeNS(null, "fill", "darkblue");
lastAlign = e.target;
}
function setMeetOrSlice(e) {
var align = lastAlign.id;
var meetOrSlice = e.target.id;
var PAR = align + " " + meetOrSlice;
svgRoot.setAttributeNS(null, "preserveAspectRatio", PAR);
viewBox.setPAR(PAR);
lastMeetOrSlice.setAttributeNS(null, "fill", "grey");
e.target.setAttributeNS(null, "fill", "darkblue");
lastMeetOrSlice = e.target;
}
function show_coords(e) {
var parent = e.currentTarget;
var rect = parent.childNodes.item(1);
var CTM = getTransformToElement(rect);
var iCTM = CTM.inverse();
var trans = svgRoot.currentTranslate;
var scale = svgRoot.currentScale;
var m = viewBox.getTM();
var p1 = svgRoot.createSVGPoint();
var p2, p3;
m = m.scale( 1/scale );
m = m.translate(-trans.x, -trans.y);
p1.x = e.clientX;
p1.y = e.clientY;
p2 = p1.matrixTransform(m);
p3 = p2.matrixTransform(iCTM);
//alert("p1 = " + p1.x + "," + p1.y);
//alert("p2 = " + p2.x + "," + p2.y);
//alert("p3 = " + p3.x + "," + p3.y);
// Update cursor
cursor.setAttributeNS(null, "cx", p2.x);
cursor.setAttributeNS(null, "cy", p2.y);
// Show the results
var tspans = parent.getElementsByTagNameNS(svgns, "tspan");
tspans.item(1).firstChild.data = e.clientX;
tspans.item(3).firstChild.data = e.clientY;
tspans.item(5).firstChild.data = Math.round(p3.x*100) / 100;
tspans.item(7).firstChild.data = Math.round(p3.y*100) / 100;
}
/*****
*
* getTransformToElement
*
*****/
function getTransformToElement(node) {
// Initialize our node's Current Transformation Matrix
var CTM = node.getCTM();
// Work our way bacwards through the ancestor nodes stopping at the
// SVG Document
while ( ( node = node.parentNode ) != svgDocument ) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=543965
// Multiply the new CTM with what we've accumulated so far
var m=node.getCTM();
m=m?m:node.getScreenCTM();
CTM = m.multiply(CTM);
}
return CTM;
}
]]></script>
<circle id="cursor" r="10" fill="black"/>
<g onmousemove="show_coords(evt)">
<rect x="10" y="10" width="500" height="400" fill="blue" opacity="0.5"/>
<text fill="white" transform="translate(19,10)"
pointer-events="none">
<tspan x="0" dy="10pt">Client X = </tspan><tspan> </tspan>
<tspan x="0" dy="10pt">Client Y = </tspan><tspan> </tspan>
<tspan x="0" dy="10pt">User X = </tspan><tspan> </tspan>
<tspan x="0" dy="10pt">User Y = </tspan><tspan> </tspan>
</text>
<g transform="translate(230,180)">
<rect width="36" height="36" fill="white" stroke="red" stroke-width="2"/>
<g onmousedown="setAlign(evt)">
<rect id="xMinYMin" x="2" y="2" width="10" height="10" fill="grey"/>
<rect id="xMidYMin" x="13" y="2" width="10" height="10" fill="grey"/>
<rect id="xMaxYMin" x="24" y="2" width="10" height="10" fill="grey"/>
<rect id="xMinYMid" x="2" y="13" width="10" height="10" fill="grey"/>
<rect id="xMidYMid" x="13" y="13" width="10" height="10" fill="darkblue"/>
<rect id="xMaxYMid" x="24" y="13" width="10" height="10" fill="grey"/>
<rect id="xMinYMax" x="2" y="24" width="10" height="10" fill="grey"/>
<rect id="xMidYMax" x="13" y="24" width="10" height="10" fill="grey"/>
<rect id="xMaxYMax" x="24" y="24" width="10" height="10" fill="grey"/>
<g fill="grey" stroke="white" transform="translate(2,40)">
<rect id="none" width="32" height="12"/>
<text x="16" y="10" fill="white" stroke="none"
text-anchor="middle" pointer-events="none">none</text>
</g>
</g>
<g onmousedown="setMeetOrSlice(evt)">
<g fill="darkblue" stroke="white" transform="translate(42,5)">
<rect id="meet" width="32" height="12"/>
<text x="16" y="10" fill="white" stroke="none"
text-anchor="middle" pointer-events="none">meet</text>
</g>
<g fill="grey" stroke="white" transform="translate(42,21)">
<rect id="slice" width="32" height="12"/>
<text x="16" y="10" fill="white" stroke="none"
text-anchor="middle" pointer-events="none">slice</text>
</g>
</g>
</g>
<g transform="scale(4)" onmousemove="show_coords(evt)">
<g transform="translate(20,35) rotate(30) scale(2)">
<rect x="-2" y="0" width="10" height="10" fill="darkblue" opacity="0.5"/>
<text font-size="1pt" fill="white" transform="translate(9,0)"
pointer-events="none">
<tspan x="0" dy="1pt">Client X = </tspan><tspan> </tspan>
<tspan x="0" dy="1pt">Client Y = </tspan><tspan> </tspan>
<tspan x="0" dy="1pt">User X = </tspan><tspan> </tspan>
<tspan x="0" dy="1pt">User Y = </tspan><tspan> </tspan>
</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View file

@ -61,7 +61,10 @@
<button id="bndn" class="btn btn-mini"><i class="icon-download-alt"></i>download</button>
</div>
<div id="svgdiv" style="width:100%;height:30em;border:1px solid red;min-height:20em;">svg here</div>
<div id="svgdiv2" style="width:100%;height:30em;border:1px solid red;min-height:20em;">svg here</div>
</div>
<script>
</script>

View file

@ -47,29 +47,37 @@
<img src="/graphxq/graphxq2.png" />
graphXQ
</a>
<form class="pull-right navbar-search" action="search">
<input type="text" class="search-query span3" placeholder="Search"
name="q" />
<div class="icon-search"></div>
</form>
<div class="btn-group pull-right" style="margin-top:0px">
{$usermenu}
</div>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="">
<a href="./dot" rel="tooltip" data-title="first tooltip">Dot</a>
</li>
<li class="">
<a href="./dotml">DotML</a>
</li>
<li class="">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Create
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>
<a href="dot"><i class="icon-edit"></i> Dot</a>
</li>
<li>
<a href="dotml"><i class="icon-align-center"></i> DotML</a>
</li>
</ul>
</li>
<li class="nav">
<a href="about">About</a>
</li>
</ul>
<form class="pull-right navbar-search" action="search">
<input type="text" class="search-query span3" placeholder="Search"
name="q" />
<div class="icon-search"></div>
</form>
<div class="btn-group pull-right" style="margin-top:0px">
{$usermenu}
</div>
</div>