Skip to content

Instantly share code, notes, and snippets.

@andreaderrico2
Last active December 10, 2019 07:51
Show Gist options
  • Save andreaderrico2/33d883b716f3c0ff46ffdc0bea8eaee0 to your computer and use it in GitHub Desktop.
Save andreaderrico2/33d883b716f3c0ff46ffdc0bea8eaee0 to your computer and use it in GitHub Desktop.
OpenSeaDragon with ESRI tiles + SVG overlay
openseadragon_config = {
id: "openseadragon",
prefixUrl: "https://rawgit.com/fabiovalse/Hub/master/lib/openseadragon/images/",
wrapHorizontal: false,
defaultZoomLevel: 0,
minZoomLevel: 0,
tileSources: {
height: (1<<23)*256
width: (1<<23)*256
tileSize: 256
getTileUrl: (z, x, y) -> "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/#{z-9}/#{y}/#{x}"
}
}
d3.json 'http://wafi.iit.cnr.it/webvis/dev/osiris_db_viewer/data/first5k.json', (data)->
projection = d3.geoMercator()
.translate [0.5, 0.5]
.scale 1/(2*Math.PI)
data = data.map (d) ->
proj_point = projection [d.lon, d.lat]
d.x = proj_point[0]
d.y = proj_point[1]
return d
#lat = 43.715927
#lon = 10.401987
#lat_paris = 48.864716
#lon_paris = 2.349014
overlay_data = {
selector: 'circle',
data: data
}
app = new Vue
el: '#app'
data:
openseadragon_config: openseadragon_config
overlay_data: overlay_data
components:
openseadragon: window.OpenSeadragonComponent
template: '''
<div>
<openseadragon :config="openseadragon_config" :overlay="overlay_data"></openseadragon>
</div>
'''
body, html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#openseadragon {
width: 100%;
height: 100%;
background: #000;
}
circle {
fill: red;
stroke: #FFF;
stroke-width: 1px;
vector-effect: non-scaling-stroke;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>OpenSeadragon with ESRI tiles + SVG overlay</title>
<link type="text/css" href="index.css" rel="stylesheet"/>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<script src="https://rawgit.com/fabiovalse/Hub/master/lib/openseadragon/openseadragon.min.js"></script>
<script src="openseadragon-svg-overlay.js"></script>
</head>
<body>
<div id="app"></div>
<script src="OverlayComponent.js"></script>
<script src="OpenSeadragon.js"></script>
<script src="index.js"></script>
</body>
</html>
// Generated by CoffeeScript 1.10.0
(function() {
var openseadragon_config;
openseadragon_config = {
id: "openseadragon",
prefixUrl: "https://rawgit.com/fabiovalse/Hub/master/lib/openseadragon/images/",
wrapHorizontal: false,
defaultZoomLevel: 0,
minZoomLevel: 0,
tileSources: {
height: (1 << 23) * 256,
width: (1 << 23) * 256,
tileSize: 256,
getTileUrl: function(z, x, y) {
return "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/" + (z - 9) + "/" + y + "/" + x;
}
}
};
d3.json('http://wafi.iit.cnr.it/webvis/dev/osiris_db_viewer/data/first5k.json', function(data) {
var app, overlay_data, projection;
projection = d3.geoMercator().translate([0.5, 0.5]).scale(1 / (2 * Math.PI));
data = data.map(function(d) {
var proj_point;
proj_point = projection([d.lon, d.lat]);
d.x = proj_point[0];
d.y = proj_point[1];
return d;
});
overlay_data = {
selector: 'circle',
data: data
};
return app = new Vue({
el: '#app',
data: {
openseadragon_config: openseadragon_config,
overlay_data: overlay_data
},
components: {
openseadragon: window.OpenSeadragonComponent
},
template: '<div>\n <openseadragon :config="openseadragon_config" :overlay="overlay_data"></openseadragon> \n</div>'
});
});
}).call(this);
// OpenSeadragon SVG Overlay plugin 0.0.4
(function() {
if (!window.OpenSeadragon) {
console.error('[openseadragon-svg-overlay] requires OpenSeadragon');
return;
}
var svgNS = 'http://www.w3.org/2000/svg';
// ----------
OpenSeadragon.Viewer.prototype.svgOverlay = function() {
if (this._svgOverlayInfo) {
return this._svgOverlayInfo;
}
this._svgOverlayInfo = new Overlay(this);
return this._svgOverlayInfo;
};
// ----------
var Overlay = function(viewer) {
var self = this;
this._viewer = viewer;
this._containerWidth = 0;
this._containerHeight = 0;
this._svg = document.createElementNS(svgNS, 'svg');
this._svg.style.position = 'absolute';
this._svg.style.left = 0;
this._svg.style.top = 0;
this._svg.style.width = '100%';
this._svg.style.height = '100%';
this._viewer.canvas.appendChild(this._svg);
this._node = document.createElementNS(svgNS, 'g');
this._svg.appendChild(this._node);
this._viewer.addHandler('animation', function() {
self.resize();
});
this._viewer.addHandler('open', function() {
self.resize();
});
this._viewer.addHandler('rotate', function(evt) {
self.resize();
});
this._viewer.addHandler('resize', function() {
self.resize();
});
this.resize();
};
// ----------
Overlay.prototype = {
// ----------
node: function() {
return this._node;
},
// ----------
resize: function() {
if (this._containerWidth !== this._viewer.container.clientWidth) {
this._containerWidth = this._viewer.container.clientWidth;
this._svg.setAttribute('width', this._containerWidth);
}
if (this._containerHeight !== this._viewer.container.clientHeight) {
this._containerHeight = this._viewer.container.clientHeight;
this._svg.setAttribute('height', this._containerHeight);
}
var p = this._viewer.viewport.pixelFromPoint(new OpenSeadragon.Point(0, 0), true);
var zoom = this._viewer.viewport.getZoom(true);
var rotation = this._viewer.viewport.getRotation();
// TODO: Expose an accessor for _containerInnerSize in the OSD API so we don't have to use the private variable.
var scale = this._viewer.viewport._containerInnerSize.x * zoom;
this._node.setAttribute('transform',
'translate(' + p.x + ',' + p.y + ') scale(' + scale + ') rotate(' + rotation + ')');
},
// ----------
onClick: function(node, handler) {
// TODO: Fast click for mobile browsers
new OpenSeadragon.MouseTracker({
element: node,
clickHandler: handler
}).setTracking(true);
}
};
})();
window.OpenSeadragonComponent =
props:
config:
type: Object
required: true
overlay:
type: Object
mounted: () ->
### OpenSeadragon viewer creation
###
@viewer = OpenSeadragon @config
svg_overlay = @viewer.svgOverlay()
@viewer.addHandler('open', (event) =>
@viewer.controls[0].destroy()
#@viewer.viewport.panTo(new OpenSeadragon.Point(0.55,0.39),true)
OverlayComponent = Vue.extend(window.OverlayComponent)
overlay_component = new OverlayComponent({propsData: {data: @overlay.data}})
overlay_component.$mount()
@$el.querySelector('svg g').appendChild(overlay_component.$el)
)
@viewer.addHandler 'zoom', (event) =>
@$el.querySelectorAll('svg g circle').forEach (d) -> d.setAttribute('r', 0.001/event.zoom)
template: '''
<div id="openseadragon"></div>
'''
// Generated by CoffeeScript 1.10.0
(function() {
window.OpenSeadragonComponent = {
props: {
config: {
type: Object,
required: true
},
overlay: {
type: Object
}
},
mounted: function() {
/* OpenSeadragon viewer creation
*/
var svg_overlay;
this.viewer = OpenSeadragon(this.config);
svg_overlay = this.viewer.svgOverlay();
this.viewer.addHandler('open', (function(_this) {
return function(event) {
var OverlayComponent, overlay_component;
_this.viewer.controls[0].destroy();
OverlayComponent = Vue.extend(window.OverlayComponent);
overlay_component = new OverlayComponent({
propsData: {
data: _this.overlay.data
}
});
overlay_component.$mount();
return _this.$el.querySelector('svg g').appendChild(overlay_component.$el);
};
})(this));
return this.viewer.addHandler('zoom', (function(_this) {
return function(event) {
return _this.$el.querySelectorAll('svg g circle').forEach(function(d) {
return d.setAttribute('r', 0.001 / event.zoom);
});
};
})(this));
},
template: '<div id="openseadragon"></div>'
};
}).call(this);
window.OverlayComponent =
props:
data:
type: Array
required: true
template: '''
<g>
<circle v-for="d in data" :cx="d.x" :cy="d.y" r="0.00001"><title>{{d.ship_name+" "+d.datetime}}</title></circle>
</g>
'''
// Generated by CoffeeScript 1.10.0
(function() {
window.OverlayComponent = {
props: {
data: {
type: Array,
required: true
}
},
template: '<g>\n <circle v-for="d in data" :cx="d.x" :cy="d.y" r="0.00001"><title>{{d.ship_name+" "+d.datetime}}</title></circle>\n</g>'
};
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment