Update dependencies. Use d3ver4

This commit is contained in:
Andy Bunce 2017-02-19 22:39:17 +00:00
parent f76ad081ab
commit 1080533e6c
17 changed files with 606 additions and 189 deletions

View file

@ -8,4 +8,5 @@
<tag>restxq</tag>
<tag>graph</tag>
<tag>svg</tag>
<tag>d3</tag>
</package>

View file

@ -1,9 +1,9 @@
<package abbrev="graphxq" name="https://github.com/apb2006/graphxq"
version="0.7" spec="1.0" xmlns="http://expath.org/ns/pkg">
version="0.7.2" spec="1.0" xmlns="http://expath.org/ns/pkg">
<title>Graphxq</title>
<dependency name="twitter-bootstrap" version="3.3.1" />
<dependency name="twitter-bootstrap" version="3.3.6" />
<dependency name="svg-pan-zoom" version="3.2.8" />
<dependency name="jquery" version="2.0.2" />
<dependency name="ace" version="1.2.3" />
<dependency name="d3" version="3" />
<dependency name="d3" version="4" />
</package>

View file

@ -18,7 +18,7 @@ declare namespace restxq = 'http://exquery.org/ns/restxq';
(:~ shared page wrapper :)
declare variable $grxq:layout:=fn:resolve-uri("views/layout.xq");
declare variable $grxq:version:=fn:doc("expath-pkg.xml")/*/@version;
declare variable $grxq:version as xs:string:=fn:doc("expath-pkg.xml")/*/@version/fn:string();
(:~
: Home page for app
:)
@ -36,7 +36,20 @@ declare
%restxq:GET %restxq:path("graphxq/about")
%output:method("html") %output:version("5.0")
function about(){
render("views/about.xml",map{"title":"GraphXQ"})
render("views/about.xq",map{"title":"GraphXQ",
"version":$grxq:version})
};
(:~
: about page for app
:)
declare
%restxq:GET %restxq:path("graphxq/search")
%output:method("html") %output:version("5.0")
%restxq:form-param("q","{$q}")
function search($q){
render("views/search.xq",map{"title":"GraphXQ search",
"q":$q})
};
(:~

View file

@ -1,7 +1,8 @@
declare variable $version external ;
<div class="row-fluid">
<div class="hero-unit">
<h1>GraphXQ</h1>
<p>A web interface to <a href="http://www.graphviz.org/" target="_blank">Graphviz</a>.
<h1>GraphXQ <span class="label label-default">{$version}</span></h1>
<p>A web interface for <a href="http://www.graphviz.org/" target="_blank">Graphviz</a>.
Graph descriptions can be entered in the
<a href="http://www.graphviz.org/content/dot-language" target="_blank">Dot</a>
or <a href="http://www.martin-loetzsch.de/DOTML" target="_blank">DotML</a> languages and the corresponding
@ -12,7 +13,7 @@
<div class="fluid-row">
<div class="span4">
<h2>Client</h2>
<p>The client side targets modern browsers with SVG support. It was tested against Firefox 46 and Chrome 50.
<p>The client side targets modern browsers with SVG support. It was tested against Firefox 51 and Chrome 56.
</p>
<p><a href="http://twitter.github.com/bootstrap/index.html"
@ -21,7 +22,8 @@
</p>
<p>Javascript libraries are loaded from CDN where possible. In particular
<a href="http://cdnjs.com" target="_blank">cdnjs.com</a> is used.</p>
<p>The resultant SVG is viewed in an interface that provides pan and zoom functionality.
<p>The resultant SVG is viewed in an interface that provides pan and zoom functionality built on top of
<a href="http://d3js.org" target="_blank">D3</a>.
The SVG may also be viewed standalone or downloaded.</p>
</div>
<div class="span4">
@ -38,15 +40,7 @@
<a href="http://www.martin-loetzsch.de/DOTML" target="_blank">DotML</a>
is a XML based syntax for the input language of the 'Dot'.</p>
</div>
<div class="span4">
<h2>Todo</h2>
<p>The SVG pan and zoom has problems, especially in Firefox. In part this maybe due
to firefox bugs</p>
<p>For reference how the SVG <a href="/static/graphxq/viewbox/viewBox.svg">viewbox</a>
works. See also <a href="http://www.dotuscomus.com/svg/lib/library.html#autozoom" target="_blank">here</a>
for a better way?
</p>
</div>
</div>
</div>
<hr/>
@ -54,28 +48,10 @@ for a better way?
<img style="position: absolute; top: 50px; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"/>
</a>
<footer>
<p>&#169; Andy Bunce 2013 -2016</p>
<p>&#169; Andy Bunce 2013 -2017</p>
<ul class="quick-links">
<!--
<li><iframe class="github-btn"
src="http://markdotto.github.com/github-buttons/github-btn.html?user=apb2006&amp;repo=xqwebdoc&amp;type=watch&amp;count=true"
allowtransparency="true" scrolling="0" width="112px" frameborder="0"
height="20px"></iframe></li>
<li><iframe class="github-btn"
src="http://markdotto.github.com/github-buttons/github-btn.html?user=apb2006&amp;repo=xqwebdoc&amp;type=fork&amp;count=true"
allowtransparency="true" scrolling="0" width="98px" frameborder="0"
height="20px"></iframe></li>
-->
<li class="follow-btn"><iframe title="Twitter Follow Button"
style="width: 237px; height: 20px;" class="twitter-follow-button"
src="http://platform.twitter.com/widgets/follow_button.html?id=twitter-widget-2&amp;lang=en&amp;screen_name=apb1704&amp;show_count=true&amp;show_screen_name=true&amp;size=m"
allowtransparency="true" scrolling="no" frameborder="0"></iframe></li>
<li class="tweet-btn"><iframe title="Twitter Tweet Button"
style="width: 106px; height: 20px;"
class="twitter-share-button twitter-count-horizontal"
src="http://platform.twitter.com/widgets/tweet_button.html?count=horizontal&amp;id=twitter-widget-0&amp;lang=en&amp;original_referer=http://apps-quodatum.rhcloud.com/graphxq/&amp;size=m&amp;text=graphxq #xquery&amp;url=http://apps-quodatum.rhcloud.com/graphxq/&amp;via=apb1704"
allowtransparency="true" scrolling="no" frameborder="0"></iframe></li>
</ul>
</ul>
</footer>
</div>

View file

@ -1,42 +1,42 @@
<div class="row-fluid">
<div class="span2">
Sidebar content outline etc..
</div>
<div class="span10">
<ul class="nav nav-tabs" id="myTab" style="margin-bottom:4px">
<li class="active"><a href="#home" data-toggle="tab">Home</a></li>
<li><a href="#profile" data-toggle="tab">Profile</a></li>
<li><a href="#messages" data-toggle="tab">Messages</a></li>
<li><a href="#settings" data-toggle="tab">Settings</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="home">
<div class="span12 ace-container extend" id="leftPane" >
<div id="editor" class="ace" data-mode="xquery" >module namespace txq = 'apb.txq';
declare default function namespace 'apb.txq';
import module namespace xquery = "http://basex.org/modules/xquery";
(:~
: template function
: @param template url to fill
: @param map name and value to apply
: @return updated doc from map
:)
declare function render($template as xs:string,$map as map(*)){{
let $map:=map:new(($map,map{{"partial":=partial(?,?,?,$map,$template)}}))
return xquery:invoke($template,$map)
}};</div>
</div>
</div>
<div class="tab-pane" id="profile">
...
</div>
<div class="tab-pane" id="messages">
...</div>
<div class="tab-pane" id="settings">
...</div>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span2">
Sidebar content outline etc..
</div>
<div class="span10">
<ul class="nav nav-tabs" id="myTab" style="margin-bottom:4px">
<li class="active"><a href="#home" data-toggle="tab">Home</a></li>
<li><a href="#profile" data-toggle="tab">Profile</a></li>
<li><a href="#messages" data-toggle="tab">Messages</a></li>
<li><a href="#settings" data-toggle="tab">Settings</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="home">
<div class="span12 ace-container extend" id="leftPane" >
<div id="editor" class="ace" data-mode="xquery" >module namespace txq = 'apb.txq';
declare default function namespace 'apb.txq';
import module namespace xquery = "http://basex.org/modules/xquery";
(:~
: template function
: @param template url to fill
: @param map name and value to apply
: @return updated doc from map
:)
declare function render($template as xs:string,$map as map(*)){{
let $map:=map:new(($map,map{{"partial":=partial(?,?,?,$map,$template)}}))
return xquery:invoke($template,$map)
}};</div>
</div>
</div>
<div class="tab-pane" id="profile">
profile...
</div>
<div class="tab-pane" id="messages">
messages...</div>
<div class="tab-pane" id="settings">
settings...</div>
</div>
</div>
</div>

View file

@ -27,18 +27,11 @@ node[shape=circle,style=filled,fillcolor=lightblue]
<div id="svgdiv" class="extend">
<div id="canvasQwpYZa" class="canvas" style="width:100%;height:100%;"></div>
<script>
var canvas = d3.demo.canvas();
d3.select("#canvasQwpYZa").call(canvas);
d3.select("#resetButtonQwpYZa").on("click", function() {{
canvas.reset();
}});
function replaceItem(item) {{
canvas.clear();
canvas.addItem(d3.select(item));
canvas.reset();
}};
var canvas = d3.graphxq.svgpan(d3.select("#canvasQwpYZa"));
d3.select("#resetButtonQwpYZa").on("click", canvas.resetted);
d3.select("#axesButton").on("click", canvas.toggleAxes);
//alert("canvas");
</script>
</div>
<div id="svgsrc" class="extend ace-container" style="display: none">

View file

@ -23,21 +23,8 @@ declare variable $svgwidget external :="{svg}";
<div id="svgdiv" class="extend">
<div id="canvasQwpYZa" class="canvas" style="width:100%;height:100%;"></div>
<script>
var canvas = d3.demo.canvas();
d3.select("#canvasQwpYZa").call(canvas);
d3.select("#resetButtonQwpYZa").on("click", function() {{
canvas.reset();
}});
function addItem(item) {{
canvas.addItem(d3.select(item));
}};
function replaceItem(item) {{
canvas.clear();
canvas.addItem(d3.select(item));
canvas.reset();
}};
var canvas = d3.graphxq.svgpan(d3.select("#canvasQwpYZa"));
d3.select("#resetButtonQwpYZa").on("click", canvas.resetted);
</script>
</div>
<div id="svgsrc" class="extend ace-container" style="display: none">

View file

@ -14,20 +14,21 @@ declare variable $active-link external :=function($_){$_};
<meta name="description" content="graphviz tool" />
<meta name="author" content="andy bunce" />
<link
href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/css/bootstrap.min.css"
href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css"
rel="stylesheet" type="text/css" />
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="/static/graphxq/graphxq2.png" />
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js" type="text/javascript"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.3/ace.js" type="text/javascript" charset="utf-8"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js" type="text/javascript"></script>
<script src="http://d3js.org/d3.v4.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.6/ace.js" type="text/javascript" charset="utf-8"></script>
<link href="/static/graphxq/app.css" rel="stylesheet" type="text/css" />
<link href="/static/graphxq/svg-pan-zoom.css" rel="stylesheet" type="text/css" />
<script src="/static/graphxq/app.js" type="text/javascript"></script>
<script src="http://d3js.org/d3.v3.js" charset="utf-8"></script>
<script src="/static/graphxq/svg-pan-zoom.js"></script>
<script src="/static/graphxq/svg-pan-zoom2.js"></script>
<script type="text/javascript"><![CDATA[
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-34544921-1']);
@ -82,14 +83,22 @@ declare variable $active-link external :=function($_){$_};
</ul>
<form class="navbar-form navbar-left" role="search">
<form class="navbar-form navbar-left" role="search" action="search" method="get">
<div class="form-group">
<input type="text" class="form-control" placeholder="Search"/>
<input name="q" type="text" class="form-control" placeholder="Search"/>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
<ul class="nav navbar-nav navbar-right">
<li >
<a id="bnOpts" class="btn btn-mini"
href="/graphxq/views/options.xml" data-target="#myModal" data-toggle="modal"
title="Extra settings (not implemented yet)" >
<i class="glyphicon glyphicon-gift"></i>
Options
</a>
</li>
<li class="{$active-link('ace')}">
<a href="ace" title="Xquery editor (just for fun)"
><i class="glyphicon glyphicon-wrench"></i> Ace</a>
@ -97,7 +106,6 @@ declare variable $active-link external :=function($_){$_};
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">About <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Action</a></li>
<li>
<a href="testd3">D3 test</a>
</li>
@ -115,19 +123,23 @@ declare variable $active-link external :=function($_){$_};
</nav>
<!-- Modal http://jsfiddle.net/matt_hwy1/hRq82/1/ -->
<div id="myModal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Modal Test Header</h3>
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">x</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
@TODO...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
<div class="modal-body">
<p>One fine body…</p>
</div>
<div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
<button class="btn btn-primary">Save changes</button>
</div>
</div>
<div class="container">
{$body}
</div>

View file

@ -0,0 +1,5 @@
declare variable $q external :="(N/A)";
<div class="row-fluid">
<h1>Search results {$q}</h1>
not yet
</div>

View file

@ -6,18 +6,14 @@
<i class="glyphicon glyphicon-refresh"></i>
Redraw
</button>
<a id="infotip" data-original-title="Status from Ajax"
class="btn btn-mini" rel="popover" data-placement="bottom" data-content="nothing yet."
title="Ajax request status">
<i class="glyphicon glyphicon-info-sign" title="Request status, click for more."></i>
</a>
</div>
</div>
<div class="btn-group">
<a id="bnOpts" class="btn btn-mini"
href="/graphxq/views/options.xml" data-target="#myModal" data-toggle="modal"
title="Extra settings (not implemented yet)" >
<i class="glyphicon glyphicon-gift"></i>
Options
</a>
</div>
<div class="btn-group">
<button id="bnclear" class="btn btn-mini"
title="Set editor to default empty content" >
@ -26,7 +22,7 @@
</button>
</div>
<!-- http://stackoverflow.com/questions/12101781/splitter-for-twitter-bootstrap -->
<div class="btn-group " data-toggle="buttons-radio">
<div class="btn-group " data-toggle="buttons-radio" style="padding-left:10em">
<a rel="tooltip" title="Show only the editor" class="btn btn-mini btn-default"
data-action="lDom" data-placement="left">
<i class="glyphicon glyphicon-indent-left"></i>
@ -40,37 +36,35 @@
<i class="glyphicon glyphicon-indent-right"></i>
</a>
</div>
<a id="infotip" data-original-title="Status from Ajax"
class="btn btn-mini" rel="popover" data-placement="bottom" data-content="nothing yet."
title="Ajax request status">
<i class="glyphicon glyphicon-info-sign" title="Request status, click for more."></i>
</a>
<div class="pull-right">
<div class="btn-group ">
<button id="resetButtonQwpYZa" class="btn btn-mini btn-default" data-toggle="button" title="Zoom to fit">
<button id="bnxml" class="btn btn-mini btn-default" data-toggle="button" title="Toggle SVG graphic and text">
SVG<i class="glyphicon glyphicon-eye-close"></i>
</button>
<button id="resetButtonQwpYZa" class="btn btn-mini btn-default" title="Zoom to fit">
<i class="glyphicon glyphicon-screenshot"></i>
</button>
<button id="resetButtonQwpYZa" class="btn btn-mini btn-default" data-toggle="button" title="Zoom in">
<button id="zoominButton" class="btn btn-mini btn-default" title="Zoom in (double-click)">
<i class="glyphicon glyphicon-plus-sign"></i>
</button>
<button id="resetButtonQwpYZa" class="btn btn-mini btn-default" data-toggle="button" title="Zoom out">
<button id="zoomoutButton" class="btn btn-mini btn-default" title="Zoom out (shift double-click)">
<i class="glyphicon glyphicon-minus-sign"></i>
</button>
<button id="axesButton" class="btn btn-mini btn-default" title="Toggle axes">
<span class="glyphicon glyphicon-th-large"></span>
</button>
</div>
<div class="btn-group ">
<button id="bnsvg" class="btn btn-mini btn-default" title="Show SVG standalone.">
<i class="glyphicon glyphicon-share"></i>
SVG
<button id="bnsvg" class="btn btn-mini btn-default" title="Show SVG standalone.">
SVG<i class="glyphicon glyphicon-share"></i>
</button>
<button id="bndn" class="btn btn-mini btn-default" title="Download SVG file">
<i class="glyphicon glyphicon-download-alt"></i>
download
<button id="bndn" class="btn btn-mini btn-default" title="Download SVG file">
download<i class="glyphicon glyphicon-download-alt"></i>
</button>
<button id="bnxml" class="btn btn-mini btn-default" data-toggle="button" title="Toggle SVG graphic and text">
<i class="glyphicon glyphicon-eye-close"></i>
SVG text
</button>
</div>
</div>

View file

@ -28,7 +28,7 @@ $(document).ready(function(){
});
function setupEdit(){
$("#infotip").popover({"html":true,
template: '<div class="popover popwidth"><div class="arrow"></div><div class="popover-inner popwidth" ><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
template: '<div class="popover popwidth"><div class="arrow"></div><div class="popover-inner " ><h3 class="popover-title"></h3><div class="popover-content"><p></p></div></div></div>'
});
// toolbar buttons
$('a[data-action="lDom"]').click(function (){
@ -87,10 +87,11 @@ function getsvg(){
var data = oParser.parseFromString(str, "text/xml");
// http://stackoverflow.com/questions/3346106/accessing-a-dom-object-defined-in-an-external-svg-file
var n = document.importNode(data.documentElement,true);
replaceItem(n);
// replaceItem(n);
if(canvas)canvas.setsvg(n);
ace.edit("svgsrc2").setValue(str,1);
//ace.edit("svgsrc2").selection.clear();
$("#infotip").attr("data-content","SVG returned in: "+d +" ms.");
$("#infotip").attr("data-content","<span>SVG returned in: "+d +" ms.</span>");
},
error:function(jqXHR, textStatus, errorThrown){
console.log("ajax error: "+textStatus + jqXHR.responseText);

View file

@ -33,4 +33,15 @@ html, body {
fill: url(#minimapGradient_qwpyza);
xfilter: url(#minimapDropShadow_qwpyza);
cursor: move;
}
}
.axis line{
stroke: cadetblue;
}
.axis path{
stroke: cadetblue;
}
.axis text{
fill: cadetblue;
}

View file

@ -1,4 +1,8 @@
// http://www.billdwhite.com/wordpress/2013/11/26/d3-minimap-pan-and-zoom-demo/
// svg mini map in d3 version 4
// @license MIT
// @Copyright 2017 Andy Bunce
// @Copyright 2008 William White
// @see http://www.billdwhite.com/wordpress/2013/11/26/d3-minimap-pan-and-zoom-demo/
d3.demo = {};
/** CANVAS **/
@ -22,18 +26,18 @@ d3.demo = {};
base = selection;
var xScale = d3.scale.linear()
var xScale = d3.scaleLinear()
.domain([-width / 2, width / 2])
.range([0, width]);
var yScale = d3.scale.linear()
var yScale = d3.scaleLinear()
.domain([-height / 2, height / 2])
.range([height, 0]);
var zoomHandler = function(newScale) {
if (!zoomEnabled) { return; }
if (d3.event) {
scale = d3.event.scale;
scale = d3.event.transform.k;
} else {
scale = newScale;
}
@ -43,7 +47,8 @@ d3.demo = {};
lbound = -width * scale,
rbound = width * scale;
// limit translation to thresholds
translation = d3.event ? d3.event.translate : [0, 0];
console.log("d3.event: ",d3.event? d3.event.transform: "none");
translation = d3.event ? [d3.event.transform.x,d3.event.transform.y]: [0, 0];
translation = [
Math.max(Math.min(translation[0], rbound), lbound),
Math.max(Math.min(translation[1], bbound), tbound)
@ -56,11 +61,12 @@ d3.demo = {};
minimap.scale(scale).render();
}; // startoff zoomed in a bit to show pan/zoom rectangle
var zoom = d3.behavior.zoom()
.x(xScale)
.y(yScale)
var zoom = d3.zoom()
// .x(xScale)
// .y(yScale)
.scaleExtent([0.1, 10])
.on("zoom.canvas", zoomHandler);
var w=width + (wrapperBorder*2) + minimapPadding*2 + (width*minimapScale);
var h=height + (wrapperBorder*2);
var svg = selection.append("svg")
@ -119,8 +125,8 @@ d3.demo = {};
.attr("in", "SourceGraphic")
.attr("in2", "blurOut")
.attr("mode", "normal");
var minimapRadialFill = svgDefs.append("radialGradient")
/*
var minimapRadialFill = svgDefs.append("svg:radialGradient")
.attr({
id:"minimapGradient_qwpyza",
gradientUnits:"userSpaceOnUse",
@ -139,7 +145,7 @@ d3.demo = {};
minimapRadialFill.append("stop")
.attr("offset", "100%")
.attr("stop-color", "#E0E0E0");
*/
var outerWrapper = svg.append("g")
.attr("class", "wrapper outer")
.attr("transform", "translate(0, " + minimapPadding + ")");
@ -181,7 +187,7 @@ d3.demo = {};
svg.call(minimap);
// startoff zoomed in a bit to show pan/zoom rectangle
zoom.scale(1.75);
//@TODO zoom.scaleBy(1.75);
zoomHandler(1.75);
/** ADD SHAPE **/
@ -242,11 +248,14 @@ d3.demo = {};
};
canvas.reset = function() {
svg.call(zoom.event);
zoom.scale(1);
zoom.translate([0,0]);
svg.transition().duration(750).call(zoom.event);
console.log("reset",zoom.transform);
svg.call(zoom.transform, d3.zoomIdentity); //.transition().duration(750)
};
canvas.zoom = function(factor) {
console.log("zoom",zoom.transform);
svg.call(zoom.scaleBy,factor);//.transition().duration(750)
};
}
@ -286,7 +295,7 @@ d3.demo = {};
scale = 1,
zoom = null,
base = null,
target = null,
target = null, // panCanvas
width = 0,
height = 0,
x = 0,
@ -318,9 +327,9 @@ d3.demo = {};
.attr("height", height)
.attr("filter", "url(#minimapDropShadow_qwpyza)");
var drag = d3.behavior.drag()
.on("dragstart.minimap", function() {
var frameTranslate = d3.demo.util.getXYFromTranslate(frame.attr("transform"));
var drag = d3.drag()
.on("start.minimap", function() {
var frameTranslate = d3.demo.util.getTranslation(frame.attr("transform"));
frameX = frameTranslate[0];
frameY = frameTranslate[1];
})
@ -330,21 +339,22 @@ d3.demo = {};
frameY += d3.event.dy;
frame.attr("transform", "translate(" + frameX + "," + frameY + ")");
var translate = [(-frameX*scale),(-frameY*scale)];
target.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
zoom.translate(translate);
// target.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
//@TODO zoom.translate(translate);
zoom.translateBy(target,translate[0],translate[1]);
});
frame.call(drag);
/** RENDER **/
minimap.render = function() {
scale = zoom.scale();
scale = 1; //@TODO zoom.scale();
container.attr("transform", "translate(" + x + "," + y + ")scale(" + minimapScale + ")");
var node = target.node().cloneNode(true);
node.removeAttribute("id");
base.selectAll(".minimap .panCanvas").remove();
minimap.node.appendChild(node);
var targetTransform = d3.demo.util.getXYFromTranslate(target.attr("transform"));
var targetTransform = d3.demo.util.getTranslation(target.attr("transform"));
frame.attr("transform", "translate(" + (-targetTransform[0]/scale) + "," + (-targetTransform[1]/scale) + ")")
.select(".background")
.attr("width", width/scale)
@ -397,6 +407,7 @@ d3.demo = {};
minimap.minimapScale = function(value) {
if (!arguments.length) { return minimapScale; }
console.log("SET SCALE",value);
minimapScale = value;
return this;
};
@ -429,8 +440,21 @@ d3.demo = {};
currentY = currentTransform.translate[1];
return [currentX, currentY];
};
/** RUN SCRIPT **/
d3.demo.util.getTranslation=function(transform) {
// Create a dummy g for calculation purposes only. This will never
// be appended to the DOM and will be discarded once this function
// returns.
var g = document.createElementNS("http://www.w3.org/2000/svg", "g");
// Set the transform attribute to the provided string value.
g.setAttributeNS(null, "transform", transform);
// consolidate the SVGTransformList containing all transformations
// to a single SVGTransform of type SVG_TRANSFORM_MATRIX and get
// its SVGMatrix.
var matrix = g.transform.baseVal.consolidate().matrix;
// As per definition values e and f are the ones for the translation.
return [matrix.e, matrix.f];
};

View file

@ -0,0 +1,157 @@
// svg mini map in d3 version 4
// d3.graphxq.svgpan(d3.selection)
// d3.graphxq.setsvg(url)
// d3.graphxq.resetted()
// @license MIT
// @Copyright 2017 Andy Bunce
var url="/static/graphxq/sample.svg";
var duration=750;
d3.graphxq = {};
d3.graphxq.svgpan=function(selection){
var showAxes=false;
var base=selection;
var width=500;
var height=500;
var that=this;
var svg = selection.append("svg")
.attr("class", "svg canvas")
.attr("width", "100%")
.attr("height", "100%")
.attr("viewBox", "0 0 "+width + " "+height)
.attr("shape-rendering", "auto");
var svgDefs = svg.append("defs");
svgDefs.append("clipPath")
.attr("id", "wrapperClipPath_qwpyza")
.attr("class", "wrapper clipPath")
.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
svgDefs.append("clipPath")
.attr("id", "minimapClipPath_qwpyza")
.attr("class", "minimap clipPath")
.attr("width", width)
.attr("height", height)
//.attr("transform", "translate(" + (width + minimapPadding) + "," + (minimapPadding/2) + ")")
.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
var filter = svgDefs.append("svg:filter")
.attr("id", "minimapDropShadow_qwpyza")
.attr("x", "-20%")
.attr("y", "-20%")
.attr("width", "150%")
.attr("height", "150%");
filter.append("svg:feOffset")
.attr("result", "offOut")
.attr("in", "SourceGraphic")
.attr("dx", "1")
.attr("dy", "1");
filter.append("svg:feColorMatrix")
.attr("result", "matrixOut")
.attr("in", "offOut")
.attr("type", "matrix")
.attr("values", "0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.5 0");
filter.append("svg:feGaussianBlur")
.attr("result", "blurOut")
.attr("in", "matrixOut")
.attr("stdDeviation", "10");
filter.append("svg:feBlend")
.attr("in", "SourceGraphic")
.attr("in2", "blurOut")
.attr("mode", "normal");
var zoom = d3.zoom()
.scaleExtent([ .5, 60 ])
.translateExtent([ [ -100, -100 ], [ width + 90, height + 100 ] ]);
var view = svg.append("g");
// X -----------------
var xScale = d3.scaleLinear()
.domain([ -1, width + 1 ])
.range([ -1, width + 1 ]);
var xAxis = d3.axisBottom(xScale)
.ticks((width + 2) / (height + 2) * 10)
.tickSize(height)
.tickPadding(8 - height);
var gX = svg.append("g")
.attr("class", "axis axis--x")
.attr("opacity",showAxes?1:0)
.call(xAxis);
// Y --------------------
var yScale = d3.scaleLinear()
.domain([ -1, height + 1 ])
.range([ -1, height + 1 ]);
var yAxis = d3.axisRight(yScale)
.ticks(10)
.tickSize(width)
.tickPadding(8 - width);
var gY = svg.append("g")
.attr("class", "axis axis--y")
.attr("opacity",showAxes?1:0)
.call(yAxis);
/*
var back = view.append("rect")
.attr("class", "view")
.attr("x", 0.5)
.attr("y", 0.5)
.attr("width", width - 1)
.attr("height", height - 1)
.attr("class", "background");
*/
var target = view.append("g");
var zoomed=function () {
//console.log("zoomed: ",d3.event.transform);
view.attr("transform", d3.event.transform);
gX.call(xAxis.scale(d3.event.transform.rescaleX(xScale)));
gY.call(yAxis.scale(d3.event.transform.rescaleY(yScale)));
};
zoom.on("zoom", zoomed);
this.resetted=function () {
svg.transition()
.duration(duration)
.call(zoom.transform, d3.zoomIdentity);
};
d3.select("button.reset").on("click", this.resetted);
var loaded=function (){
d3.xml(url,setsvg);
};
this.setsvg=function(xml){
var tn=target.node();
while (tn.hasChildNodes()) {
tn.removeChild(tn.lastChild);
};
target.node().appendChild(xml);
};
this.toggleAxes=function(){
showAxes=!showAxes;
gX.transition().duration(duration).attr("opacity",showAxes?1:0);
gY.transition().duration(duration).attr("opacity",showAxes?1:0);
//alert("Show: "+showAxes);
//zoomed();
};
d3.select("button.load").on("click", loaded);
svg.call(zoom);
return this;
};

View file

@ -0,0 +1,36 @@
html, body {
font-family: Arial, sans-serif;
}
.title {
font-size: 12px;
}
.canvas {
overflow: hidden;
fill: #808040;
}
.canvas .wrapper.outer > .background {
fill: #000000;
}
.canvas .wrapper.inner > .background {
fill: #CCCCCC;
cursor: move;
}
.canvas .background {
fill: #F6F6F6;
stroke: #333333;
cursor: move;
}
.canvas .panCanvas {
cursor: move;
}
.canvas .minimap .frame .background {
stroke: #111111;
stroke-width: 4px;
fill-opacity: 0.4;
fill: #000000;
fill: url(#minimapGradient_qwpyza);
xfilter: url(#minimapDropShadow_qwpyza);
cursor: move;
}

View file

@ -0,0 +1,150 @@
// svg mini map in d3 version 4
// usage:
// d3.graphxq.svgpan(d3.selection)
// d3.graphxq.loadurl(url)
// d3.graphxq.resetted()
// @license MIT
// @Copyright 2017 Andy Bunce
var url="/static/graphxq/sample.svg";
d3.graphxq = {};
d3.graphxq.svgpan=function(selection){
var showAxes=true;
var base=selection;
var width=500;
var height=500;
var svg = selection.append("svg")
.attr("class", "svg canvas")
.attr("width", "100%")
.attr("height", "100%")
.attr("viewBox", "0 0 "+width + " "+height)
.attr("shape-rendering", "auto");
var svgDefs = svg.append("defs");
svgDefs.append("clipPath")
.attr("id", "wrapperClipPath_qwpyza")
.attr("class", "wrapper clipPath")
.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
svgDefs.append("clipPath")
.attr("id", "minimapClipPath_qwpyza")
.attr("class", "minimap clipPath")
.attr("width", width)
.attr("height", height)
//.attr("transform", "translate(" + (width + minimapPadding) + "," + (minimapPadding/2) + ")")
.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height);
var filter = svgDefs.append("svg:filter")
.attr("id", "minimapDropShadow_qwpyza")
.attr("x", "-20%")
.attr("y", "-20%")
.attr("width", "150%")
.attr("height", "150%");
filter.append("svg:feOffset")
.attr("result", "offOut")
.attr("in", "SourceGraphic")
.attr("dx", "1")
.attr("dy", "1");
filter.append("svg:feColorMatrix")
.attr("result", "matrixOut")
.attr("in", "offOut")
.attr("type", "matrix")
.attr("values", "0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.1 0 0 0 0 0 0.5 0");
filter.append("svg:feGaussianBlur")
.attr("result", "blurOut")
.attr("in", "matrixOut")
.attr("stdDeviation", "10");
filter.append("svg:feBlend")
.attr("in", "SourceGraphic")
.attr("in2", "blurOut")
.attr("mode", "normal");
var zoom = d3.zoom()
.scaleExtent([ .5, 60 ])
.translateExtent([ [ -100, -100 ], [ width + 90, height + 100 ] ])
var xScale = d3.scaleLinear()
.domain([ -1, width + 1 ])
.range([ -1, width + 1 ]);
var yScale = d3.scaleLinear()
.domain([ -1, height + 1 ])
.range([ -1, height + 1 ]);
var xAxis = d3.axisBottom(xScale)
.ticks((width + 2) / (height + 2) * 10)
.tickSize(height)
.tickPadding(8 - height);
var yAxis = d3.axisRight(yScale)
.ticks(10)
.tickSize(width)
.tickPadding(8 - width);
var view = svg.append("g")
var back = view.append("rect")
.attr("class", "view")
.attr("x", 0.5)
.attr("y", 0.5)
.attr("width", width - 1)
.attr("height", height - 1)
.attr("class", "background");
var target = view.append("g");
var gX = svg.append("g")
.attr("class", "axis axis--x");
if(showAxes)gX.call(xAxis);
var gY = svg.append("g")
.attr("class", "axis axis--y");
if(showAxes)gY.call(yAxis);
var zoomed=function () {
console.log("zoomed: ",d3.event.transform);
view.attr("transform", d3.event.transform);
if(showAxes){
gX.call(xAxis.scale(d3.event.transform.rescaleX(xScale)));
gY.call(yAxis.scale(d3.event.transform.rescaleY(yScale)));
}
};
zoom.on("zoom", zoomed);
var resetted=function () {
svg.transition()
.duration(750)
.call(zoom.transform, d3.zoomIdentity);
};
d3.select("button.reset").on("click", resetted);
var loaded=function (){
loadurl(url);
};
var loadurl=function(url){
d3.xml(url,
function(xml) {
var load=xml.documentElement;
var tn=target.node();
while (tn.hasChildNodes()) {
tn.removeChild(tn.lastChild);
};
target.node().appendChild(load);
});
};
d3.select("button.load").on("click", loaded);
svg.call(zoom);
};

View file

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html>
<head id="head">
<meta charset="utf-8">
<title id="title">d3-v4zoom</title>
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="graphviz tool">
<meta name="author" content="andy bunce">
<link
href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css"
rel="stylesheet" type="text/css">
<link href="svg-pan-zoom.css" rel="stylesheet" type="text/css">
<style>
.axis path {
display: none;
}
.axis line {
stroke-opacity: 0.3;
shape-rendering: crispEdges;
}
.view {
fill: url(#gradient);
stroke: #000;
}
.buttons {
position: absolute;
right: 30px;
top: 30px;
}
</style>
<script src="http://d3js.org/d3.v4.js" charset="utf-8"></script>
<head>
<body>
<div class="row">
</div>
<div class="row">
<div class="col-md-6" id="leftPane"> Left </div>
<div class="col-md-6" >
<div class="buttons">
<button class="reset">Reset</button>
<button class="load">Load</button>
</div>
<div id="canvasQwpYZa" class="canvas" style="width: 800px; height: 500px;"></div>
</div>
</div>
<script src="svg-pan-zoom2.js" charset="utf-8"></script>
<script >
var canvas = d3.graphxq.svgpan(d3.select("#canvasQwpYZa"));
</script>
</body>
</html>