Guest User

Untitled

a guest
Oct 23rd, 2017
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.77 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html>
  3.  
  4. <head>
  5. <meta charset="UTF-8">
  6. <title>D3 Parliament Power Measures: Spanish parliament 2015 Case Study</title>
  7. <meta charset="utf-8">
  8. <meta name="viewport" content="width=device-width, initial-scale=1">
  9. <style>
  10. #buttoms {
  11. padding: 0 0 0 0;
  12. margin: 0 0 0 0;
  13. }
  14.  
  15. #spanish_parliament_div {
  16. font-family: "Roboto", sans-serif;
  17. color: #333333;
  18. font-weight: 500;
  19. font-size: 18px;
  20. border-radius: 5px 5px 0 0;
  21. padding-top: 0px;
  22. padding-left: 0px;
  23. margin: 0 0 0 0;
  24. height: 100%;
  25. background-color: #fff;
  26. }
  27. #spanish_parliament_div svg {
  28. width: 100% !important;
  29. height: 100%;
  30. /* Shadow effects */
  31. /* -webkit-filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.3) );
  32. filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.25) );*/
  33. }
  34.  
  35. #spanish_parliament_div .slice {
  36. stroke: white;
  37. stroke-width: 0px;
  38. }
  39.  
  40. #spanish_parliament_div .slice:hover {
  41. opacity: .7;
  42. }
  43.  
  44. #spanish_parliament_div .labels text {
  45. font-style: normal;
  46. font-size: 1.5vw;
  47. background-color: #333;
  48. width: 200px;
  49. /* font-weight: 700;*/
  50. font-style: italic;
  51.  
  52. }
  53.  
  54. #spanish_parliament_div
  55. .hidden {
  56. display: none;
  57. }
  58.  
  59. /*Styling for the lines connecting the labels to the slices*/
  60. #spanish_parliament_div polyline {
  61. opacity: .3;
  62. stroke: black;
  63. stroke-width: 1px;
  64. fill: none;
  65. }
  66. </style>
  67. <script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
  68. <script src="//code.jquery.com/jquery.js"></script>
  69.  
  70. </head>
  71.  
  72. <body>
  73. <div id="buttoms">
  74. <select id="inds_spanish_parliament">
  75. <option value="Seats" selected="selected">Seats</option>
  76. <option value="Proportional">Proportional</option>
  77. <option value="Shapley">Shapley</option>
  78. <option value="Banzhaf">Banzhaf</option>
  79. <option value="Winnable-Ideologia">Winnable-Ideologia</option>
  80. <option value="Worsable-Ideologia">Worsable-Ideologia</option>
  81.  
  82. </select>
  83. </div>
  84. <div id="spanish_parliament_div" class="svg-container" style="width: 100%;"></div>
  85. <script type="text/javascript">
  86. var svg = d3.select("#spanish_parliament_div")
  87. .append("svg")
  88. .append("g");
  89. svg.append("g")
  90. .attr("class", "slices");
  91. svg.append("g")
  92. .attr("class", "labels");
  93. svg.append("g")
  94. .attr("class", "lines");
  95. svg.append("text")
  96. .attr("id", "titleMeasure");
  97. svg.append("g")
  98. .attr("class", "legend")
  99. .attr("id", "LegendParties");
  100. svg.append("line")
  101. .attr("id", "DashedHalfSeparator");
  102. svg.append('text')
  103. .attr("id", "InnerCircleDetails");
  104. svg.append("text")
  105. .attr("id", "HalfIndicator");
  106. var width = $("#spanish_parliament_div").width(),
  107. height = width/3.0,
  108. radius = width/4.0;
  109. document.getElementById('spanish_parliament_div').setAttribute("style", "height:"+height+"px");
  110. // radius = Math.min(width,height) / 2;
  111. svg.attr("transform", "translate(" + 2*width / 5.0 + "," + height + ")");
  112. //svg.attr("transform", "translate(" + 2*width / 5.0 + "," + 3.0*height + ")");
  113. /* ------ TOOLTIP formating ------ */
  114. var tooltip = svg.append("g")
  115. .attr("class", "tooltip")
  116. .style("display", "none");
  117.  
  118. tooltip.append("rect")
  119. .attr("width", width/9.0)
  120. .attr("height", height/6.0)
  121. .attr("fill", "white")
  122. .style("opacity", 0.5);
  123. tooltip.append("text")
  124. .attr("x", 15)
  125. .attr("dy", "1.2em")
  126. .style("text-anchor", "left")
  127. .attr("font-size", "12px")
  128. .attr("font-weight", "bold");
  129. /*
  130. var key = function(d){ return d.data.label; };
  131. var color = d3.scale.category20()
  132. .domain(["JxSi", "C's", "PSC", "CSQP", "PPC", "CUP"])
  133. .range(["#34cbcb", "#ff8000", "#e60000", "#e60073", "#3333ff", "#ffff00"]);
  134. function readData (){
  135. var labels = color.domain();
  136. return labels.map(function(label){
  137. return { label: label, value: seats[label] }
  138. }).filter(function(d){
  139. return d.value > 0;
  140. }).sort(function(a, b){
  141. return d3.descending(a.value, b.value);
  142. });
  143. }
  144. change(readData());
  145. */
  146.  
  147. dataset = {
  148. "parliament": {
  149. "name": "Congreso de los Diputados",
  150. "seats": "350"
  151. },
  152. "parties": [
  153. {
  154. "code": "PP",
  155. "color": "#3333ff",
  156. "name": "Partido Popular"
  157. },
  158. {
  159. "code": "PSOE",
  160. "color": "#e60000",
  161. "name": "Partido Socialista Obrero Espa\u00f1ol"
  162. },
  163. {
  164. "code": "Podemos",
  165. "color": "#660033",
  166. "name": "Podemos"
  167. },
  168. {
  169. "code": "C's",
  170. "color": "#ff8000",
  171. "name": "Ciutadans"
  172. },
  173. {
  174. "code": "ERC",
  175. "color": "#ffd11a",
  176. "name": "Esquerra Republicana de Catalunya"
  177. },
  178. {
  179. "code": "DiL",
  180. "color": "#000066",
  181. "name": "Democr\u00e0cia i Llibertat"
  182. },
  183. {
  184. "code": "PNV",
  185. "color": "#009933",
  186. "name": "Partido Nacionalista Vasco"
  187. },
  188. {
  189. "code": "IU",
  190. "color": "#660000",
  191. "name": "Izquierda Unida"
  192. },
  193. {
  194. "code": "Bildu",
  195. "color": "#99ff33",
  196. "name": "EH Bildu"
  197. },
  198. {
  199. "code": "CC",
  200. "color": "#e6e600",
  201. "name": "Coalicion Canarias"
  202. }
  203. ],
  204. "results": {
  205. "Banzhaf": {
  206. "Bildu": 0.008,
  207. "C's": 0.084,
  208. "CC": 0.003,
  209. "DiL": 0.033,
  210. "ERC": 0.04,
  211. "IU": 0.008,
  212. "PNV": 0.026,
  213. "PP": 0.378,
  214. "PSOE": 0.21,
  215. "Podemos": 0.21
  216. },
  217. "Proportional": {
  218. "Bildu": 0.006,
  219. "C's": 0.114,
  220. "CC": 0.003,
  221. "DiL": 0.023,
  222. "ERC": 0.026,
  223. "IU": 0.006,
  224. "PNV": 0.017,
  225. "PP": 0.351,
  226. "PSOE": 0.257,
  227. "Podemos": 0.197
  228. },
  229. "Seats": {
  230. "Bildu": 2,
  231. "C's": 40,
  232. "CC": 1,
  233. "DiL": 8,
  234. "ERC": 9,
  235. "IU": 2,
  236. "PNV": 6,
  237. "PP": 123,
  238. "PSOE": 90,
  239. "Podemos": 69
  240. },
  241. "Shapley": {
  242. "Bildu": 0.006,
  243. "C's": 0.07,
  244. "CC": 0.002,
  245. "DiL": 0.025,
  246. "ERC": 0.03,
  247. "IU": 0.006,
  248. "PNV": 0.02,
  249. "PP": 0.402,
  250. "PSOE": 0.22,
  251. "Podemos": 0.22
  252. },
  253. "Winnable-Ideologia": {
  254. "Bildu": 0.053,
  255. "C's": 0.106,
  256. "CC": 0.074,
  257. "DiL": 0.089,
  258. "ERC": 0.067,
  259. "IU": 0.043,
  260. "PNV": 0.088,
  261. "PP": 0.192,
  262. "PSOE": 0.172,
  263. "Podemos": 0.117
  264. },
  265. "Worsable-Ideologia": {
  266. "Bildu": 0.05,
  267. "C's": 0.11,
  268. "CC": 0.086,
  269. "DiL": 0.097,
  270. "ERC": 0.062,
  271. "IU": 0.036,
  272. "PNV": 0.098,
  273. "PP": 0.156,
  274. "PSOE": 0.203,
  275. "Podemos": 0.101
  276. }
  277. }
  278. }
  279.  
  280.  
  281. d3.select('#inds_spanish_parliament')
  282. .on("change", function () {
  283. MeasureSettings();
  284. change(dataset);
  285. });
  286. MeasureSettings();
  287. change(dataset);
  288.  
  289. d3.json("2015_spanish_parliament.json", function (error, dataset) {
  290. if (error) throw error;
  291. d3.select('#inds_spanish_parliament')
  292. .on("change", function () {
  293. MeasureSettings();
  294. change(dataset);
  295. });
  296. MeasureSettings();
  297. change(dataset);
  298. });
  299. function MeasureSettings () {
  300. var titleMeasure = document.getElementById("titleMeasure");
  301. titleMeasure.parentNode.removeChild(titleMeasure);
  302. var sect = document.getElementById("inds_spanish_parliament");
  303. var measure_name = sect.options[sect.selectedIndex].value;
  304. svg.append("text")
  305. .attr("id", "titleMeasure")
  306. .html('<tspan x="'+ -width/3.5 +'" dy="'+ -1.2*radius +'" font-size="2vw" fill="green" style="font-weight:bold">'+measure_name+'</tspan>')
  307. .style('font-size', '.9em')
  308. .style('color', 'green')
  309. .style('text-anchor', 'left');
  310. }
  311. /* ------- AUXILIAR FUNCTIONS -------*/
  312. function mergeWithFirstEqualZero(first, second){
  313. var secondSet = d3.set(); second.forEach(function(d) { secondSet.add(d.label); });
  314. var onlyFirst = first
  315. .filter(function(d){ return !secondSet.has(d.label); })
  316. .map(function(d) { return {label: d.label, value: 0}; });
  317. return d3.merge([ second, onlyFirst ])
  318. .sort(function(a,b) {
  319. return d3.ascending(a.label, b.label);
  320. });
  321. }
  322. function defineColors (dataset){
  323. /* ---------------- Get variables ---------------- */
  324. var parties_info = Object.keys(dataset.results.Seats).map(function(label){
  325. return {label: label, value: dataset.results.Seats[label],
  326. color: dataset.parties.filter(function(p){return p.code == label;})[0].color};
  327. }).filter(function(d){
  328. return d.value > 0;
  329. }).sort(function(a, b){
  330. return d3.descending(a.value, b.value);
  331. });
  332. var parties = parties_info.map(function(party_info){
  333. return party_info.label;
  334. });
  335. var colors_parties = parties_info.map(function(party_info){
  336. return party_info.color;
  337. });
  338. /* ---------------- Define colors ---------------- */
  339. var color = d3.scale.category20()
  340. .domain(parties)
  341. .range(colors_parties);
  342. return color;
  343. }
  344. function readData (dataset){
  345. /* ---------------- Define colors ---------------- */
  346. var color = defineColors(dataset);
  347. /* ------------ Get measure from buttom ------------ */
  348. var sect = document.getElementById("inds_spanish_parliament");
  349. var measure_name = sect.options[sect.selectedIndex].value;
  350. /* ---------------- Compute data ---------------- */
  351. var measure = dataset.results[measure_name];
  352. var seats = dataset.results.Seats;
  353. var labels = color.domain();
  354. return labels.map(function(label){
  355. return {label: label, value: measure[label], seats: seats[label]};
  356. }).filter(function(d){
  357. return d.seats > 0;
  358. }).sort(function(a, b){
  359. return d3.descending(a.seats, b.seats);
  360. });
  361. }
  362. /* ------- REPLOT FUNCTION -------*/
  363. function change(dataset) {
  364. /* ------- MAIN DATA -------*/
  365. // var duration = +document.getElementById("duration").value;
  366. var duration = 500,
  367. data = readData(dataset),
  368. color = defineColors(dataset),
  369. n_seats = dataset.parliament.seats,
  370. name_parlament = dataset.parliament.name;
  371. var key = function(d){ return d.data.label; };
  372. /* ------- REBUILD PLOT -------*/
  373. var data0 = svg.select(".slices").selectAll("path.slice")
  374. .data().map(function(d) { return d.data ;});
  375. if (data0.length == 0) data0 = data;
  376. var was = mergeWithFirstEqualZero(data, data0);
  377. var is = mergeWithFirstEqualZero(data0, data);
  378. /* ------- MAIN FUNCTIONS -------*/
  379. var pie = d3.layout.pie()
  380. .startAngle(-90 * (Math.PI/180))
  381. .endAngle(90 * (Math.PI/180))
  382. .sort(null)
  383. .value(function(d) {
  384. return d.value;
  385. });
  386. var arc = d3.svg.arc()
  387. .outerRadius(radius * 1.0)
  388. .innerRadius(radius * 0.4)
  389. .cornerRadius(7) // sets how rounded the corners are on each slice
  390. .padAngle(0.015); // effectively dictates the gap between slices
  391. var outerArc = d3.svg.arc()
  392. .innerRadius(radius * 0.5)
  393. .outerRadius(radius * 1.1);
  394. /* ------- SLICE ARCS -------*/
  395. var slice = svg.select(".slices").selectAll("path.slice")
  396. .data(pie(was), key);
  397. slice.enter()
  398. .insert("path")
  399. .attr("class", "slice")
  400. .style("fill", function(d) { return color(d.data.label); })
  401. .each(function(d) {
  402. this._current = d;
  403. });
  404. slice = svg.select(".slices").selectAll("path.slice")
  405. .data(pie(is), key);
  406. slice
  407. .transition().duration(duration)
  408. .attrTween("d", function(d) {
  409. var interpolate = d3.interpolate(this._current, d);
  410. var _this = this;
  411. return function(t) {
  412. _this._current = interpolate(t);
  413. return arc(_this._current);
  414. };
  415. });
  416. slice = svg.select(".slices").selectAll("path.slice")
  417. .data(pie(data), key);
  418. // .on("mouseover", function() { tooltip.style("display", null); })
  419. // .on("mouseout", function() { tooltip.style("display", "none"); })
  420. // .on("mousemove", function(d) {
  421. // var xPosition = d3.mouse(this)[0] - 15;
  422. // var yPosition = d3.mouse(this)[1] - 25;
  423. // tooltip.style("display", "inline");
  424. // tooltip.attr("transform", "translate(" + xPosition + "," + yPosition + ")");
  425. // tooltip.select("text").text(d.data.label+': '+d.data.value);
  426. // });
  427. /* ------- TEXT LABELS -------*/
  428. var text = svg.select(".labels").selectAll("text")
  429. .data(pie(was), key);
  430. text.enter()
  431. .append("text")
  432. .attr("dy", ".35em")
  433. .style("opacity", 0)
  434. .text(function(d) {
  435. return d.data.label;
  436. })
  437. .each(function(d) {
  438. this._current = d;
  439. });
  440. function midAngle(d){
  441. var middle = d.startAngle + (d.endAngle - d.startAngle)/2;
  442. return middle;
  443. }
  444. text = svg.select(".labels").selectAll("text")
  445. .data(pie(is), key);
  446. text.transition().duration(duration)
  447. .style("opacity", function(d) {
  448. return d.data.value == 0 ? 0 : 1;
  449. })
  450. .attrTween("transform", function(d) {
  451. var interpolate = d3.interpolate(this._current, d);
  452. var _this = this;
  453. return function(t) {
  454. var d2 = interpolate(t);
  455. _this._current = d2;
  456. var pos = outerArc.centroid(d2);
  457. pos[0] = 1.1*radius * (midAngle(d2) > 0 ? 1 : -1);
  458. return "translate("+ pos +")";
  459. };
  460. })
  461. .styleTween("text-anchor", function(d){
  462. var interpolate = d3.interpolate(this._current, d);
  463. return function(t) {
  464. var d2 = interpolate(t);
  465. return midAngle(d2) > 0 ? "start":"end";
  466. };
  467. });
  468.  
  469. text = svg.select(".labels").selectAll("text")
  470. .data(pie(data), key);
  471. text
  472. .exit().transition().delay(duration)
  473. .remove();
  474. /* ------- SLICE TO TEXT POLYLINES -------*/
  475. var polyline = svg.select(".lines").selectAll("polyline")
  476. .data(pie(was), key);
  477.  
  478. polyline.enter()
  479. .append("polyline")
  480. .style("opacity", 0)
  481. .each(function(d) {
  482. this._current = d;
  483. });
  484. polyline = svg.select(".lines").selectAll("polyline")
  485. .data(pie(is), key);
  486.  
  487. polyline.transition().duration(duration)
  488. .style("opacity", function(d) {
  489. return d.data.value == 0 ? 0 : 1;
  490. })
  491. .attrTween("points", function(d){
  492. this._current = this._current;
  493. var interpolate = d3.interpolate(this._current, d);
  494. var _this = this;
  495. return function(t) {
  496. var d2 = interpolate(t);
  497. _this._current = d2;
  498. var pos = outerArc.centroid(d2);
  499. pos[0] = radius * 1.05 * (midAngle(d2) > 0 ? 1 : -1);
  500. return [arc.centroid(d2), outerArc.centroid(d2), pos];
  501. };
  502. });
  503. polyline = svg.select(".lines").selectAll("polyline")
  504. .data(pie(data), key);
  505. polyline
  506. .exit().transition().delay(duration)
  507. .remove();
  508. // Append center
  509. var InnerCircleDetails = document.getElementById("InnerCircleDetails");
  510. InnerCircleDetails.parentNode.removeChild(InnerCircleDetails);
  511. svg.append('text')
  512. .attr("id", "InnerCircleDetails")
  513. .attr('class', 'toolCircle')
  514. // .attr('dy', -20) // hard-coded. can adjust this to adjust text vertical alignment in tooltip
  515. .html('<tspan x="0" dy="'+-radius/7.0+'" font-size="3.2vw" fill="red">'+n_seats+'</tspan>'+'<tspan x="0" dy="'+0.12*radius+'" style="font-weight:bold" font-size="1.25vw">'+name_parlament+'</tspan>')
  516. .style('font-size', '.9em')
  517. .style('color', 'black')
  518. .style('text-anchor', 'middle'); // centres text in tooltip
  519. /* ------- ADD DASHED LINE -------*/
  520. var DashedHalfSeparator = document.getElementById("DashedHalfSeparator");
  521. DashedHalfSeparator.parentNode.removeChild(DashedHalfSeparator);
  522. svg.append("line")
  523. .attr("id", "DashedHalfSeparator")
  524. .attr("x1", 0) //<<== change your code here
  525. .attr("y1", -radius*0.3)
  526. .attr("x2", 0) //<<== and here
  527. .attr("y2", -radius*1.05)
  528. .style("stroke-dasharray", ("3, 3"))
  529. .style("stroke-width", 2.5)
  530. .style("stroke", "red")
  531. .style("fill", "none");
  532. /* ------- ADD TEXTS INDICATIONS -------*/
  533. var HalfIndicator = document.getElementById("HalfIndicator");
  534. HalfIndicator.parentNode.removeChild(HalfIndicator);
  535. svg.append("text")
  536. .attr("id", "HalfIndicator")
  537. .html('<tspan x="0" dy="'+-radius*1.06+'" font-size="1.3vw" fill="green">1/2</tspan>')
  538. .style('font-size', '.9em')
  539. .style('color', 'black')
  540. .style('text-anchor', 'middle');
  541. /* ------- ADD LEGEND -------*/
  542. var LegendParties = document.getElementById("LegendParties");
  543. LegendParties.parentNode.removeChild(LegendParties);
  544. // add legend
  545. var legend = svg.append("g")
  546. .attr("class", "legend")
  547. .attr("id", "LegendParties")
  548. .attr("height", 2.5/3.0*height)
  549. .attr("width", width/13.0)
  550. .attr('transform', 'translate('+ -width/65.0 +','+ height/15.0 +')');
  551.  
  552. legend.selectAll('rect')
  553. .data(data)
  554. .enter()
  555. .append("rect")
  556. .attr("x", width*2/5)
  557. .attr("y", function(d, i){ return -height*9.0/10.0 + i * height/12.5;})
  558. .attr("width", height/24.0)
  559. .attr("height", height/24.0)
  560. .style("fill", function(d) { return color(d.label); });
  561. legend.selectAll('text')
  562. .data(data)
  563. .enter()
  564. .append("text")
  565. .attr("x", width*2/5+width/30.0)
  566. .attr("y", function(d, i){ return -height*9.0/10.0 + height/30.0 + i * height/12.5;})
  567. .style('font-size', '1.5vw')
  568. .text(function(d) {
  569. var text = d.label;
  570. return text;
  571. });
  572. }
  573. </script>
  574. </body>
  575. </html>
Add Comment
Please, Sign In to add comment