block by shimizu 2675d59f526a80b02d8db8c26ab0e45d

D3 & A-frame example1

Full Screen

A-frameとD3を組み合わせて使うサンプル。

localで動かしたいときは以下を。

$ git clone git@gist.github.com:2675d59f526a80b02d8db8c26ab0e45d.git
$ cd 2675d59f526a80b02d8db8c26ab0e45d
$ npm install
$ npm start

script.jsの中身を修正したい場合は、ビルドツールが使う依存モジュールのインストールが必要です。

$ npm run installDevtool
$ npm start

Made with blockup

script.js

const poStrfy = (x, y, z) => [x, y, z].join(" ");

const cast = d => {
  Object.keys(d).forEach(key => {
    if (!isNaN(+d[key])) d[key] = +d[key];
  });
  return d;
};

//データの読み込み
d3.tsv("data.tsv", cast, main);

function main(data) {
  //a-frameのscenエレメントにデータをバインド
  const scene1 = d3.select("#scene1").datum(data);
  //データの値をa-frameのhigth値に正規化する関数
  scene1._scale = d3
    .scaleLinear()
    .domain([0, 400])
    .range([0, 20])
    .nice();
  //a-frame Entityをd3を使って生成
  scene1.call(addEntity);
}

function addEntity(_selection) {
  //a-entity -> a-boxをsceneエレメントにバインドされた値から生成
  var bar = _selection
    .selectAll(".bar")
    .data(d => d)
    .enter()
    .append("a-entity")
    .attr("class", "bar")
    .append("a-box")
    .attr("class", (d, i) => "box box" + i)
    .attr("color", "red")
    .attr("position", (d, i) => {
      return poStrfy(i * 1.1, -1, -5);
    })
    .attr("height", 0) //アニメーションの為に初期値を0としている
    .on("mouseenter", function(d) {
      bar.attr("color", "red");
      d3.select(this).attr("color", "blue");
      //d3でa-boxにバインドしたデータを取り出すことができる。
      console.log(d);
    });

  // d3.jsのトランジション機能を使ってa-frameのエンティティをアニメーションさせる。
  // 通常の.attrを使ったトランジションは補完値をあトリビュートに適用するループが呼ばれないため遷移しない。
  // attrTweenを使い、明示的にトランジションループを回すことでa-frame側にアトリビュートの更新を反映することができる
  bar
    .transition()
    .duration(2000)
    .attrTween("height", (d, i) => {
      var fn = d3.interpolate(0, _selection._scale(d["高さ"]));
      return t => fn(t);
    });
}

index.html

<!DOCTYPE html>
<title>d3 & a-frame example1</title>
<link href='dist.css' rel='stylesheet' />
<script src="//unpkg.com/d3@4.12.2/build/d3.min.js"></script>
<script src="//unpkg.com/aframe@0.7.1/dist/aframe.js"></script>

<body>
<a-scene id="scene1" d3>


    <a-sky radius="5000" color="skyblue"></a-sky>
	<a-plane color="wheat" height="20" width="40" position="0 -1 0" rotation="270 0 0"></a-plane>	  
	        
      <a-entity camera look-controls wasd-controls cursor="rayOrigin: mouse" position="6 0 5">
      </a-entity>
</a-scene>


<script src='dist.js'></script>
</body>

data.tsv

年	建物名	高さ	階数
1935年	三越本店	60	7階
1936年	国会議事堂中央塔	65	9階
1964年	ホテルニューオータニ本館	73	17階
1968年	霞が関ビルディング	156	36階
1970年	世界貿易センタービル	163	40階
1971年	京王プラザホテル	179	47階
1974年	新宿住友ビル	210	52階
1974年	新宿三井ビル	225	55階
1978年	サンシャイン60	239.7	60階
1991年	東京都庁第一本庁舎	243	48階
1993年	横浜ランドマークタワー	296	70階
2014年	あべのハルカス	300	60階

dist.css

/* Do not touch this file - your changes will be overwritten. */

dist.js

!function(t){function n(i){if(c[i])return c[i].exports;var a=c[i]={i:i,l:!1,exports:{}};return t[i].call(a.exports,a,a.exports,n),a.l=!0,a.exports}var c={};n.m=t,n.c=c,n.i=function(t){return t},n.d=function(t,c,i){n.o(t,c)||Object.defineProperty(t,c,{configurable:!1,enumerable:!0,get:i})},n.n=function(t){var c=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(c,"a",c),c},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=0)}([function(module,exports,__webpack_require__){"use strict";eval('\n\nvar poStrfy = function poStrfy(x, y, z) {\n\treturn [x, y, z].join(" ");\n};\n\nvar cast = function cast(d) {\n\tObject.keys(d).forEach(function (key) {\n\t\tif (!isNaN(+d[key])) d[key] = +d[key];\n\t});\n\treturn d;\n};\n\nd3.tsv("data.tsv", cast, main);\n\nfunction main(data) {\n\tvar scene1 = d3.select("#scene1").datum(data);\n\tscene1._scale = d3.scaleLinear().domain([0, 400]).range([0, 20]).nice();\n\tscene1.call(addEntity);\n}\n\nfunction addEntity(_selection) {\n\tvar bar = _selection.selectAll(".bar").data(function (d) {\n\t\treturn d;\n\t}).enter().append("a-entity").attr("class", "bar").append("a-box").attr("class", function (d, i) {\n\t\treturn "box box" + i;\n\t}).attr("color", "red").attr("position", function (d, i) {\n\t\tconsole.log(i);return poStrfy(i * 1.1, -1, -5);\n\t}).attr("height", 0).on("mouseenter", function (d) {\n\t\tbar.attr("color", "red");\n\t\td3.select(this).attr("color", "blue");\n\t\tconsole.log(d);\n\t});\n\n\tbar.transition().duration(2000).attrTween("height", function (d, i) {\n\t\tvar fn = d3.interpolate(0, _selection._scale(d["高さ"]));\n\t\treturn function (t) {\n\t\t\treturn fn(t);\n\t\t};\n\t});\n}//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy9zY3JpcHQuanM/OWE5NSJdLCJzb3VyY2VzQ29udGVudCI6WyJjb25zdCBwb1N0cmZ5ID0gKHgsIHksIHopID0+IFt4LHksel0uam9pbihcIiBcIik7XG5cblxuY29uc3QgY2FzdCA9IChkKSA9PiB7XG5cdE9iamVjdC5rZXlzKGQpLmZvckVhY2goa2V5ID0+IHtcblx0XHRpZighaXNOYU4oK2Rba2V5XSkpIGRba2V5XSA9ICtkW2tleV07XG5cdH0pO1xuXHRyZXR1cm4gZFxufVxuXG5kMy50c3YoXCJkYXRhLnRzdlwiLCBjYXN0ICwgbWFpbik7XG5cbmZ1bmN0aW9uIG1haW4oZGF0YSl7XG5cdGNvbnN0IHNjZW5lMSA9IGQzLnNlbGVjdChcIiNzY2VuZTFcIikuZGF0dW0oZGF0YSk7XHRcdFxuXHRzY2VuZTEuX3NjYWxlID0gZDMuc2NhbGVMaW5lYXIoKS5kb21haW4oWzAsIDQwMF0pLnJhbmdlKFswLCAyMF0pLm5pY2UoKTtcblx0c2NlbmUxLmNhbGwoYWRkRW50aXR5KTtcdFxufVxuXG5cbmZ1bmN0aW9uIGFkZEVudGl0eShfc2VsZWN0aW9uKXtcblx0dmFyIGJhciA9IF9zZWxlY3Rpb24uc2VsZWN0QWxsKFwiLmJhclwiKVxuXHRcdC5kYXRhKGQgPT4gZCApXG5cdFx0LmVudGVyKClcblx0XHQuYXBwZW5kKFwiYS1lbnRpdHlcIilcblx0XHQuYXR0cihcImNsYXNzXCIsIFwiYmFyXCIpXG5cdFx0LmFwcGVuZChcImEtYm94XCIpXG5cdFx0LmF0dHIoXCJjbGFzc1wiLCAoZCxpKSA9PiAgXCJib3ggYm94XCIraSApXG5cdFx0LmF0dHIoXCJjb2xvclwiLCBcInJlZFwiKVxuXHRcdC5hdHRyKFwicG9zaXRpb25cIiwgKGQsaSkgPT57Y29uc29sZS5sb2coaSk7IHJldHVybiBwb1N0cmZ5KGkgKiAxLjEsIC0xLCAtNSkgfSApXG5cdFx0LmF0dHIoXCJoZWlnaHRcIiwgMClcblx0XHQub24oXCJtb3VzZWVudGVyXCIsIGZ1bmN0aW9uKGQpe1xuXHRcdFx0YmFyLmF0dHIoXCJjb2xvclwiLCBcInJlZFwiKTtcblx0XHRcdGQzLnNlbGVjdCh0aGlzKS5hdHRyKFwiY29sb3JcIiwgXCJibHVlXCIpO1xuXHRcdFx0Y29uc29sZS5sb2coZClcblx0XHR9KVxuXHRcdFxuXHRiYXIudHJhbnNpdGlvbigpLmR1cmF0aW9uKDIwMDApXG5cdFx0LmF0dHJUd2VlbihcImhlaWdodFwiLCAoZCxpKSA9PiB7XG5cdFx0XHR2YXIgZm4gPSBkMy5pbnRlcnBvbGF0ZSgwLCBfc2VsZWN0aW9uLl9zY2FsZShkW1wi6auY44GVXCJdKSlcblx0XHRcdHJldHVybiB0ID0+IGZuKHQpIFxuXHRcdH0pXG59XG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIHNjcmlwdC5qcyJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBS0E7QUFBQTtBQUVBO0FBQUE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=')}]);

package.json

{
  "dependencies": {
    "aframe": "^0.7.1",
    "blockup": "^2.2.10",
    "d3": "^4.12.2"
  },
  "name": "d3_aframe_sample1",
  "description": "[Made with blockup](https://github.com/gabrielflorit/blockup)",
  "version": "1.0.0",
  "main": "dist.js",
  "devDependencies": {},
  "scripts": {
    "start": "blockup",
    "installDevtool": "cd node_modules/blockup/; npm install ; cd ../../",
    "check": "blockup check",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

style.styl

*
	box-sizing border-box