Skip to content

Instantly share code, notes, and snippets.

@nitaku
Last active July 27, 2020 02:47
Show Gist options
  • Save nitaku/a2471c06959834d9bcd0 to your computer and use it in GitHub Desktop.
Save nitaku/a2471c06959834d9bcd0 to your computer and use it in GitHub Desktop.
2.5D interactive building

This example shows a method to create an interactive map of a building. Inspired by the wayfinding design solutions commonly found in airports or shopping centers, this map is in 2.5D.

In particular, this example shows how to load an external SVG file with d3.js, how to lower the walls' opacity via CSS to achieve a see-through effect, and how to make some zones of the map interactive (in this case, the rooms).

The SVG is an Inkscape-edited version of multiple PDF exports from Trimble's Sketchup, an easy to use, freeware 3D graphic software. In order for this method to work, manual editing of the SVG and the adherence to a formal set of IDs, classes and layer names are required, making the solution not trivial to maintain. Despite this, the proposed solution achieves high levels of both aesthetical value and clarity of representation.

Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
load_svg = (filename, container, fit, callback) ->
d3.xml filename, (error, documentFragment) ->
throw error if error
svg_dom = documentFragment
.getElementsByTagName("svg")[0]
d3.select(container).node().appendChild(svg_dom)
svg_d3 = d3.select(container).select('svg')
if fit
svg_d3
.attr('width', '100%')
.attr('height', '100%')
callback(svg_d3)
load_svg 'building.svg', '#vis', true, (svg) ->
svg
.attr
width: '960px'
height: '500px'
# add a title to all active elements (their ID)
actives = svg.selectAll('.active')
actives.each () ->
active = d3.select(this)
active.datum({id: active.attr('id')})
actives.append('title')
.text((d) -> d.id )
svg * {
pointer-events: none;
}
.active {
pointer-events: all;
fill: #DDD;
}
.active:hover {
fill: orange;
}
#ground_walls {
opacity: 0.2 !important;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" type="text/css" href="index.css">
<title>2.5D interactive building</title>
</head>
<body>
<div id="vis"></div>
<script src="index.js"></script>
</body>
</html>
// Generated by CoffeeScript 1.4.0
(function() {
var load_svg;
load_svg = function(filename, container, fit, callback) {
return d3.xml(filename, function(error, documentFragment) {
var svg_d3, svg_dom;
if (error) {
throw error;
}
svg_dom = documentFragment.getElementsByTagName("svg")[0];
d3.select(container).node().appendChild(svg_dom);
svg_d3 = d3.select(container).select('svg');
if (fit) {
svg_d3.attr('width', '100%').attr('height', '100%');
}
return callback(svg_d3);
});
};
load_svg('building.svg', '#vis', true, function(svg) {
var actives;
svg.attr({
width: '960px',
height: '500px'
});
actives = svg.selectAll('.active');
actives.each(function() {
var active;
active = d3.select(this);
return active.datum({
id: active.attr('id')
});
});
return actives.append('title').text(function(d) {
return d.id;
});
});
}).call(this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment