diff --git a/layout.force.js b/layout.force.js index a35049c..adf71fd 100644 --- a/layout.force.js +++ b/layout.force.js @@ -57,17 +57,23 @@ var LayoutForce = (function () { var svg = d3.select('#' + this.stageId); // Linksを反映 - var edge = svg.selectAll('.link').data(this.links).enter().append('line').attr('class', 'link').style('stroke', function (d) { + var e = svg.selectAll('.link').data(this.links); + var edge = e.enter().append('line').attr('class', 'link').attr('id', function (d) { + return 'link-to-' + d.target.id; + }).style('stroke', function (d) { return _this.getEdgeColorByTargetNodeType(d.target.type); }).style('stroke-width', function (d) { if (d.value !== undefined) return d.value; return 1; }); - svg.selectAll('link').data(this.links).exit().remove(); + e.exit().remove(); // Nodesを反映 - var node = svg.selectAll('.node').data(this.nodes).enter().append('g').attr('class', 'node').call(this.force.drag); - svg.selectAll('.node').data(this.nodes).exit().remove(); + var n = svg.selectAll('.node').data(this.nodes); + var node = n.enter().append('g').attr('id', function (d) { + return 'node-' + d.id; + }).attr('class', 'node').call(this.force.drag); + n.exit().remove(); // Node.Circlesを反映 var circle = node.append('circle').attr('r', function (d) { @@ -163,6 +169,19 @@ var LayoutForce = (function () { key: 'removeLinkById', value: function removeLinkById(id, redraw) {} + // ノードとリンクのペアを削除する + }, { + key: 'removeNode', + value: function removeNode(nodeId, redraw) { + this.nodes = this.nodes.filter(function (node) { + return node.id == nodeId ? null : node; + }); + this.links = this.links.filter(function (link) { + return link.target.id == nodeId ? null : link; + }); + this.drawGraph(); + } + // canvasサイズを設定する }, { key: 'setGraphSize', diff --git a/layout.force.miil.js b/layout.force.miil.js index 874d07e..2e4fa17 100644 --- a/layout.force.miil.js +++ b/layout.force.miil.js @@ -105,12 +105,14 @@ var MiilGraph = (function (_LayoutForce) { photos.forEach(function (photo_json) { var parentNodeId = photo_json[pid]; var me = { + pid: parentNodeId, id: photo_json.id, title: photo_json.title, type: 'photo', photo_url: photo_json.url, page_url: photo_json.page_url, - group: parentNodeId + group: parentNodeId, + visible: true }; self.addNode(me); var parent = self.getNodeById(parentNodeId); @@ -131,6 +133,23 @@ var MiilGraph = (function (_LayoutForce) { // TODO: `m`を使わない場合どうすれば良いのかわからない m.parseMiilPhotos(callback_res, 'subcategory', m); } + }, { + key: 'closeNodeExceptNodeId', + value: function closeNodeExceptNodeId(id) { + var _this3 = this; + + var nodes = this.getNodesAll(); + var del_nodeIds = []; + nodes.forEach(function (node) { + if (node.type === 'photo' && node.pid != id) { + del_nodeIds.push(node.id); + } + }); + + del_nodeIds.forEach(function (nid) { + _this3.removeNode(nid, true); + }); + } // @Override }, { @@ -145,11 +164,11 @@ var MiilGraph = (function (_LayoutForce) { }, { key: 'appLoad', value: function appLoad() { - var _this3 = this; + var _this4 = this; miil_categories.forEach(function (cate) { if (cate.category_id !== 588 && cate.category_id !== 589) { - _this3.parseMiilCategories(cate, [_this3.getNodeIdxById('miilroot')]); + _this4.parseMiilCategories(cate, [_this4.getNodeIdxById('miilroot')]); } }); this.drawGraph(); @@ -169,11 +188,14 @@ var MiilGraph = (function (_LayoutForce) { this.parseMiilSubCategories(id); console.info(node); } else if (type === 'subcategory') { + // 自身以外のサブカテゴリに属するコンテンツを非表示にする + this.closeNodeExceptNodeId(id); // サブカテゴリに属するコンテンツを展開する var baseApi = 'https://api.miil.me/api/photos/recent/categories/' + node.id; var api = this.getMiilApiUrl(baseApi, node.nextUrl, 'callback=ps'); d3.jsonp(api, null); } else if (type === 'user') { + this.closeNodeExceptNodeId(id); var userName = node.title; var baseApi = 'https://api.miil.me/api/users/' + userName + '/photos/public'; var api = this.getMiilApiUrl(baseApi, node.nextUrl, 'callback=pu'); diff --git a/src/LayoutForce.js b/src/LayoutForce.js index 877d4ff..08c2e3f 100644 --- a/src/LayoutForce.js +++ b/src/LayoutForce.js @@ -40,13 +40,17 @@ class LayoutForce { } drawGraph () { - var self =this; + var self = this; var svg = d3.select('#' + this.stageId); // Linksを反映 - var edge = svg.selectAll('.link').data(this.links).enter() + var e = svg.selectAll('.link').data(this.links); + var edge = e.enter() .append('line') .attr('class', 'link') + .attr('id', d => { + return 'link-to-' + (d.target.id); + }) .style('stroke', d => { return this.getEdgeColorByTargetNodeType(d.target.type); }) @@ -54,14 +58,18 @@ class LayoutForce { if (d.value !== undefined) return d.value; return 1; }); - svg.selectAll('link').data(this.links).exit().remove(); + e.exit().remove(); // Nodesを反映 - var node = svg.selectAll('.node').data(this.nodes).enter() + var n = svg.selectAll('.node').data(this.nodes); + var node = n.enter() .append('g') + .attr('id', d => { + return 'node-' + d.id; + }) .attr('class', 'node') .call(this.force.drag); - svg.selectAll('.node').data(this.nodes).exit().remove(); + n.exit().remove(); // Node.Circlesを反映 var circle = node.append('circle') @@ -157,6 +165,17 @@ class LayoutForce { } + // ノードとリンクのペアを削除する + removeNode (nodeId, redraw) { + this.nodes = this.nodes.filter(node => { + return (node.id == nodeId) ? null : node; + }); + this.links = this.links.filter(link => { + return (link.target.id == nodeId) ? null : link; + }); + this.drawGraph(); + } + // canvasサイズを設定する setGraphSize () { var width = window.innerWidth - this.widthPhotoGallery; diff --git a/src/MiilGraph.js b/src/MiilGraph.js index 7a02255..604e3d6 100644 --- a/src/MiilGraph.js +++ b/src/MiilGraph.js @@ -73,13 +73,15 @@ class MiilGraph extends LayoutForce { photos.forEach(photo_json => { var parentNodeId = photo_json[pid]; var me = { + pid: parentNodeId, id: photo_json.id, title: photo_json.title, type: 'photo', photo_url: photo_json.url, page_url: photo_json.page_url, - group: parentNodeId - } + group: parentNodeId, + visible: true + }; self.addNode(me); var parent = self.getNodeById(parentNodeId); parent.nextUrl = nextUrl; @@ -98,6 +100,20 @@ class MiilGraph extends LayoutForce { m.parseMiilPhotos(callback_res, 'subcategory', m); } + closeNodeExceptNodeId (id) { + var nodes = this.getNodesAll(); + var del_nodeIds = []; + nodes.forEach(node => { + if (node.type === 'photo' && node.pid != id) { + del_nodeIds.push(node.id); + } + }); + + del_nodeIds.forEach(nid => { + this.removeNode(nid, true); + }); + } + // @Override getFillColorByNodeType (type) { if (type === 'user' || type === 'root') return '#F4433C'; @@ -127,11 +143,14 @@ class MiilGraph extends LayoutForce { this.parseMiilSubCategories(id); console.info(node); }else if (type === 'subcategory') { + // 自身以外のサブカテゴリに属するコンテンツを非表示にする + this.closeNodeExceptNodeId(id); // サブカテゴリに属するコンテンツを展開する var baseApi = 'https://api.miil.me/api/photos/recent/categories/' + node.id; var api = this.getMiilApiUrl(baseApi, node.nextUrl, 'callback=ps'); d3.jsonp(api, null); }else if (type === 'user') { + this.closeNodeExceptNodeId(id); var userName = node.title; var baseApi = 'https://api.miil.me/api/users/'+ userName +'/photos/public'; var api = this.getMiilApiUrl(baseApi, node.nextUrl, 'callback=pu');