Skip to content

Instantly share code, notes, and snippets.

@Rayraegah

Rayraegah/index.pug

Created Oct 8, 2018
Embed
What would you like to do?
"Random" color harmonies
#app.wrap
-// input(type='number', v-model='amount' v-on:change="newColors")
.bg
.colors()
button.refresh(v-on:click="newColors").
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" viewBox="0 0 23 23" version="1.1" x="0px" y="0px"><path d="M 12.109896,2.9653518 C 10.830826,2.9134678 9.5257058,3.132602 8.2817758,3.648946 c -3.9806,1.652399 -6.2540499,5.897846 -5.4179699,10.123046 0.8360799,4.2253 4.5540699,7.274132 8.8613301,7.269532 a 0.9995584,1.0006417 14.999899 1 0 0,-2 c -3.3667302,0 -6.2475202,-2.360557 -6.9004002,-5.660157 -0.65294,-3.2997 1.11025,-6.592765 4.22266,-7.884765 3.1124002,-1.292 6.6825102,-0.213669 8.5488302,2.582031 1.85391,2.77709 1.49946,6.460477 -0.8418,8.845703 l 0.0781,-2.365234 a 1.0001,1.0001 0 0 0 -0.98242,-1.046875 1.0001,1.0001 0 0 0 -1.01758,0.982422 l -0.15235,4.59375 a 1.0001,1.0001 0 0 0 1.03321,1.033203 l 4.5957,-0.152344 a 1.0001,1.0001 0 1 0 -0.0664,-1.998047 l -1.79492,0.06055 c 2.74739,-3.056097 3.10892,-7.618693 0.80859,-11.064453 -1.64326,-2.461525 -4.33252,-3.887808 -7.14648,-4.0019532 z"/></svg>
button.expand(v-on:click="newColors").
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23" x="0px" y="0px"><defs><style>.cls-1{fill:none;stroke:#000;stroke-linecap:round;stroke-linejoin:round;}</style></defs><polyline class="cls-1" points="18.5 14.5 21.5 11.5 18.5 8.5"/><polyline class="cls-1" points="4.5 8.5 1.5 11.5 4.5 14.5"/><line class="cls-1" x1="1.5" y1="11.5" x2="8.5" y2="11.5"/><line class="cls-1" x1="14.5" y1="11.5" x2="21.5" y2="11.5"/></svg>
color(v-for="c in colors", v-bind:color="c")
const shuffleArray = arr => arr
.map(a => [Math.random(), a])
.sort((a, b) => a[0] - b[0])
.map(a => a[1]);
const random = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var generateRandomColors = (total, mode = 'lab', padding = .175, parts = 4) => {
// modified version of http://www.husl-colors.org/syntax/
let colors = [];
const part = Math.floor(total / parts);
const reminder = total % parts;
// hues to pick from
const baseHue = random(0, 360);
const hues = [0, 60, 120, 180, 240, 300].map(offset => {
return (baseHue + offset) % 360;
});
// low saturated color
const baseSaturation = random(5, 40);
const baseLightness = random(0, 20);
const rangeLightness = 90 - baseLightness;
colors.push( HUSL.toHex(
hues[0],
baseSaturation,
baseLightness * random(.25, .75)
) );
for (let i = 0; i < (part - 1); i++) {
colors.push( HUSL.toHex(
hues[0],
baseSaturation,
baseLightness + (rangeLightness * Math.pow(i/(part - 1), 1.5))
) );
}
// random shades
const minSat = random(50, 70);
const maxSat = minSat + 30;
const minLight = random(45, 80);
const maxLight = Math.min(minLight + 40, 95);
for (let i = 0; i < (part + reminder - 1); i++) {
colors.push( HUSL.toHex(
hues[random(0, hues.length - 1)],
random(minSat, maxSat),
random(minLight, maxLight)
) )
}
colors.push( HUSL.toHex(
hues[0],
baseSaturation,
rangeLightness
) );
//colors = shuffleArray(colors);
return chroma.scale(colors).padding(padding).mode(mode).colors(total);
}
Vue.component('color', {
props: ['color'],
template: `<div class="color" v-bind:style="{background: color, color: textColor}">
<div class="label">{{ color }}</div>
<div class="name">{{ name }}</div>
</div>`,
computed: {
name: function () {
return getClosestNamedColor( this.color ).name;
},
textColor: function () {
let currentColor = chroma( this.color );
let lum = currentColor.luminance();
let contrastColor;
if ( lum < 0.15 ) {
contrastColor = currentColor.set('hsl.l', '+.25');
} else {
contrastColor = currentColor.set('hsl.l', '-.35');
}
return contrastColor;
}
}
});
let colors = new Vue({
el: '#app',
data: () => {
return {
colors: [],
amount: 6,
}
},
methods: {
newColors: function () {
let colorArr = generateRandomColors(this.amount)
this.colors = colorArr;
let gradient = [...colorArr];
gradient[0] += ' 12vmin'
gradient[gradient.length - 1] += ' 69%'
document.querySelector('.bg').style['background-image'] = `
linear-gradient(to bottom, ${gradient.join(',')})
`;
document.querySelector('.refresh').style.background = this.colors[this.colors.length - 1]
document.querySelector('.expand').style.background = this.colors[this.colors.length - 1]
}
},
mounted: function () {
this.newColors();
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/husl/6.0.1/husl.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chroma-js/1.2.2/chroma.min.js"></script>
<script src="//cdn.rawgit.com/dtao/nearest-color/master/nearestColor.js"></script>
<script src="//codepen.io/meodai/pen/VLVRYw"></script>
@import url('https://fonts.googleapis.com/css?family=Space+Mono');
button {
border: none;
margin: 0;
padding: 0;
width: auto;
overflow: visible;
background: transparent;
/* inherit font & color from ancestor */
color: inherit;
font: inherit;
/* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */
line-height: normal;
/* Corrects font smoothing for webkit */
-webkit-font-smoothing: inherit;
-moz-osx-font-smoothing: inherit;
/* Corrects inability to style clickable `input` types in iOS */
-webkit-appearance: none;
}
html {
font-size: calc(.75rem + 1.15vh);
font-family: 'Space Mono', monospace;
}
body {
height: 100vh;
background: #212121;
overflow: hidden;
}
input {
position: absolute;
z-index: 2;
}
.wrap, .bg {
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}
.bg {
//clip-path: inset(12vmin 26% 12vmin 26%);
}
.colors {
//opacity: .8;
position: absolute;
left: 50%;
bottom: 10vmin; top: 10vmin;
display: flex;
flex-direction: column;
cursor: pointer;
transform: translateX(-50%);
width: 52%;
@media (max-width: 700px){
width: 75%;
}
}
.color {
position: relative;
display: flex;
@media (max-width: 700px){
display: block;
padding: 1rem;
}
align-items: center;
padding: 0 1rem;
flex-grow: 1;
will-change: min-height;
&::after {
opacity: .5;
content: '';
position: absolute;
left: 0; right: 0; bottom: 0; top: 0;
box-shadow: 0 0 10rem currentColor;
}
/*
border: solid currentColor;
border-width: 0 2px;
*/
transition: 200ms color linear, 200ms background-color linear, 300ms min-height cubic-bezier(.7,.3,0,1.1);
min-height: 0.1vmax;
&:last-child {
padding-bottom: #{1.61803 * 4rem};
}
&:hover {
min-height: 10vmax;
}
}
.label {
flex-grow: 1;
padding-right: 1rem;
font-size: .75em;
@media (max-width: 700px){
font-weight: bold;
font-size: .6em;
margin-bottom: .15em;
}
}
.name {
font-size: .8em;
text-align: right;
@media (max-width: 700px){
text-align: left;
}
}
.refresh, .expand {
z-index: 1;
position: absolute;
top: 100%; left: 100%;
margin: 0;
padding: 0;
transform: translate(-60%,-60%);
font-size: 2em;
width: 1.2em; height: 1.2em;
background: #000;
color: #fff;
border-radius: 50%;
outline: 0;
box-shadow: 0 0 2rem rgba(#000, .2);
cursor: pointer;
svg {
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%,-50%);
animation-name: rotate;
animation-duration: 3s;
width: .6em; height: .6em;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-play-state: paused;
line-height: 1;
fill: #fff;
}
&:hover {
svg {
animation-play-state: running;
}
}
}
.expand {
display: none;
margin-left: -1.4em;
svg {
fill: none;
stroke: #fff;
stroke-width: 1.5;
animation: none;
width: .75em; height: .75em;
}
}
@keyframes rotate {
from {transform: translate(-50%,-50%) rotate(0deg);}
to {transform: translate(-50%,-50%) rotate(360deg);}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment