mirror of
https://github.com/Quodatum/graphxq.git
synced 2025-07-04 14:52:45 +01:00
svg viewbox
This commit is contained in:
parent
74916f723f
commit
41d29c6036
6 changed files with 374 additions and 23 deletions
|
@ -100,13 +100,14 @@ else
|
||||||
(:~ post process svg :)
|
(:~ post process svg :)
|
||||||
declare %private function get-svg($dot as xs:string) as node(){
|
declare %private function get-svg($dot as xs:string) as node(){
|
||||||
let $svgx:=gr:dot($dot,())
|
let $svgx:=gr:dot($dot,())
|
||||||
return gr:autosize($svgx)
|
return gr:autosize($svgx)
|
||||||
};
|
};
|
||||||
|
|
||||||
declare function render($template,$locals){
|
declare function render($template,$locals){
|
||||||
let $sidebar:=<div>
|
let $sidebar:=<div>
|
||||||
|
<a href="/graphxq/viewbox/viewBox.svg">viewbox work</a>
|
||||||
<ul>
|
<ul>
|
||||||
<div>Smples:</div>
|
<div>Samples:</div>
|
||||||
<li> <a href="dot?src=graphxq/samples/process.gv">process</a></li>
|
<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/unix.gv">unix</a></li>
|
||||||
<li> <a href="/restxq/graphxq/dot?src=graphxq/samples/root.gv">root (slow)</a></li>
|
<li> <a href="/restxq/graphxq/dot?src=graphxq/samples/root.gv">root (slow)</a></li>
|
||||||
|
|
|
@ -51,9 +51,9 @@ declare %private function dot1( $dot as xs:string) as node(){
|
||||||
let $ver:=$s/comment()[1]/fn:normalize-space()
|
let $ver:=$s/comment()[1]/fn:normalize-space()
|
||||||
let $title:=$s/comment()[2]/fn:normalize-space()
|
let $title:=$s/comment()[2]/fn:normalize-space()
|
||||||
let $svg:=$s/*
|
let $svg:=$s/*
|
||||||
return <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
return <svg xmlns="http://www.w3.org/2000/svg"
|
||||||
width="100%" height="100%" preserveAspectRatio="xMidYMid meet">
|
xmlns:xlink="http://www.w3.org/1999/xlink" >
|
||||||
{$svg/@* except ($svg/@width,$svg/@height,$svg/@preserveAspectRatio),
|
{$svg/@* ,
|
||||||
<metadata>
|
<metadata>
|
||||||
<rdf:RDF
|
<rdf:RDF
|
||||||
xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
xmlns:rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
|
171
src/graphxq/viewbox/ViewBox.js
Normal file
171
src/graphxq/viewbox/ViewBox.js
Normal 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";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
168
src/graphxq/viewbox/viewBox.svg
Normal file
168
src/graphxq/viewbox/viewBox.svg
Normal 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 |
|
@ -61,7 +61,10 @@
|
||||||
<button id="bndn" class="btn btn-mini"><i class="icon-download-alt"></i>download</button>
|
<button id="bndn" class="btn btn-mini"><i class="icon-download-alt"></i>download</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="svgdiv" style="width:100%;height:30em;border:1px solid red;min-height:20em;">svg here</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>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -47,29 +47,37 @@
|
||||||
<img src="/graphxq/graphxq2.png" />
|
<img src="/graphxq/graphxq2.png" />
|
||||||
graphXQ
|
graphXQ
|
||||||
</a>
|
</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">
|
<div class="nav-collapse collapse">
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
|
<li class="dropdown">
|
||||||
<li class="">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
<a href="./dot" rel="tooltip" data-title="first tooltip">Dot</a>
|
Create
|
||||||
</li>
|
<b class="caret"></b>
|
||||||
<li class="">
|
</a>
|
||||||
<a href="./dotml">DotML</a>
|
<ul class="dropdown-menu">
|
||||||
</li>
|
<li>
|
||||||
|
<a href="dot"><i class="icon-edit"></i> Dot</a>
|
||||||
<li class="">
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="dotml"><i class="icon-align-center"></i> DotML</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li class="nav">
|
||||||
<a href="about">About</a>
|
<a href="about">About</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</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>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue