Built with blockbuilder.org
xxxxxxxxxx
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link href='https://fonts.googleapis.com/css?family=Cabin:300,400' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Lato:300,400' rel='stylesheet' type='text/css'>
<style>
body{
max-width: 900px;
margin: 0px auto;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
background-color: LightSkyBlue;
}
#container{
position: relative;
}
#sections{
width: 800px;
position: relative;
margin: 0px auto;
padding-top: 40px;
}
#sections div{
font-family: Lato;
text-align: center;
color: Navy;
padding: 10px;
max-width: 900px;
margin-bottom: 500px;
margin-top: -25px;
font-size: 20px;
}
#sections > div:last-child{
margin-bottom: 30px;
}
#sections > div.graph-scroll-active{
opacity: 1;
}
#graph{
width: 600px;
position: absolute;
top: 200px;
margin-left: 15%;
}
.graph-scroll-fixed #graph{
position: fixed;
top: 100px;
}
.graph-scroll-below #graph{
bottom: 20px;
top: auto;
}
h1 {
font-family: Cabin;
margin-top: 20px;
margin-left: 60px;
margin-right: 60px;
color: Navy;
}
h3, h5 {
font-family: Lato;
margin-left: 80px;
margin-right: 80px;
margin-top: -8px;
color: Navy;
}
h1, h3, h5{
text-align: center;
}
#intro-block {
display: block;
top: 0;
width: 100%;
float: top;
overflow: auto;
}
p {
color: Navy;
line-height: 1.2em;
margin-left: 50px;
margin-right: 50px;
text-align: center;
}
circle{
fill: steelblue;
}
.mono{
font-family: monospace;
}
rect {
fill: Goldenrod;
}
svg{
background-color: LightSkyBlue;
}
#logo {
display: block;
margin: auto;
}
#quote {
font-family: Lato;
font-size: 20px;
}
#head {
color: Ivory;
text-shadow: 1px 1px Navy;
}
</style>
<div id="intro-block">
<h1>Camping World Business Model</h1>
<h5>July 15, 2017</h5>
<h3>How does Camping World's business model resemble Apple's walled garden ecosystem?</h3>
</div>
<img id="logo" src="https://www.samhooker.com/images/classcrv.png" width="40">
<div id='container'>
<div id='graph'></div>
<div id='sections'>
<div>
<h3 id="head">Booming RV Sales</h3>
<p>The RV business has been a bonanza. Since 2008 economic downturn, RV sales have been moving up rapidly, and its been a powerful force. for enthusiasts. Freedom, travel, exploration, family, these aren’t functional needs, but they are emotional needs. Trailers to motorhomes, there’s a product for every economic tier.</p>
</div>
<div>
<p>Not only are more RVs being sold each year, but the total revenue is growing more than the units, showing that higher priced units are being sold more, continuing the bonanza for RV dealers.</p>
</div>
<div>
<p id="quote">"Today, what we have is the single-largest RV and camping company that the world has ever known. Bigger than any manufacturer, bigger than anything."</p>
<h6>Marcus Lemonis, CEO of Camping World</h6>
</div>
</div>
</div>
<div id='container' class='container-2'>
<div id='graph'></div>
<div id='sections'>
<div>
<p>Camping World has is the largest seller of RVs in the country, and is the single largest dealer of Thor and Winnebago (17%).
</p>
</div>
<div>
<p>Marcus quote “we aren’t an RV dealership”.
So what gives? How can the biggest seller of RVs not consider themselves an RV dealership? Wouldn’t you want to be the king of this growth channel?</p>
</div>
<div>
<p>Wouldn’t you want to keep your ASPs flat given the power you have over the market via market share? Why wouldn’t you keep the price higher for your captive audience of buyers?</p>
</div>
</div>
</div>
<div id='container' class='container-3'>
<div id='graph'></div>
<div id='sections'>
<div>
<h1>
Multiple graphs
</h1>
<img id="logo" src="https://www.samhooker.com/images/cwgs.png" width="200">
</div>
<div>
<h3>Scroll away</h3>
As the bottom of the container approaches the top of the page, the graph is classed with <span class='mono'>graph-scroll-below</span>. A little more css allows the graph slide out of view gracefully:
<pre>
.graph-scroll-below #graph{
position: absolute;
bottom: 0px;
}
</pre>
</div>
<div>
<h3>Mobile</h3>
On mobile centering the graph and sections while adding a some padding for the first slide is a good option:
<pre>
@media (max-width: 925px) {
#graph{
width: 100%;
transform: translate(-50%, 0);
margin-left: 50%;
}
#sections{
position: relative;
margin: 0px auto;
padding-top: 400px;
}
}
</pre>
</div>
<div>
<h3>Examples</h3>
<p><a href='https://www.bloomberg.com/graphics/2015-auto-sales/'>Auto Sales</a></p>
<p><a href='https://www.bloomberg.com/graphics/2015-measles-outbreaks/'>Measles</a></p>
<p><a href='https://roadtolarissa.com/blog/2015/01/04/coloring-maps-with-d3/'>Coloring Maps</a></p>
<p><a href='https://www.bloomberg.com/graphics/2015-fifa-scandal/'>FIFA Scandal</a></p>
<p><a href='https://www.bloomberg.com/graphics/2015-whats-warming-the-world/'>Global Warming</a></p>
<p><a href='https://www.bloomberg.com/politics/graphics/2015-hillary-womens-movement-timeline/'>Hillary Clinton’s Debt to Feminism
</a></p>
<p><a href='https://www.bloomberg.com/graphics/year-ahead-2016/'>The Year Ahead</a></p>
<p><a href='https://www.bloomberg.com/graphics/2015-pace-of-social-change/'>Pace of Social Change</a></p>
<p><a href='https://www.bloomberg.com/graphics/2015-red-meat-cancer/'>Red Meat</a></p>
</div>
<div>
<h3>More reading</h3>
<p><a href='https://bost.ocks.org/mike/scroll/'>How To Scroll</a></p>
<p><a href='https://vallandingham.me/scroller.html/'>So You Want to Build A Scroller</a></p>
<p><a href='https://source.opennews.org/en-US/articles/behind-scenes-fewer-helmets-more-deaths/'>Making “Fewer Helmets, More Deaths”</a></p>
<p><a href='https://www.nytimes.com/interactive/2015/10/27/world/greenland-is-melting-away.html'>Greenland Is Melting Away</a></p>
<p><a href='https://www.theguardian.com/us-news/ng-interactive/2015/oct/19/homan-square-chicago-police-detainees'>Homan Square</a></p>
</div>
<div>
<h3>Todos</h3>
<p>- Simple examples
<p>- Self explanatory graphics
<p>- Swiper
</div>
</div>
</div>
<h3 id='source'><a href='https://github.com/1wheel/graph-scroll'>contribute/view on github</a></h3>
<script src="https://d3js.org/d3-dsv.v1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3-jetpack@2.2.1/build/d3v4+jetpack.js"></script>
<script src="https://www.samhooker.com/d3/graph-scroll.js"></script>
<script>
var oldWidth = 0
function render(){
if (oldWidth == innerWidth) return
oldWidth = innerWidth
var width = d3.select('#graph').node().offsetWidth,
height = 500;
r = 20
var svg = d3.select('#graph').html('')
.append('svg')
.attrs({width: width, height: height})
var circle = svg.append('circle')
.attrs({cx: 0, cy: 0, r: r})
var colors = ['orange', 'purple', 'HotPink', 'pink', 'black']
var gs = d3.graphScroll()
.container(d3.select('#container'))
.graph(d3.selectAll('#graph'))
.eventId('uniqueId1')
.sections(d3.selectAll('#sections > div'))
// .offset(innerWidth < 900 ? innerHeight - 30 : 200)
.on('active', function(i){
var pos = [ {cx: width - r *2, cy: r},
{cx: r , cy: r*2},
{cx: width - r, cy: height - r},
{cx: width/3, cy: height/3} ][i]
circle.transition().duration(1000)
.attrs(pos)
.transition()
.style('fill', colors[i])
})
var svg2 = d3.select('.container-2 #graph').html('')
.append('svg')
.attrs({width: width, height: height})
var path = svg2.append('path')
var gs2 = d3.graphScroll()
.container(d3.select('.container-2'))
.graph(d3.selectAll('.container-2 #graph'))
.eventId('uniqueId1')
.sections(d3.selectAll('.container-2 #sections > div'))
.on('active', function(i){
var h = height
var w = width
var dArray = [
[[w/4, h/4], [w*3/4, h/4], [w*3/4, h*3/4], [w/4, h*3/4]],
[[0, 0], [w*3/4, h/4], [w*3/4, h*3/4], [w/4, h*3/4]],
[[w/2, h/2], [w, h/4], [w, h], [w/4, h]],
[[w/2, h/2], [w, h/4], [w, h], [w/4, h]],
[[w/2, h/2], [w, h/2], [0, 0], [w/4, h/2]],
[[w/2, h/2], [0, h/4], [0, h/2], [w/4, 0]],
].map(function(d){ return 'M' + d.join(' L ') })
path.transition().duration(1000)
.attr('d', dArray[i])
.style('fill', colors[i])
})
var svg3 = d3.select('.container-3 #graph').html('')
.append('svg')
.attrs({width: width, height: height})
var path = svg3.append('path')
var gs3 = d3.graphScroll()
.container(d3.select('.container-3'))
.graph(d3.selectAll('.container-3 #graph'))
.eventId('uniqueId1')
.sections(d3.selectAll('.container-3 #sections > div'))
.on('active', function(i){
var h = height
var w = width
var dArray = [
[[w/6, h/6], [w*3/6, h/6], [w*3/6, h*3/6], [w/6, h*3/6]],
[[0, 0], [w*3/6, h/6], [w*3/6, h*3/6], [w/4, h*3/6]],
[[w/2, h/2], [w, h/4], [w, h], [w/6, h]],
[[w/2, h/2], [w, h/4], [w, h], [w/6, h]],
[[w/2, h/2], [w, h/2], [0, 0], [w/6, h/2]],
[[w/2, h/2], [0, h/4], [0, h/2], [w/4, 0]],
].map(function(d){ return 'M' + d.join(' L ') })
path.transition().duration(500)
.attr('d', dArray[i])
.style('fill', colors[i])
})
d3.select('#source')
.styles({'margin-bottom': window.innerHeight - 450 + 'px', padding: '100px'})
}
render()
d3.select(window).on('resize', render)
Promise.all([
"https://www.samhooker.com/data/rvsales.csv",
"two.csv",
"three.csv"
].map(function(url) {
return fetch(url).then(function(response) {
return response.ok ? response.text() : Promise.reject(response.status);
}).then(function(text) {
return d3.csvParse(text);
});
})).then(function(value) {
var one = +value[0][0].number,
two = +value[1][0].number,
three = +value[2][0].number;
});
</script>
Modified http://www.samhooker.com/d3/d3v4+jetpack.js to a secure url
Modified http://www.samhooker.com/d3/graph-scroll.js to a secure url
https://d3js.org/d3-dsv.v1.min.js
https://www.samhooker.com/d3/d3v4+jetpack.js
https://www.samhooker.com/d3/graph-scroll.js