-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add new template: before and after comparison. closes #19
- Loading branch information
1 parent
54dc126
commit 817bc2d
Showing
9 changed files
with
473 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
Before and After Comparison | ||
======================== | ||
|
||
### About this template | ||
|
||
This template offers an animated toggle between two images (a "before" and an "after") — often useful for comparing satellite imagery between two time periods. | ||
|
||
Columns in the spreadsheet: | ||
|
||
* `key` — A unique one-word descriptor for this pair of before and after images (such as the location the image). This is used as the unique id for each photo embed. | ||
* `headline` - A headline for this pair of before and after images _(optional)_. This is most useful in cases where you are including multiple before/after toggles in the same embed. | ||
* `image1` - The before image filename. We assume that it will live in the `synced/` folder inside the graphic. | ||
* `image1_alt` - Alt text for `image1` | ||
* `label_hed1` — The primary label for the first button. When user clicks the button, `image1` will be displayed. The text for the label is typically "Before." | ||
* `label_dek1` — A secondary label for the first button — typically the date when the `image1` was taken. _(optional)_ | ||
* `image2` - The after image filename. We assume that it will live in the `synced/` folder inside the graphic. | ||
* `image2_alt` - Alt text for `image2` | ||
* `label_hed2` — The primary label for the second button. When user clicks the button, `image2` will be displayed. The text for the label is typically "After." | ||
* `label_dek2` — A secondary label for the second button — typically the date when the `image2` was taken. _(optional)_ | ||
* `photo_credit` — Photo credit for `image1` and `image2`. _(optional)_ | ||
|
||
Key files: | ||
|
||
* `synced/` — All images should go here. (Note: This does not get committed to the repo. Files are published using a separate syncing process. See further below.) | ||
* `partials/_beforeafter.html` — Template code to display each pair of before and after images | ||
* `index.html` — View all before/after comparisons in this project | ||
|
||
----- | ||
|
||
### Creating multiple pairs of before and after images | ||
|
||
Add rows with corresponding attributes in the `data` spreadsheet with a unique `key` value. Then, depending on your desired way of presenting the images: | ||
|
||
#### All pairs appear in the same embed | ||
|
||
By default, `index.html` is set up to show all before/after pairs in the spreadsheet, in the order they're listed in the spreadsheet. | ||
|
||
#### Each pair gets its own embed | ||
|
||
If you want separate embeds for each before/after pair in the spreadsheet: | ||
|
||
* Make a copy of `index.html` and rename it according to the `key` for that row | ||
* Change this section of code: | ||
|
||
``` | ||
<% for (let key of Object.keys(COPY.data)) { %> | ||
<%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data[key] ]}}) %> | ||
<% } %> | ||
``` | ||
|
||
to: | ||
|
||
``` | ||
<%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data['KEY_FOR_THIS_ROW'] ]}}) %> | ||
``` | ||
|
||
----- | ||
|
||
### Optimizing images | ||
|
||
Create a folder locally somewhere on your machine with the original-size images. Inside that folder, create a new folder called `resized`. | ||
|
||
Run this ImageMagick script (from our [best practices](https://github.com/nprapps/bestpractices/blob/master/assets.md)) to resize the images: | ||
|
||
``` | ||
for f in *.jpg; do convert $f -quality 75 -resize 1600x1200\> -strip -sampling-factor 4:2:0 -define jpeg:dct-method=float -interlace Plane resized/$f; done | ||
``` | ||
|
||
Save the `resized` images in the `synced` folder in this project. Do not keep the original high-res images here. | ||
|
||
----- | ||
|
||
### Synced files | ||
|
||
For this project, images are synced to S3 rather than stored in the repo. Run this to retrieve / sync them: | ||
|
||
``` | ||
node cli sync $PROJECT_SLUG | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
var pym = require("./lib/pym"); | ||
var ANALYTICS = require("./lib/analytics"); | ||
require("./lib/webfonts"); | ||
var { isMobile } = require("./lib/breakpoints"); | ||
|
||
var pymChild = null; | ||
var isMobile = isMobile.matches; | ||
|
||
/* | ||
* Initialize the graphic. | ||
*/ | ||
var onWindowLoaded = function() { | ||
pym.then(function(child) { | ||
pymChild = child; | ||
child.sendHeight(); | ||
window.addEventListener("resize", render); | ||
}); | ||
|
||
initUI(); | ||
} | ||
|
||
/* | ||
* Render the graphic. | ||
*/ | ||
var render = function() { | ||
// Update iframe | ||
if (pymChild) { | ||
pymChild.sendHeight(); | ||
} | ||
} | ||
|
||
var initUI = function() { | ||
document.querySelectorAll('.graphic').forEach(function(wrapper) { | ||
var toggleTimeout; | ||
var toggleButtons = wrapper.querySelectorAll('.toggle-btn'); | ||
var splitId = toggleButtons[0].getAttribute('id').split('-'); | ||
|
||
toggleButtons.forEach(function(button) { | ||
button.addEventListener('click', function() { | ||
var parentToggleWrap = button.parentElement; | ||
parentToggleWrap.classList.add('clicked'); | ||
window.clearTimeout(toggleTimeout); | ||
|
||
splitId = button.getAttribute('id').split('-'); | ||
|
||
// select before image by its unique id | ||
var beforeImage = wrapper.querySelector('#image-' + splitId[1] + '-1'); | ||
|
||
if (splitId[2] == '1') { | ||
beforeImage.classList.remove('hidden'); | ||
} else { | ||
beforeImage.classList.add('hidden'); | ||
} | ||
|
||
if (!button.classList.contains('active')) { | ||
let activeToggleBtn = parentToggleWrap.querySelector('.toggle-btn.active'); | ||
if (activeToggleBtn) { | ||
activeToggleBtn.classList.remove('active'); | ||
} | ||
button.classList.add('active'); | ||
} | ||
}); | ||
}); | ||
|
||
var autoToggle = function() { | ||
var stepList = [2, 1, 2, 1, 2]; | ||
toggleStep(0); | ||
|
||
function toggleStep(step_i) { | ||
if (step_i < stepList.length) { | ||
var step = stepList[step_i]; | ||
|
||
if (!wrapper.querySelector('.image-toggle').classList.contains('clicked')) { | ||
// select before image by its unique id | ||
var beforeImage = wrapper.querySelector('#image-' + splitId[1] + '-1'); | ||
|
||
if (step == 1) { | ||
beforeImage.classList.remove('hidden'); | ||
} else { | ||
beforeImage.classList.add('hidden'); | ||
} | ||
|
||
let activeToggleBtn = wrapper.querySelector('.toggle-btn.active'); | ||
if (activeToggleBtn) { | ||
activeToggleBtn.classList.remove('active'); | ||
} | ||
|
||
wrapper.querySelector('#toggle-' + splitId[1] + '-' + step).classList.add('active'); | ||
|
||
toggleTimeout = window.setTimeout(toggleStep, 2000, step_i + 1); | ||
} | ||
} | ||
} | ||
}; | ||
|
||
autoToggle(); | ||
}); | ||
}; | ||
/* | ||
* Initially load the graphic | ||
* (NB: Use window.load to ensure all images have loaded) | ||
*/ | ||
window.onload = onWindowLoaded; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
@import "./lib/base"; | ||
|
||
body { | ||
max-width: 1000px; | ||
margin-left: auto; | ||
margin-right: auto; | ||
} | ||
|
||
h1, | ||
h2 { | ||
.mmedia-constrained-centered(); | ||
} | ||
|
||
.beforeafter + .beforeafter { | ||
margin-top: 33px; | ||
} | ||
|
||
.graphic h4 { | ||
.mmedia-constrained-centered(); | ||
.lato(); | ||
font-size: 18px; | ||
margin-bottom: 11px; | ||
color: #666; | ||
} | ||
|
||
.footer, | ||
.footnotes { | ||
.mmedia-constrained(); | ||
} | ||
|
||
.graphic + .footer { | ||
margin-top: -11px; | ||
} | ||
|
||
.top-wrapper { | ||
.clearfix(); | ||
text-align: center; | ||
|
||
.image-toggle, | ||
.legend { | ||
display: inline-block; | ||
} | ||
} | ||
|
||
.image-toggle { | ||
margin-right: 2.5%; | ||
padding-left: 5px; | ||
margin-bottom: 10px; | ||
} | ||
|
||
.toggle-btn { | ||
box-sizing: border-box; | ||
display: inline-block; | ||
width: 160px; | ||
padding: 8px; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
background-color: #ddd; | ||
color: #666; | ||
margin-left: -5px; | ||
opacity: 0.7; | ||
transition: all 200ms ease-in; | ||
.lato(); | ||
|
||
@media @screen-mobile { | ||
width: 120px; | ||
} | ||
|
||
.btn-hed { | ||
text-transform: uppercase; | ||
display: block; | ||
font-size: 13px; | ||
} | ||
|
||
.btn-dek { | ||
display: block; | ||
font-size: 11px; | ||
font-style: italic; | ||
font-weight: normal; | ||
color: #aaa; | ||
} | ||
|
||
&:first-child { | ||
border-top-right-radius: 0; | ||
border-bottom-right-radius: 0; | ||
} | ||
|
||
&:last-child { | ||
border-top-left-radius: 0; | ||
border-bottom-left-radius: 0; | ||
} | ||
|
||
&:hover { | ||
color: #999; | ||
opacity: 1; | ||
} | ||
|
||
&.active { | ||
background-color: #fff; | ||
border-color: #ddd; | ||
color: #454545; | ||
font-weight: bold; | ||
cursor: pointer; | ||
opacity: 1; | ||
} | ||
|
||
@media screen and (max-width: 500px) { | ||
font-size: 1.2em; | ||
|
||
img { | ||
display: none; | ||
} | ||
} | ||
} | ||
|
||
.img-wrapper { | ||
position: relative; | ||
max-width: 1240px; | ||
margin: 0 auto; | ||
overflow: hidden; | ||
|
||
img { | ||
padding: 0; | ||
margin: 0; | ||
max-width: 100%; | ||
display: block; | ||
|
||
// @media screen and (max-width: 500px) { | ||
// max-width: 130%; | ||
// margin-left: -15%; | ||
// } | ||
|
||
&.image-1 { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
transition: opacity 500ms ease-out; | ||
opacity: 1; | ||
|
||
&.hidden { | ||
opacity: 0; | ||
} | ||
} | ||
} | ||
} | ||
|
||
.footnotes { | ||
display: none; | ||
} | ||
|
||
@media screen and (max-width: 440px) { | ||
.top-wrapper { | ||
text-align: center; | ||
} | ||
} | ||
|
||
.hp { | ||
h1, h2, h4 { | ||
display: none; | ||
} | ||
|
||
.graphic { | ||
margin-bottom: 10px; | ||
} | ||
|
||
.footnotes { | ||
display: block; | ||
margin-bottom: 6px; | ||
} | ||
|
||
.footer, | ||
.footnotes { | ||
max-width: none; | ||
margin-left: 0; | ||
margin-right: 0; | ||
} | ||
|
||
.image-toggle { | ||
display: flex; | ||
padding: 0; | ||
margin: 0 auto 2px; | ||
justify-content: center; | ||
|
||
@media @screen-mobile-above { | ||
max-width: 400px; | ||
} | ||
} | ||
|
||
.toggle-btn { | ||
box-sizing: border-box; | ||
display: block; | ||
width: 50%; | ||
border: 1px solid #ccc; | ||
margin-left: 0; | ||
|
||
@media @screen-mobile { | ||
width: 50%; | ||
} | ||
|
||
&:first-child { | ||
border-right: none; | ||
} | ||
} | ||
} |
Oops, something went wrong.