1
0
mirror of https://github.com/Mayccoll/Gogh.git synced 2023-08-10 21:12:46 +03:00

Website Filter by Bg Color

This commit is contained in:
Mayccoll 2020-12-19 19:18:16 -05:00
parent 7f795cd7b0
commit 5ae0690564
5 changed files with 287 additions and 95 deletions

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -27,15 +27,15 @@
<body> <body>
<a href=https://github.com/Mayccoll/Gogh> <a href=https://github.com/Mayccoll/Gogh>
<img <img
loading="lazy" loading="lazy"
width="149" width="149"
height="149" height="149"
style="position: absolute; top: 0; right: 0; border: 0;" style="position: absolute; top: 0; right: 0; border: 0;"
src="https://github.blog/wp-content/uploads/2008/12/forkme_right_darkblue_121621.png" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_darkblue_121621.png"
class="attachment-full size-full" class="attachment-full size-full"
alt="Fork me on GitHub" alt="Fork me on GitHub"
data-recalc-dims="1"> data-recalc-dims="1">
</a> </a>
<header class=gogh-header> <header class=gogh-header>
@ -52,6 +52,7 @@
<h2> <h2>
Color Scheme for Gnome Terminal, Pantheon Terminal, Tilix, and XFCE4 Terminal Color Scheme for Gnome Terminal, Pantheon Terminal, Tilix, and XFCE4 Terminal
</h2> </h2>
<p> <p>
Color Schemes For Ubuntu, Linux Mint, Elementary OS and all distributions that use Gnome Terminal, Pantheon Terminal, Tilix, or XFCE4 Terminal; initially inspired by Elementary OS Luna. Also works on iTerm for macOS. Color Schemes For Ubuntu, Linux Mint, Elementary OS and all distributions that use Gnome Terminal, Pantheon Terminal, Tilix, or XFCE4 Terminal; initially inspired by Elementary OS Luna. Also works on iTerm for macOS.
</p> </p>
@ -107,29 +108,50 @@
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<div class="filters"> <div class="filters">
<button class="btn" <button class="btn js-btn--filter"
v-bind:class="{ active: filter === 'all' }" :class="{ active: filter === 'all' }"
v-on:click="setFilter('all')"> @click="setFilter('all'); resetMenuSelected()">
All All
</button> </button>
<button class="btn" <button class="btn js-btn--filter"
v-bind:class="{ active: filter === 'light' }" :class="{ active: filter === 'light' }"
v-on:click="setFilter('light')"> @click="setFilter('light'); resetMenuSelected()">
Light Themes Light Themes
</button> </button>
<button class="btn" <button class="btn js-btn--filter"
v-bind:class="{ active: filter === 'dark' }" :class="{ active: filter === 'dark' }"
v-on:click="setFilter('dark')"> @click="setFilter('dark'); resetMenuSelected()">
Dark Themes Dark Themes
</button> </button>
<button class="btn js-btn--filter-bg"
:class="{ active: selected === 'background' }"
@click="getBackgrounds()">
by Background
</button>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="filter-background js-filter-background" style="display: none;">
<template v-for="item in themeBackgrounds">
<button class="btn btn--filter-bg"
:class="{ active: filter === item.toLowerCase() }"
:style="'background-color:' + item"
@click="setFilter(item)">
<span>{{ item.toLowerCase() }}</span>
</button>
</template>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<template v-for="theme in themes"> <template v-for="theme in themes">
<div class="col-md-6 col-lg-6 col-xl-4" v-show="filter === theme.category || filter === 'all'"> <div class="col-md-6 col-lg-6 col-xl-4" v-show="filter === theme.category || filter === 'all' || filter === 'background' || filter === theme.background.toLowerCase()">
<div class="terminal"> <div class="terminal">
<div class=bar> <div class=bar>
<div class="bar__title"> <div class="bar__title">
@ -240,7 +262,9 @@
<a target=_blank href="https://clipboardjs.com/"> Clipboardjs </a> put it all together : <a target=_blank href="https://clipboardjs.com/"> Clipboardjs </a> put it all together :
</footer> </footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.slim.min.js" integrity="sha512-/DXTXr6nQodMUiq+IUJYCt2PPOUjrHJ9wFrqpJ3XkgPNOZVfMok7cRw6CSxyCQxXn6ozlESsSh1/sMCTF1rL/g==" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js" integrity="sha512-bLT0Qm9VnAYZDflyKcBaQ2gg0hSYNQrJ8RilYldYQ1FxQYoCLtUjuuRuZo+fjqhx/qtq/1itJ0C2ejDxltZVFg==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/2.1.0/chroma.min.js" integrity="sha512-yocoLferfPbcwpCMr8v/B0AB4SWpJlouBwgE0D3ZHaiP1nuu5djZclFEIj9znuqghaZ3tdCMRrreLoM8km+jIQ==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/components/prism-core.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/components/prism-core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/plugins/autoloader/prism-autoloader.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.22.0/plugins/autoloader/prism-autoloader.min.js"></script>

View File

@ -1,4 +1,4 @@
/* global $, Vue, axios */ /* global $, Vue, axios, chroma, vm */
/* eslint no-undef: "error", semi: 2 */ /* eslint no-undef: "error", semi: 2 */
/** /**
@ -13,11 +13,14 @@ new ClipboardJS('.btn-copy');
* *
* ······· Functions * ······· Functions
* *
*/ */
function lightOrDark(color) { function lightOrDark (color) {
// Variables for red, green, blue values // Variables for red, green, blue values
var r, g, b, hsp; var r,
g,
b,
hsp;
// Check the format of the color, HEX or RGB? // Check the format of the color, HEX or RGB?
if (color.match(/^rgb/)) { if (color.match(/^rgb/)) {
// If RGB --> store the red, green, blue values in separate variables // If RGB --> store the red, green, blue values in separate variables
@ -42,11 +45,77 @@ function lightOrDark(color) {
} }
} }
/**
*
* ······· Color Functions
*
*/
function colorDistance (color1, color2) {
// This is actually the square of the distance but
// this doesn't matter for sorting.
var result = 0;
for (var i = 0; i < color1.length; i++)
result += (color1[i] - color2[i]) * (color1[i] - color2[i]);
return result;
}
function sortColors (colors) {
// Calculate distance between each color
var distances = [];
for (var i = 0; i < colors.length; i++) {
distances[i] = [];
for (var j = 0; j < i; j++)
distances.push([
colors[i],
colors[j],
colorDistance(colors[i], colors[j]),
]);
}
distances.sort(function (a, b) {
return a[2] - b[2];
});
// Put each color into separate cluster initially
var colorToCluster = {};
for (var y = 0; y < colors.length; y++)
colorToCluster[colors[y]] = [colors[y]];
// Merge clusters, starting with lowest distances
var lastCluster;
for (var e = 0; e < distances.length; e++) {
var color1 = distances[e][0];
var color2 = distances[e][1];
var cluster1 = colorToCluster[color1];
var cluster2 = colorToCluster[color2];
if (!cluster1 || !cluster2 || cluster1 == cluster2)
continue;
// Make sure color1 is at the end of its cluster and
// color2 at the beginning.
if (color1 !== cluster1[cluster1.length - 1])
cluster1.reverse();
if (color2 !== cluster2[0])
cluster2.reverse();
// Merge cluster2 into cluster1
cluster1.push.apply(cluster1, cluster2);
delete colorToCluster[color1];
delete colorToCluster[color2];
colorToCluster[cluster1[0]] = cluster1;
colorToCluster[cluster1[cluster1.length - 1]] = cluster1;
lastCluster = cluster1;
}
// By now all colors should be in one cluster
return lastCluster;
}
/** /**
* *
* ······· Vue App * ······· Vue App
* *
*/ */
var $getUrl = 'https://raw.githubusercontent.com/Mayccoll/Gogh/master/data/themes.json'; var $getUrl = 'https://raw.githubusercontent.com/Mayccoll/Gogh/master/data/themes.json';
@ -54,24 +123,63 @@ const $app = {
data () { data () {
return { return {
themes: [], themes: [],
filter: 'all' filter: 'all',
themeBackgrounds: null,
selected: null
}; };
}, },
created () { created () {
axios.get($getUrl) axios.get($getUrl).then((response) => {
.then((response) => { this.themes = response.data.themes;
this.themes = response.data.themes; this.themes.forEach((v) => {
this.themes.forEach((v) => { v.category = lightOrDark(v.background);
v.category = lightOrDark(v.background);
});
}); });
});
}, },
methods: { methods: {
setFilter: function (f) { setFilter (f) {
this.filter = ''; this.filter = '';
setTimeout(() => { this.filter = f; }, 50); setTimeout(() => {
this.filter = f;
}, 100);
},
setBackground () {
this.filter = 'background';
},
getBackgrounds () {
const $bgs = this.themes.map(e => e.background);
const $bgsLowerCase = $bgs.map((ele) => ele.toLowerCase());
const $bgsUnique = [...new Set($bgsLowerCase)];
const $bgsRGB = $bgsUnique.map((ele) => chroma(ele).rgb());
const $bgsSort = sortColors($bgsRGB);
const $bgsHEX = $bgsSort.map(ele => chroma(ele).hex());
this.themeBackgrounds = $bgsHEX;
this.selected = 'background';
this.filter = 'background';
},
resetMenuSelected () {
this.selected = '';
} }
} }
}; };
Vue.createApp($app).mount('#js-vue-app'); Vue.createApp($app).mount('#js-vue-app');
/**
*
* ······· Menu
*
*/
$('.js-btn--filter-bg').on('click', function () {
$('.js-filter-background').slideToggle();
});
$('.js-btn--filter').on('click', function () {
$('.js-filter-background').slideUp(400);
});

View File

@ -136,6 +136,125 @@
margin : 0 0 40px; margin : 0 0 40px;
text-align: center; text-align: center;
} }
/**
*
* ······· Filters
*
*/
.filters {
display : flex;
justify-content: center;
margin : 0 0 40px;
.btn {
position: relative;
margin : 0 15px;
&:hover {
&::before {
position : absolute;
right : 0;
bottom : -10px;
left : 0;
margin : 0 auto;
width : 100%;
height : 1px;
background-color : #0d1926;
content : " ";
opacity : 1;
animation-name : anim-gogh-bg;
animation-duration: 8s;
}
}
&::before {
position : absolute;
right : 0;
bottom : -10px;
left : 0;
margin : 0 auto;
width : 0;
height : 1px;
background-color: #0d1926;
content : " ";
opacity : 0;
transition : all 0.3s ease;
}
&.active {
background-color: #0d1926;
color : #e7e7e7;
}
&.active::before {
position : absolute;
right : 0;
bottom : -10px;
left : 0;
width : 100%;
height : 1px;
background-color: #0d1926;
content : " ";
opacity : 1;
}
}
}
/**
*
* ······· Filters Bg
*
*/
.filter-background {
margin: 0 0 70px;
.btn--filter-bg {
position : relative;
padding : 0;
width : 5%;
height : 40px;
border : none;
cursor : pointer;
transition: all 0.3s ease, border-radius 0.9s ease;
span {
position : absolute;
bottom : -12px;
display : none;
padding : 1px 3px;
width : 100%;
border-radius : 1px;
background : #0d1926;
color : #ffffff;
text-align : center;
text-transform: none;
font-size : 0.6rem;
transition : all 0.3s ease;
}
&:hover {
z-index : 20;
height : 40px;
border : 1px solid #414141;
border-radius: 1px;
transform : scale(1.6);
span {
display: block;
}
}
}
.btn--filter-bg.active {
z-index : 10;
border : 1px solid #414141;
border-radius: 1px;
transform : scale(1.6);
span {
display: block;
}
}
}
/** /**
* *
* ······· Main Content * ······· Main Content
@ -160,65 +279,6 @@
@include m2200 { @include m2200 {
max-width: 74%; max-width: 74%;
} }
.filters {
display : flex;
justify-content: center;
margin : 0 0 60px;
.btn {
position: relative;
margin : 0 15px;
&:hover {
&::before {
position : absolute;
right : 0;
bottom : -10px;
left : 0;
margin : 0 auto;
width : 100%;
height : 1px;
background-color : #0d1926;
content : " ";
opacity : 1;
animation-name : anim-gogh-bg;
animation-duration: 8s;
}
}
&::before {
position : absolute;
right : 0;
bottom : -10px;
left : 0;
margin : 0 auto;
width : 0;
height : 1px;
background-color: #0d1926;
content : " ";
opacity : 0;
transition : all 0.3s ease;
}
&.active {
background-color: #0d1926;
color : #e7e7e7;
}
&.active::before {
position : absolute;
right : 0;
bottom : -10px;
left : 0;
width : 100%;
height : 1px;
background-color: #0d1926;
content : " ";
opacity : 1;
}
}
}
} }
/** /**
* *