Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@
dist/*
!dist/js/
node_modules/
images/
json/

# uncomment to block committing copyright images
# images/
# json/
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ tech-tree-js
===
![tech tree example](https://user-images.githubusercontent.com/1187476/30304466-a83803f6-973b-11e7-85ec-88988919b151.png)

# Update
If you use react, consider taking a look at my library [react-tech-tree](https://github.com/ldd/react-tech-tree). It has support for tooltips, styling, etc.


# Demo
Please check out the demo by visiting [https://ldd.github.io/tech-tree-js](https://ldd.github.io/tech-tree-js)

Expand Down
2 changes: 1 addition & 1 deletion dist/js/techTree.min.js.map

Large diffs are not rendered by default.

49 changes: 28 additions & 21 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
var gulp = require('gulp'),
gulpIf = require('gulp-if'),
gulpCopy = require('gulp-copy');
var gulp = require("gulp"),
gulpIf = require("gulp-if"),
gulpCopy = require("gulp-copy");

var useref = require('gulp-useref'),
uglify = require('gulp-uglify'),
sourcemaps = require('gulp-sourcemaps'),
lazypipe = require('lazypipe');
var useref = require("gulp-useref"),
uglify = require("gulp-uglify"),
sourcemaps = require("gulp-sourcemaps"),
lazypipe = require("lazypipe");

var webserver = require('gulp-webserver');
var webserver = require("gulp-webserver");

gulp.task('serve', function() {
gulp.src('.')
.pipe(webserver({}));
gulp.task("serve", function() {
gulp.src(".").pipe(webserver({}));
});

gulp.task('useref', function(){
return gulp.src('index.html')
.pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true })))
.pipe(gulpIf('js/*.js', uglify()))
.pipe(gulpIf('js/*.js', sourcemaps.write('.')))
.pipe(gulp.dest('dist'));
gulp.task("useref", function() {
return gulp
.src("index.html")
.pipe(
useref(
{},
lazypipe().pipe(
sourcemaps.init,
{ loadMaps: true }
)
)
)
.pipe(gulpIf("js/*.js", uglify()))
.pipe(gulpIf("js/*.js", sourcemaps.write(".")))
.pipe(gulp.dest("dist"));
});

gulp.task('copyImages', function(){
return gulp.src(['images/**/*.png'])
.pipe(gulpCopy('dist'));
gulp.task("copyImages", function() {
return gulp.src(["images/**/*.png"]).pipe(gulpCopy("dist"));
});

gulp.task('default', ['copyImages','useref']);
gulp.task("default", ["copyImages", "useref"]);
Binary file added images/high_res/beam-blue-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/beam-red-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/explosion-red-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/fire-arrows-sky-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/fireball-acid-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/fireball-eerie-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/light-jade-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/light-royal-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/needles-fire-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/high_res/wind-blue-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/beam-blue-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/beam-red-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/explosion-red-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/fire-arrows-sky-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/fireball-acid-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/fireball-eerie-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/light-jade-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/light-royal-3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/needles-fire-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/low_res/wind-blue-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/spriteSheet.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 23 additions & 21 deletions js/eventHelper.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
var techTree = (function(api){
// Toggle children on click.
api.clickHandler = function clickHandler(d, nodesByName) {
if(!d.selected){
var otherSelected = true;
if(d.requirements && d.requirements.length){
for(var i=0;i< d.requirements.length; i+=1){
otherSelected = otherSelected && (nodesByName[d.requirements[i]].datum().selected === true);
}
}
if(otherSelected){
d.selected = true;
techTree.updateNode(nodesByName[d.name]);
techTree.updateLinks(d, nodesByName);
}
var techTree = (function(api) {
// Toggle children on click.
api.clickHandler = function clickHandler(d, nodesByName) {
if (!d.selected) {
var otherSelected = true;
if (d.requirements && d.requirements.length) {
for (var i = 0; i < d.requirements.length; i += 1) {
otherSelected =
otherSelected &&
nodesByName[d.requirements[i]].datum().selected === true;
}
};
d3.select(api.settings.downloadWrapper).on("click", function(){
saveSvgAsPng(d3.select("svg").node(),api.settings.imageDownloadFileName);
});
return api;
}(techTree || {}));
}
if (otherSelected) {
d.selected = true;
techTree.updateNode(nodesByName[d.name]);
techTree.updateLinks(d, nodesByName);
}
}
};
d3.select(api.settings.downloadWrapper).on("click", function() {
saveSvgAsPng(d3.select("svg").node(), api.settings.imageDownloadFileName);
});
return api;
})(techTree || {});
97 changes: 50 additions & 47 deletions js/imageUtils.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,52 @@
var techTree = (function(api){
api.setupImageUtils = function setupImageUtils(container){
container.append("filter")
.attr("id","desaturate")
.append("feColorMatrix")
.attr("type","matrix")
.attr("values","0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0");
var techTree = (function(api) {
api.setupImageUtils = function setupImageUtils(container) {
container
.append("filter")
.attr("id", "desaturate")
.append("feColorMatrix")
.attr("type", "matrix")
.attr(
"values",
"0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"
);

var shadow = container
.append("filter")
.attr("id","dropshadow")
.attr("filterUnits","userSpaceOnUse")
.attr("color-interpolation-filters","sRGB")
.attr("height","130%")
.append("feGaussianBlur")
.attr("stdDeviation","2")
.append("feComponentTransfer")
.attr("in","SourceAlpha")
.append("feFuncR")
.attr("type","discrete")
.attr("tableValues","0")
;
shadow
.append("feOffset")
.attr("dx","2")
.attr("dy","2")
.attr("result","offsetblur")
.append("feMerge")
.append("feMergeNode")
.attr("in","SourceGraphics");
//.append("feMergeNode");
var shadow = container
.append("filter")
.attr("id", "dropshadow")
.attr("filterUnits", "userSpaceOnUse")
.attr("color-interpolation-filters", "sRGB")
.attr("height", "130%")
.append("feGaussianBlur")
.attr("stdDeviation", "2")
.append("feComponentTransfer")
.attr("in", "SourceAlpha")
.append("feFuncR")
.attr("type", "discrete")
.attr("tableValues", "0");
shadow
.append("feOffset")
.attr("dx", "2")
.attr("dy", "2")
.attr("result", "offsetblur")
.append("feMerge")
.append("feMergeNode")
.attr("in", "SourceGraphics");
//.append("feMergeNode");

if(api.settings.useSpriteSheet) {
var offset;
Object.keys(api.offsets).forEach(function (offsetKey) {
offset = api.offsets[offsetKey];
d3.select("svg")
.append("clipPath")
.attr("id", "clip-" + offsetKey)
.append("rect")
.attr("x", offset.x)
.attr("y", offset.y)
.attr("width", offset.w)
.attr("height", offset.h);
});
}
};
return api;
}(techTree || {}));
if (api.settings.useSpriteSheet) {
var offset;
Object.keys(api.offsets).forEach(function(offsetKey) {
offset = api.offsets[offsetKey];
d3.select("svg")
.append("clipPath")
.attr("id", "clip-" + offsetKey)
.append("rect")
.attr("x", offset.x)
.attr("y", offset.y)
.attr("width", offset.w)
.attr("height", offset.h);
});
}
};
return api;
})(techTree || {});
34 changes: 20 additions & 14 deletions js/jsonLoader.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
var techTree = (function(api){
api.createTreeFromJSON = function(config){
d3.json(config.offsetsFileName, function(error, jsonOffsets){
if (error) {return console.warn(error);}
d3.json(config.dataFileName, function(error, json) {
if (error) {return console.warn(error);}
d3.json(config.settingsFileName, function(error, settings) {
if (error) {return console.warn(error);}
techTree.createTree(json.nodes, settings, jsonOffsets);
});
});
var techTree = (function(api) {
api.createTreeFromJSON = function(config) {
d3.json(config.offsetsFileName, function(error, jsonOffsets) {
if (error) {
return console.warn(error);
}
d3.json(config.dataFileName, function(error, json) {
if (error) {
return console.warn(error);
}
d3.json(config.settingsFileName, function(error, settings) {
if (error) {
return console.warn(error);
}
techTree.createTree(json.nodes, settings, jsonOffsets);
});
};
});
});
};

return api;
}(techTree || {}));
return api;
})(techTree || {});
101 changes: 52 additions & 49 deletions js/linkHelper.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,56 @@
var techTree = (function(api){
var linksBySource = {};
var techTree = (function(api) {
var linksBySource = {};

api.initializeLinks = function initializeLinks(links){
links.enter().insert("path", "g")
.attr("class", "link")
.attr("id", function(pLink){
linksBySource[pLink.source.name] = linksBySource[pLink.source.name] || [];
linksBySource[pLink.source.name].push(d3.select(this));
return pLink.source.name+"-"+pLink.target.name;
})
.attr("d",api.lineFunction)
.style("stroke",function(pLink){
return pLink.source.selected? "#FFBB33": api.settings.initialLinkColor;
});
};
api.updateLinks = function updateLinks(node, nodesByName){
api.initializeLinks = function initializeLinks(links) {
links
.enter()
.insert("path", "g")
.attr("class", "link")
.attr("id", function(pLink) {
linksBySource[pLink.source.name] =
linksBySource[pLink.source.name] || [];
linksBySource[pLink.source.name].push(d3.select(this));
return pLink.source.name + "-" + pLink.target.name;
})
.attr("d", api.lineFunction)
.style("stroke", function(pLink) {
return pLink.source.selected
? "#FFBB33"
: api.settings.initialLinkColor;
});
};
api.updateLinks = function updateLinks(node, nodesByName) {
var links = linksBySource[node.name];
if (links && links.length) {
for (var i = 0; i < links.length; i += 1) {
links[i]
.transition()
.duration(api.durations.activateLink)
.style("stroke", "#FFBB33");

var links = linksBySource[node.name];
if(links && links.length){
for (var i=0;i<links.length;i+=1) {
links[i]
.transition()
.duration(api.durations.activateLink)
.style("stroke", "#FFBB33");
var d = links[i].datum().target;
var name = d.name;
var selectable = true;

var d = links[i].datum().target;
var name = d.name;
var selectable = true;

if(d.requirements){
for(var j=0;j< d.requirements.length; j+=1){
var other = nodesByName[d.requirements[j]].datum();
selectable = selectable && other.selected;
d3
.transition()
.duration(api.durations.activateLink)
.select("#"+other.name+"-"+d.name)
.style("stroke",other.selected? "#FFBB33": "#ccc");
}
}
if(selectable){
nodesByName[name]
.transition()
.duration(api.durations.activateLink)
.select("rect").style("stroke", "#FFBB33");
}

}
if (d.requirements) {
for (var j = 0; j < d.requirements.length; j += 1) {
var other = nodesByName[d.requirements[j]].datum();
selectable = selectable && other.selected;
d3.transition()
.duration(api.durations.activateLink)
.select("#" + other.name + "-" + d.name)
.style("stroke", other.selected ? "#FFBB33" : "#ccc");
}
}
if (selectable) {
nodesByName[name]
.transition()
.duration(api.durations.activateLink)
.select("rect")
.style("stroke", "#FFBB33");
}
};
return api;
}(techTree || {}));
}
}
};
return api;
})(techTree || {});
Loading