Compare commits

...

5 Commits

  1. 1
      .gitignore
  2. 274
      css/index.css
  3. 39
      index.html
  4. 164
      js/chart.js
  5. 16
      js/chart3.js
  6. 64
      js/data.js
  7. 8
      js/map.js
  8. 5
      vendor/d3.min.js

1
.gitignore vendored

@ -1,5 +1,4 @@
experiments
d3.min.js
node_modules
three.js-r73
.DS_Store

@ -1,105 +1,133 @@
* {
box-sizing: border-box;
cursor: default;
letter-spacing: 0.7px;
margin: 0;
padding: 0; }
box-sizing: border-box;
cursor: default;
margin: 0;
padding: 0;
}
.main {
height: 920px;
margin: 10px auto 100px auto;
padding: 50px 20px;
position: relative;
width: 800px; }
height: 900px;
margin: 10px auto 100px auto;
padding: 20px;
position: relative;
width: 1040px;
}
#chart {
cursor: pointer;
height: 880px;
left: 540px;
position: absolute;
top: 20px;
width: 220px; }
#chart svg {
margin-left: 30px;
height: 100%;
width: 210px; }
cursor: pointer;
height: 200px;
left: 50%;
margin-left:-450px;
position: absolute;
top: 640px;
width: 900px;
}
#chart svg {
height: 200px;
width: 100%;
}
#year-labels {
font-size: 0;
height: 100%;
left: 540px;
padding-top: 15px;
position: absolute;
top: 20px;
width: 30px; }
#year-labels .label {
font-size: 0;
height: 30px;
left: 50%;
margin-left:-450px;
padding-left:30px;
position: absolute;
top: 840px;
width: 900px;
}
#year-labels .label {
color: #777;
cursor: pointer;
display:inline-block;
font-size: 9px;
height: 23px;
line-height: 20px;
margin-bottom: 2px;
text-align: center; }
height:30px;
line-height: 30px;
margin-right:2px;
text-align:center;
vertical-align:top;
width: 23px;
}
.year-toggle:hover {
background: #eee; }
background: #eee;
}
.axis .domain {
fill: none;
stroke: none; }
fill: none;
stroke: none;
}
.axis .tick {
fill: #aaa;
font-size: 10px; }
fill: #aaa;
font-size: 10px;
}
.label-axis-x {
fill: #aaa;
font-size: 10px;
letter-spacing: normal; }
fill: #aaa;
font-size: 10px;
letter-spacing: normal;
}
.tick-line {
stroke: #f0f0f0; }
stroke: #f0f0f0;
}
#chart3 {
height: 260px;
left: 20px;
position: absolute;
top: 640px;
width: 500px; }
height: 300px;
left: 20px;
position: absolute;
top: 20px;
width: 480px;
}
#map {
border: 1px solid #e8e8e8;
height: 600px;
position: relative;
width: 500px;
z-index: 0; }
#map svg {
border: 1px solid #e8e8e8;
height: 600px;
left:520px;
position: absolute;
top:20px;
width: 500px;
z-index: 0;
}
#map svg {
height: 100%;
width: 100%; }
width: 100%;
}
.feature {
fill: #f7f7f7;
stroke: #ccc; }
fill: #f7f7f7;
stroke: #ccc;
}
.reticle {
cursor: move;
fill: rgba(153, 173, 40, 0.2);
stroke: #5D5336; }
cursor: move;
fill: rgba(153, 173, 40, 0.2);
stroke: #5D5336;
}
.column-display {
cursor: pointer;
height: 210px;
left: 40px;
overflow: hidden;
position: absolute;
top: 330px;
width: 180px; }
.column-display select {
cursor: pointer;
height: 210px;
left: 40px;
overflow: hidden;
position: absolute;
top: 380px;
width: 180px;
}
.column-display select {
background: 0;
border: 0;
outline: 0;
width: 200px; }
.column-display .toggle {
width: 200px;
}
.column-display .toggle {
background: 0;
color: #ccc;
cursor: pointer;
@ -108,25 +136,36 @@
letter-spacing: 1.5px;
line-height: 30px;
text-transform: uppercase;
transition: color 0.3s ease; }
.column-display .toggle:hover {
color: #777; }
.column-display .toggle.selected {
color: #444;
cursor: default;
font-weight: bold; }
transition: color 0.3s ease;
}
.column-display .toggle:hover {
color: #777;
}
.column-display .toggle.selected {
color: #444;
cursor: default;
font-weight: bold;
}
.reticle-sizer {
left: 40px;
position: absolute;
top: 520px;
z-index: 1; }
height:60px;
left: 240px;
position: absolute;
top: 380px;
width:160px;
z-index: 1;
}
.bar-display {
left: 40px;
position: absolute;
top: 560px; }
.bar-display .toggle {
left: 240px;
position: absolute;
top: 460px;
width:160px;
}
.bar-display .toggle {
background-image: url("../bar-display.png");
background-repeat: no-repeat;
cursor: pointer;
@ -136,38 +175,53 @@
margin-right: 15px;
opacity: 0.15;
transition: opacity 0.3s ease;
width: 30px; }
.bar-display .toggle:hover {
opacity: 1; }
.bar-display .toggle.selected {
cursor: default;
opacity: 1; }
.bar-display .toggle1 {
background-position: -60px 10px; }
.bar-display .toggle2 {
background-position: -30px 10px; }
.bar-display .toggle3 {
background-position: 0 10px; }
width: 30px;
}
.bar-display .toggle:hover {
opacity: 1;
}
.bar-display .toggle.selected {
cursor: default;
opacity: 1;
}
.bar-display .toggle1 {
background-position: -60px 10px;
}
.bar-display .toggle2 {
background-position: -30px 10px;
}
.bar-display .toggle3 {
background-position: 0 10px;
}
input[type=range] {
cursor: pointer;
-webkit-appearance: none; }
cursor: pointer;
-webkit-appearance: none;
}
input[type=range]::-webkit-slider-runnable-track {
background: #ddd;
border: none;
border-radius: 3px;
height: 2px;
width: 300px; }
background: #ddd;
border: none;
border-radius: 3px;
height: 2px;
width: 300px;
}
input[type=range]::-webkit-slider-thumb {
background: #d8ebd3;
border: 2px solid #5D5336;
border-radius: 50%;
height: 16px;
margin-top: -7px;
width: 16px;
-webkit-appearance: none; }
background: #d8ebd3;
border: 2px solid #5D5336;
border-radius: 50%;
height: 16px;
margin-top: -7px;
width: 16px;
-webkit-appearance: none;
}
input[type=range]:focus {
outline: none; }
outline: none;
}

@ -2,9 +2,9 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<title>Buoy Analysis</title>
<link href='css/index.css' rel='stylesheet' type='text/css'>
<script src='/bb-2016/js/ui.js'></script>
<script src='/core/js/ui.js'></script>
</head>
<body>
@ -19,6 +19,7 @@
<br><br>
Visualization should invite interaction to create and answer questions such as:
<ul>
<li>Why are ocean temperatures generally lowest in spring rather than winter?</li>
<li>Are ocean temperatures increasing?</li>
<li>What are the visible effects of El Nino?</li>
<li>What is the temperature of the ocean near San Francisco?</li>
@ -58,9 +59,6 @@
<div id="chart3"></div>
</div>
<!-- <script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script> -->
<!-- <script src="//d3js.org/topojson.v1.min.js"></script> -->
<!-- https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js -->
<script src="vendor/three.min.js"></script>
<script src="vendor/TextGeometry.js"></script>
<script src="vendor/FontUtils.js"></script>
@ -76,36 +74,5 @@
<script src="js/chart3.js"></script>
<script src="js/init.js"></script>
<!--
Deploy!
Pong!
https://css-tricks.com/svg-line-animation-works/
DISCUSS:
Gradient evolution
- Opacity solution lacks saturation and transition alignment (omit?)
- Composite solution overly complex and lacks transition alignment
- Square mesh OK, causes diamond-shaped artifacts
- Triangle mesh?
gourand / phong?
Delaunay / Voronoi
Mesh gradients / coon mesh (http://www.svgopen.org/2011/papers/18-Advanced_Gradients_for_SVG/)
feImage
ogr2ogr -f "esri shapefile" -where "sov_a3 = 'MEX'" C:/dev/bb/buoy-analysis/data/map/merged.shp C:/dev/bb/buoy-analysis/data/map/countries.shp
ogr2ogr -f "esri shapefile" -update -append C:/dev/bb/buoy-analysis/data/map/merged.shp C:/dev/bb/buoy-analysis/data/map/states.shp
ogr2ogr -f GeoJSON -clipsrc -105 30 -125 43 C:/dev/bb/buoy-analysis/data/map.json C:/dev/bb/buoy-analysis/data/map/merged.shp
ogr2ogr -f GeoJSON C:/dev/bb/buoy-analysis/data/map/places.json C:/dev/bb/buoy-analysis/data/map/places.shp
topojson -o test.json _map.json
http://dvisvgm.bplaced.net/Gradients
http://www.gdal.org/ogr_sql.html
http://www.sarasafavi.com/intro-to-ogr-part-i-exploring-data.html
-->
<!-- <h3>ETL Stage</h3> -->
</body>
</html>

@ -7,8 +7,8 @@ var BuoyAnalysisChart = {
bars: {
padding: 15,
spacing: 2,
height: 23,
width: 190,
height: 200,
width: 23,
color: '#f00',
showMonths: true,
@ -30,16 +30,16 @@ var BuoyAnalysisChart = {
/**
*
*/
barYearY: function(d, i) {
return i * BuoyAnalysisChart.bars.height + i * BuoyAnalysisChart.bars.spacing + BuoyAnalysisChart.bars.padding;
barYearX: function(d, i) {
return i * BuoyAnalysisChart.bars.width + i * BuoyAnalysisChart.bars.spacing + 30;
},
/**
*
*/
barMonthY: function(d, i) {
barMonthX: function(d, i) {
var year = Math.floor(i / 12);
return year * BuoyAnalysisChart.bars.height + BuoyAnalysisChart.bars.padding + year * BuoyAnalysisChart.bars.spacing + (i % 12) * 2;
return year * BuoyAnalysisChart.bars.width + year * BuoyAnalysisChart.bars.spacing + (i % 12) * 2 + 30;
},
/**
@ -72,29 +72,29 @@ var BuoyAnalysisChart = {
chart.append("g")
.classed('axis', true)
.classed('axis-imperial', true)
.attr('transform', 'translate(0, 19)')
.attr('transform', 'translate(0, 0)')
.attr('fill', '#000')
.call(BuoyAnalysisChart.axis.imperial);
chart.append("g")
.classed('axis', true)
.classed('axis-metric', true)
.attr('transform', 'translate(0, 860)')
.attr('transform', 'translate(875, 0)')
.call(BuoyAnalysisChart.axis.metric);
chart.append('text')
.classed('label-axis-x', true)
.attr('text-anchor', 'middle')
.text(BuoyAnalysisChart.bars.imperialLabel)
.attr('x', 180)
.attr('x', 20)
.attr('y', 10)
chart.append('text')
.classed('label-axis-x', true)
.attr('text-anchor', 'middle')
.text(BuoyAnalysisChart.bars.metricLabel)
.attr('x', 180)
.attr('y', 876)
.attr('x', 890)
.attr('y', 10)
},
/**
@ -116,7 +116,7 @@ var BuoyAnalysisChart = {
b += parseInt(tmp[2], 16);
});
BuoyAnalysisChart.bars.color = 'rgba(' + avg(r) + ',' + avg(g) + ',' + avg(b) + ', 0.1)';
BuoyAnalysisChart.bars.color = 'rgba(' + avg(r) + ',' + avg(g) + ',' + avg(b) + ', 0.5)';
},
/**
@ -125,7 +125,7 @@ var BuoyAnalysisChart = {
updateAxes: function() {
switch(BuoyAnalysisData.property) {
case 'at':
BuoyAnalysisChart.bars.tickValues = [8, 12, 16, 20];
BuoyAnalysisChart.bars.tickValues = [4, 8, 12, 16, 20];
BuoyAnalysisChart.bars.imperialLabel = '°F';
BuoyAnalysisChart.bars.metricLabel = '°C';
@ -135,7 +135,7 @@ var BuoyAnalysisChart = {
break;
case 'wt':
BuoyAnalysisChart.bars.tickValues = [8, 12, 16, 20];
BuoyAnalysisChart.bars.tickValues = [4, 8, 12, 16, 20];
BuoyAnalysisChart.bars.imperialLabel = '°F';
BuoyAnalysisChart.bars.metricLabel = '°C';
@ -155,7 +155,7 @@ var BuoyAnalysisChart = {
break;
case 'wp':
BuoyAnalysisChart.bars.tickValues = [5, 7, 9, 11, 13];
BuoyAnalysisChart.bars.tickValues = [3, 5, 7, 9, 11, 13];
BuoyAnalysisChart.bars.imperialLabel = 'SEC';
BuoyAnalysisChart.bars.metricLabel = 'SEC';
@ -176,6 +176,70 @@ var BuoyAnalysisChart = {
};
},
/**
*
*/
setAxisProperties: function() {
var json = BuoyAnalysisData.stationJson;
var property = BuoyAnalysisData.property;
var tickValues = BuoyAnalysisChart.bars.tickValues;
BuoyAnalysisChart.axis.min = 100;
BuoyAnalysisChart.axis.max = 0;
for (var id in json) {
for (var year = BuoyAnalysisData.years.start; year <= BuoyAnalysisData.years.end; year++) {
for (var i = 0; i < 12; i++) {
if (json[id]['a' + year][property]['m'][i] <= 0) {
continue;
}
if (json[id]['a' + year][property]['m'][i] < BuoyAnalysisChart.axis.min) {
BuoyAnalysisChart.axis.min = json[id]['a' + year][property]['m'][i];
}
if (json[id]['a' + year][property]['m'][i] > BuoyAnalysisChart.axis.max) {
BuoyAnalysisChart.axis.max = json[id]['a' + year][property]['m'][i];
}
}
}
}
BuoyAnalysisChart.axis.scale = d3.scale.linear().domain([0, BuoyAnalysisChart.axis.max])
.range([BuoyAnalysisChart.bars.height, 0]);
BuoyAnalysisChart.axis.imperial = d3.svg.axis()
.scale(BuoyAnalysisChart.axis.scale)
.orient("right")
.tickFormat(function(d) {
var val;
switch(BuoyAnalysisData.property) {
case 'at':
case 'wt':
val = Math.round(d * 9 / 5 + 32);
break;
case 'wh':
case 'ws':
val = Math.round(d * 3.28 * 10) / 10;
break;
case 'wp':
val = d;
break;
};
return val;
})
.tickValues(tickValues);
BuoyAnalysisChart.axis.metric = d3.svg.axis()
.scale(BuoyAnalysisChart.axis.scale)
.orient("right")
.tickValues(tickValues);
},
/**
*
*/
@ -189,7 +253,7 @@ var BuoyAnalysisChart = {
var len = BuoyAnalysisData.years.end - BuoyAnalysisData.years.start + 1;
var h = (BuoyAnalysisChart.bars.height + BuoyAnalysisChart.bars.spacing) * len + BuoyAnalysisChart.bars.padding;
BuoyAnalysisData.setAxisProperties();
BuoyAnalysisChart.setAxisProperties();
BuoyAnalysisChart.appendAxes();
BuoyAnalysisChart.appendYearLabels();
@ -198,38 +262,40 @@ var BuoyAnalysisChart = {
chart.selectAll('.bar-month').remove();
chart.selectAll('.tick-line').remove();
chart.append('line')
.classed('tick-line', true)
.attr('x1', 1)
.attr('x2', 1)
.attr('y1', 15)
.attr('y2', h)
chart.append('line')
.classed('tick-line', true)
.attr('x1', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[0]))
.attr('x2', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[0]))
.attr('y1', 15)
.attr('y2', h)
chart.append('line')
.classed('tick-line', true)
.attr('x1', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[BuoyAnalysisChart.bars.tickValues.length - 1]))
.attr('x2', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[BuoyAnalysisChart.bars.tickValues.length - 1]))
.attr('y1', 15)
.attr('y2', h)
// chart.append('line')
// .classed('tick-line', true)
// .attr('x1', 1)
// .attr('x2', 1)
// .attr('y1', 15)
// .attr('y2', h)
//
// chart.append('line')
// .classed('tick-line', true)
// .attr('x1', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[0]))
// .attr('x2', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[0]))
// .attr('y1', 15)
// .attr('y2', h)
//
// chart.append('line')
// .classed('tick-line', true)
// .attr('x1', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[BuoyAnalysisChart.bars.tickValues.length - 1]))
// .attr('x2', BuoyAnalysisChart.axis.scale(BuoyAnalysisChart.bars.tickValues[BuoyAnalysisChart.bars.tickValues.length - 1]))
// .attr('y1', 15)
// .attr('y2', h)
if (BuoyAnalysisChart.bars.showYears === true) {
chart.selectAll('.bar-year').data(years).enter()
.append('rect')
.classed('bar-year', true)
.attr('fill', BuoyAnalysisChart.bars.color)
.attr('height', 23)
.attr('width', function(d) {
.attr('width', BuoyAnalysisChart.bars.width)
.attr('height', function(d) {
return BuoyAnalysisChart.bars.height - BuoyAnalysisChart.axis.scale(d.average);
})
.attr('x', BuoyAnalysisChart.barYearX)
.attr('y', function(d) {
return BuoyAnalysisChart.axis.scale(d.average);
})
.attr('x', 0)
.attr('y', BuoyAnalysisChart.barYearY)
}
if (BuoyAnalysisChart.bars.showMonths === true) {
@ -237,18 +303,14 @@ var BuoyAnalysisChart = {
.append('rect')
.classed('bar-month', true)
.attr('fill', 'rgba(0, 0, 0, 0.2)')
.attr('height', 1)
.attr('width', function(d) {
var w = BuoyAnalysisChart.axis.scale(d.average);
if (w <= 20) {
return 0;
}
return w;
.attr('width', 1)
.attr('height', function(d) {
return BuoyAnalysisChart.bars.height - BuoyAnalysisChart.axis.scale(d.average);
})
.attr('x', BuoyAnalysisChart.barMonthX)
.attr('y', function(d) {
return BuoyAnalysisChart.axis.scale(d.average);
})
.attr('x', 0)
.attr('y', BuoyAnalysisChart.barMonthY)
}
}
};

@ -2,8 +2,8 @@
var BuoyAnalysisChart3 = {
h: 258,
w: 498,
h: 300,
w: 480,
components: {},
scene: null,
@ -112,11 +112,15 @@ var BuoyAnalysisChart3 = {
BuoyAnalysisChart3.controls = new THREE.OrbitControls( BuoyAnalysisChart3.camera, BuoyAnalysisChart3.renderer.domElement );
BuoyAnalysisChart3.controls.target = new THREE.Vector3(200, 100, 0);
// controls.minPolarAngle = 50 * Math.PI / 180; // radians
// controls.maxPolarAngle = 90 * Math.PI / 180; // radians
// BuoyAnalysisChart3.controls.minPolarAngle = 50 * Math.PI / 180; // radians
// BuoyAnalysisChart3.controls.maxPolarAngle = 90 * Math.PI / 180; // radians
// controls.minAzimuthAngle = -90 * Math.PI / 180; // radians
// controls.maxAzimuthAngle = 0 * Math.PI / 180; // radians
// BuoyAnalysisChart3.controls.minAzimuthAngle = -90 * Math.PI / 180; // radians
// BuoyAnalysisChart3.controls.maxAzimuthAngle = 0 * Math.PI / 180; // radians
BuoyAnalysisChart3.controls.enablePan = false;
BuoyAnalysisChart3.controls.userPanSpeed = 6;
},
/**

@ -38,70 +38,6 @@ var BuoyAnalysisData = {
});
},
/**
*
*/
setAxisProperties: function() {
var json = BuoyAnalysisData.stationJson;
var property = BuoyAnalysisData.property;
var tickValues = BuoyAnalysisChart.bars.tickValues;
BuoyAnalysisChart.axis.min = 100;
BuoyAnalysisChart.axis.max = 0;
for (var id in json) {
for (var year = BuoyAnalysisData.years.start; year <= BuoyAnalysisData.years.end; year++) {
for (var i = 0; i < 12; i++) {
if (json[id]['a' + year][property]['m'][i] <= 0) {
continue;
}
if (json[id]['a' + year][property]['m'][i] < BuoyAnalysisChart.axis.min) {
BuoyAnalysisChart.axis.min = json[id]['a' + year][property]['m'][i];
}
if (json[id]['a' + year][property]['m'][i] > BuoyAnalysisChart.axis.max) {
BuoyAnalysisChart.axis.max = json[id]['a' + year][property]['m'][i];
}
}
}
}
BuoyAnalysisChart.axis.scale = d3.scale.linear().domain([0, BuoyAnalysisChart.axis.max])
.range([0, BuoyAnalysisChart.bars.width]);
BuoyAnalysisChart.axis.imperial = d3.svg.axis()
.scale(BuoyAnalysisChart.axis.scale)
.orient("top")
.tickFormat(function(d) {
var val;
switch(BuoyAnalysisData.property) {
case 'at':
case 'wt':
val = Math.round(d * 9 / 5 + 32);
break;
case 'wh':
case 'ws':
val = Math.round(d * 3.28 * 10) / 10;
break;
case 'wp':
val = d;
break;
};
return val;
})
.tickValues(tickValues);
BuoyAnalysisChart.axis.metric = d3.svg.axis()
.scale(BuoyAnalysisChart.axis.scale)
.orient("bottom")
.tickValues(tickValues);
},
/**
*
*/

@ -1,5 +1,11 @@
'use strict';
// ogr2ogr -f "esri shapefile" -where "sov_a3 = 'MEX'" merged.shp countries.shp
// ogr2ogr -f "esri shapefile" -update -append merged.shp states.shp
// ogr2ogr -f GeoJSON -clipsrc -105 30 -125 43 map.json merged.shp
// ogr2ogr -f GeoJSON places.json places.shp
// topojson -o test.json _map.json
var BuoyAnalysisMap = {
/**
*
@ -24,7 +30,7 @@ var BuoyAnalysisMap = {
/**
*
*/
stationColorScale: d3.scale.linear().domain([42, 37.5, 33]).range(['blue', 'orange', 'purple']),
stationColorScale: d3.scale.linear().domain([42, 37.5, 33]).range(['blue', 'orange', '#DC0953']),
/**
*

5
vendor/d3.min.js vendored

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save