diff --git a/src/assets/content/ChartGrid.js b/src/assets/content/ChartGrid.js index b13bf48c3c8f11b654094d5ab80fdfb7dd0de9b6..db21cd4ca336550a3b8ff3ba06d3fe888b607d95 100644 --- a/src/assets/content/ChartGrid.js +++ b/src/assets/content/ChartGrid.js @@ -5,13 +5,23 @@ export default { { title: 'Inland fisheries are threatened', project: 'Findex', - vizKey: 'ThreatSankey', + vizKey: 'FindexThreatSankey', vizRoute: 'inland-fish-total-threats', img_src: 'Placeholder_thumbnail.webp', alt: '', chartOrder: 1, description: 'Land use change is threatening inland fisheries.' }, + { + title: 'Threats to inland fisheries vary across the globe', + project: 'Findex', + vizKey: 'FindexGlobalThreats', + vizRoute: 'inland-fish-global-threats', + img_src: 'Placeholder_thumbnail.webp', + alt: '', + chartOrder: 2, + description: 'Inland fisheries are threatened globally.' + }, { title: 'Explore the Juneau Icefield', project: 'Fire in Ice', diff --git a/src/assets/css/main.css b/src/assets/css/main.css index a275007bcd4535123ba80c1205766e304ecc5b61..0bb765e4a699aa0ebc541f775ab7f2b35c19132c 100644 --- a/src/assets/css/main.css +++ b/src/assets/css/main.css @@ -123,11 +123,11 @@ a:hover { /* css for Beaufort species-related viz */ .highlight { - padding: 0.5px 8px 0.5px 5px; + padding: 0.05rem 0.8rem 0.15rem 0.5rem; border-radius: 10px; white-space: nowrap; font-weight: bold; - transition: all 0.1s; + /* transition: all 0.1s; */ } #cassidulina { color: white; diff --git a/src/assets/text/authors.js b/src/assets/text/authors.js index 77765a1503f301da44078a50584c5e209ff41df4..5ac69f47d003d8ef36314b47222fd9eaea9a9c1d 100644 --- a/src/assets/text/authors.js +++ b/src/assets/text/authors.js @@ -100,7 +100,19 @@ export default { profile_link: 'https://www.usgs.gov/staff-profiles/hayley-corson-dosch' }, ], - ThreatSankey: [ + FindexThreatSankey: [ + { + fullName: 'Hayley Corson-Dosch', + initials: 'HCD', + profile_link: 'https://www.usgs.gov/staff-profiles/hayley-corson-dosch' + }, + ], + FindexGlobalThreats: [ + { + fullName: 'Kaysa Vaarre-Lamoureux', + initials: 'KVL', + profile_link: null + }, { fullName: 'Hayley Corson-Dosch', initials: 'HCD', diff --git a/src/assets/text/text.js b/src/assets/text/text.js index 3d4befe9e1e74324767356eaebaa5e7df87642d2..5cbd371b4d2d2912d6c0b744ea4888d7ece1936e 100644 --- a/src/assets/text/text.js +++ b/src/assets/text/text.js @@ -232,8 +232,63 @@ export default { explanation1: "As scientists <a href='/visualizations/earth-in-flux/#/fire-in-ice/glacier-scan' target='_blank'>collected the snow core</a>, they carefully stored each ten-centimeter section for transport off the Juneau Icefield. The retrieved samples were analyzed in a laboratory for particle counts, major ions, stable isotopes of oxygen and hydrogen, and the three sugars that are markers of biomass combustion—mannosan, galactosan, and levoglucosan.", explanation2: "In this visual representation of the core, the darker grey shows layers of the snow that had high amounts of particulate matter. The high-particulate layer present in both 2015 and 2016 likely represents the summer melt surface." }, - ThreatSankey: { + FindexThreatSankey: { paragraph1: 'Land use change is the biggest threat to inland fisheries.' + }, + FindexGlobalThreats: { + paragraph1: 'Threats to inland fisheries.', + tabData: [ + { + tabTitle: "Habitat", + tabContentTitle: "Habitat", + tabContentTitleID: "habitat", + tabIcon: "noun-canal-29572-7A562B", + tabText: "Habitat text.", + tabImageAlt: "Habitat alt.", + subThreatPrefix: "H_", + subThreatData: ["Dams", "Wetland drainage", "Deforestation and associated runoff", "Riparian degradation", "Agricultural extraction", "Urban extraction", "Industrial Extraction"] + }, + { + tabTitle: "Pollution", + tabContentTitle: "Pollution", + tabContentTitleID: "pollution", + tabIcon: "noun-drain-7131918-002D5E", + tabText: "Pollution text.", + tabImageAlt: "Pollution alt.", + subThreatPrefix: "P_", + subThreatData: ["Agricultural effluents", "Urban wastewater", "Industrial effluents", "Aquaculture effluents", "Pharmaceuticals", "Oil or gas exploration", "Plastics", "Mining"] + }, + { + tabTitle: "Climate and Weather", + tabContentTitle: "Climate and Weather", + tabContentTitleID: "climate-and-weather", + tabIcon: "noun-rain-1760091-835192", + tabText: "Climate and Weather text.", + tabImageAlt: "Climate and Weather alt.", + subThreatPrefix: "CW_", + subThreatData: ["Change in water temperature", "Drought", "Change in flooding", "Change in wind patterns", "Change in ice cover"] + }, + { + tabTitle: "Invasive species", + tabContentTitle: "Invasive species", + tabContentTitleID: "invasive-species", + tabIcon: "noun-competition-1371235-4E6D6E", + tabText: "Invasive species text.", + tabImageAlt: "Invasive species alt.", + subThreatPrefix: "IS_", + subThreatData: [] + }, + { + tabTitle: "Exploitation", + tabContentTitle: "Exploitation", + tabContentTitleID: "exploitation", + tabIcon: "noun-fishing-1545130-B74F49", + tabText: "Exploitation text.", + tabImageAlt: "Exploitation alt.", + subThreatPrefix: "E_", + subThreatData: [] + } + ], } } } \ No newline at end of file diff --git a/src/components/FindexGlobalThreatsViz.vue b/src/components/FindexGlobalThreatsViz.vue new file mode 100644 index 0000000000000000000000000000000000000000..c7bd557f1b75425b1cd73c2caca9ca533b5c6dae --- /dev/null +++ b/src/components/FindexGlobalThreatsViz.vue @@ -0,0 +1,406 @@ +<template> + <!---VizSection--> + <VizSection + :figures="true" + :fig-caption="false" + > + <!-- HEADING --> + <template #heading> + <h2> + </h2> + </template> + <!-- FIGURES --> + <template #aboveExplanation> + <p v-html="text.paragraph1" /> + </template> + <template #figures> + <tabsGroup id="map-tabs" :options="{ useUrlFragment: false }" > + <tabItem v-for="tab in text.tabData" :name="tab.tabTitle" :key="tab.tabTitle" :prefix="getPrefixImageHTML(tab.tabIcon)"> + <h3> + Threat category: + <button v-html="tab.tabContentTitle" @click = "switchToPrimaryCategory(tab.tabContentTitle, tab.subThreatPrefix)" :class="[tab.tabContentTitleID, { 'active': currentCategory == tab.tabContentTitle, 'highlight': currentCategory == tab.tabContentTitle }]" :id="tab.tabContentTitleID" class="category-button" /> + </h3> + <div id="button-container"> + <h4 v-if="tab.subThreatData.length > 1">Subthreat categories: + <span v-for="subThreat, index in tab.subThreatData" :key="subThreat"> + <button @click="switchToSubCategory(subThreat, tab.subThreatPrefix)" :class="[tab.tabContentTitleID, { 'active': currentCategory == subThreat, 'highlight': currentCategory == subThreat }]" v-html="subThreat" class="subcategory-button"></button> + <span v-if="index < tab.subThreatData.length-1"> | </span> + </span> + </h4> + </div> + <p v-html="tab.tabText" /> + <img class="tab-content-image" :src="mapSource" :alt="tab.tabImageAlt"> + </tabItem> + </tabsGroup> + </template> + <!-- FIGURE CAPTION --> + <template #figureCaption> + </template> + <!-- EXPLANATION --> + <template #belowExplanation> + </template> + </VizSection> +</template> + +<script setup> + import { nextTick, onMounted, ref } from "vue"; + // import { isMobile } from 'mobile-device-detect'; + import VizSection from '@/components/VizSection.vue'; + + // define props + const props = defineProps({ + text: { type: Object } + }) + + // Global variables + // const publicPath = import.meta.env.BASE_URL; + // const mobileView = isMobile; + let primaryCategorySelected = ref(true); + let currentCategory = ref(null); + let currentCategorySubThreatPrefix = ref(null); + let mapSource = ref(null); + + // Declare behavior on mounted + // functions called here + onMounted(async () => { + try { + console.log("on mounted") + + // Once DOM is up to date, make sure the currently shown tab is updated + await nextTick() + updateTab() + + // add event listeners to all tabs, so that update on click + const tabs = document.getElementById("map-tabs") + const tabList = tabs.querySelectorAll("a") + tabList.forEach(tab => { + tab.href = "" + tab.addEventListener("click", updateTab) + }) + } catch (error) { + console.error('Error during component mounting', error); + } + }); + function updateTab() { + // identify active tab + const tabs = document.getElementById("map-tabs") + console.log(tabs) + console.log(tabs.querySelectorAll("a")) + const activeTab = tabs.querySelectorAll(".is-active a") + console.log(activeTab) + + // pull category information + currentCategory.value = activeTab[0].text + const currentData = props.text.tabData.filter(d => d.tabContentTitle == currentCategory.value) + currentCategorySubThreatPrefix.value = currentData.subThreatPrefix + + // update map + switchToPrimaryCategory(currentCategory.value, currentCategorySubThreatPrefix.value) + } + function getPrefixImageURL(filename) { + return `src/assets/images/${filename}.png` + } + function getPrefixImageHTML(filename) { + const imgURL = getPrefixImageURL(filename) + return `<img class='tab-image' src=${imgURL}>` + } + function getContentImageUrl(title, category_prefix) { + if (primaryCategorySelected.value) { + return `src/assets/images/${title.replace(/ /g, "_")}_map.png` + } else { + return `src/assets/images/${category_prefix}${title.replace(/ /g, "_")}_map.png` + } + } + function switchToSubCategory(category, prefix) { + primaryCategorySelected.value = false; + currentCategory.value = category + currentCategorySubThreatPrefix.value = prefix + console.log(`switching to ${currentCategory.value}, ${currentCategorySubThreatPrefix.value}`) + mapSource.value = getContentImageUrl(currentCategory.value, currentCategorySubThreatPrefix.value) + } + function switchToPrimaryCategory(category, prefix) { + primaryCategorySelected.value = true; + currentCategory.value = category + currentCategorySubThreatPrefix.value = prefix + mapSource.value = getContentImageUrl(currentCategory.value, currentCategorySubThreatPrefix.value) + } + +</script> + +<style> + +#map-tabs { + margin-top: 3rem; +} +#button-container { + margin-bottom: 2rem; +} +.active { + /* border-color: ; */ + border-width: 3px; + border-style: solid; + /* border-radius: 1.5px; */ + opacity: 1; + font-weight: 500; + color: white; + /* transform: scale(1.1); */ + + } +/* .active.habitat { + background-color: #7A562B; +} */ +.category-button { + background-color: transparent; + padding-left: 0.75rem; + padding-bottom: 0.2rem; + border: 0rem; + padding: 0.05rem 0.8rem 0.2rem 0.75rem; + border-radius: 10px; + white-space: nowrap; + font-weight: bold; + font-size: 2.2rem; + margin-bottom: 1rem; +} +.category-button:hover { + color: var(--color-text) +} +.category-button:hover.habitat { + background-color: #E1C8AA; +} +.category-button:hover.pollution { + background-color: #B2C0CE; +} +.category-button:hover.climate-and-weather { + background-color: #DDCCE2; +} +.category-button:hover.invasive-species { + color: white; + /* background-color: #C9D8D9; */ +} +.category-button:hover.exploitation { + color: white; + /* background-color: #E1C8AA; */ +} +.highlight.habitat { + background-color: #7A562B; +} +.highlight.pollution { + background-color: #002D5E; +} +.highlight.climate-and-weather { + background-color: #835192; +} +.highlight.invasive-species { + background-color: #4E6D6E; +} +.highlight.exploitation { + background-color: #B74F49; +} +.subcategory-button { + background-color: transparent; + border: 0rem; + border-radius: 10px; + padding: 0.05rem 0.8rem 0.2rem 0.75rem; +} +.subcategory-button:hover { + color: var(--color-text) +} +.subcategory-button:hover.habitat { + background-color: #E1C8AA; +} +.subcategory-button:hover.pollution { + background-color: #B2C0CE; +} +.subcategory-button:hover.climate-and-weather { + background-color: #DDCCE2; +} +ul { + padding-inline-start: 0px; +} +li { + padding: 0; +} +.tabs-component { + margin: auto; + width: 90vw; + max-width: 1000px; +} +@media (min-width: 1000px) { + .tabs-component { + width: 70vw; + } +} +.tab-image { + max-width: 2.5rem; + max-height: 2.5rem; + margin-right: 1rem; + height: auto; + width: auto; +} + +@media (min-width: 1000px) { + .tab-image { + max-width: fit-content; + max-height: 5rem; + margin-bottom: 1rem; + height: 5rem; + width: auto; + } +} +.subheading-container { + margin: 1rem 0 1rem 0; + height: 5rem; +} +.subheading-image { + /* max-width: 5rem; */ + height: 5rem; + margin: 0 1rem 0 1rem; +} +.subheading { + padding: 0; + display: inline-block; + transform: translate(0%, -50%); +} +.tabs-component-tab.is-inactive img { + opacity: 0.5; +} +.tab-content-image { + width: 100%; +} +.tab-content-title { + padding: 1rem 1rem 1rem 1rem; + line-height: 2.6rem; +} +/* css modified from vue-tabs-component demo: https://tabs-component.jakubpotocky.sk/ */ +.tabs-component-tabs { + border: solid 1px #ddd; + border-radius: 6px; + margin-bottom: 5px; +} + +@media (min-width: 1000px) { + .tabs-component-tabs { + border: 0; + align-items: stretch; + display: flex; + justify-content: flex-start; + margin-bottom: -1px; + } +} + +.tabs-component-tab, .tabs-component-tab--custom { + color: #999; + font-size: 1.6rem; + font-weight: 600; + margin-right: 0; + list-style: none; +} + +.tabs-component-tab:not(:last-child) { + border-bottom: dotted 1px #ddd; +} + +.tabs-component-tab:hover { + color: #666; +} + +.tabs-component-tab.is-active { + color: #000; +} +.tabs-component-tab.is-disabled *, .tabs-component-tab--custom.is-disabled * { + color: #cdcdcd; + cursor: not-allowed !important; +} + +@media (min-width: 1000px) { + .tabs-component-tab, .tabs-component-tab--custom { + background-color: #fff; + border: solid 1px #ddd; + border-radius: 3px 3px 0 0; + margin-right: .5em; + /* transform: translateY(4px); */ + transition: transform .3s ease; + font-size: 1.6rem; + text-align: center; + } + + .tabs-component-tab.is-active, .tabs-component-tab--custom.is-active { + border-bottom: solid 1px #fff; + z-index: 2; + transform: translateY(0); + } +} + +@media (min-width: 1000px) { + .tabs-component-tab-a, .tabs-component-tab-a--custom { + align-items: center; + color: inherit; + display: flex; + flex-direction: column; + padding: .75em 1em; + text-decoration: none; + } +} + +.tabs-component-tab-a, .tabs-component-tab-a--custom { + align-items: center; + color: inherit; + display: flex; + padding: .75em 1em; + text-decoration: none; +} + +.tabs-component-panels { + padding: 2em 1em; + background-color: #fff; + border: solid 1px #ddd; + border-radius: 0 6px 6px 6px; + box-shadow: 0 0 10px rgba(0, 0, 0, .05); +} + +@media (min-width: 1000px) { + .tabs-component-panels { + background-color: #fff; + border: solid 1px #ddd; + border-radius: 0 6px 6px 6px; + box-shadow: 0 0 10px rgba(0, 0, 0, .05); + padding: 2em 2em; + } +} + +.tabs-component-btn { + cursor: pointer; + background: #e1ecf4; + border-radius: 3px; + border: 1px solid #7aa7c7; + padding: 4px 8px; + color: #39739d; +} + +.tabs-component-btn:hover { + background-color: #b3d3ea; + color: #2c5777; +} + +.tabs-component-btn:active { + background-color: #a0c7e4; + box-shadow: none; + color: #2c5777; +} + +.tabs-component-tab--custom { + border-color: #e1ecf4; + color: #68838d; +} + +.tabs-component-tab--custom:hover { + border-color: #e1ecf4; + color: #39739d; +} + +.tabs-component-tab--custom.is-active { + color: #39739d; + border-color: #7aa7c7; + border-bottom: solid 1px #fff; +} +</style> \ No newline at end of file