mirror of
https://github.com/janishutz/color-thief.git
synced 2025-11-25 05:44:24 +00:00
updates before renaming to color-thief
This commit is contained in:
197
css/app.css
197
css/app.css
@@ -63,43 +63,214 @@ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav,
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* line 3, ../sass/app.sass */
|
||||
body {
|
||||
color: #444444;
|
||||
font-family: "lucida grande", sans-serif;
|
||||
line-height: 1.625em;
|
||||
padding: 40px;
|
||||
/* =Global */
|
||||
/* line 9, ../sass/app.sass */
|
||||
body, input, textarea {
|
||||
margin: 40px;
|
||||
color: #555555;
|
||||
font: 16px/1.625em "Varela Round", "lucida grande", tahoma, sans-serif;
|
||||
font-weight: 400;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
/* line 9, ../sass/app.sass */
|
||||
/* line 17, ../sass/app.sass */
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Terminal Dosis", "lucida grande", tahoma, sans-serif;
|
||||
line-height: 1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* line 23, ../sass/app.sass */
|
||||
h1 {
|
||||
font-size: 60px;
|
||||
}
|
||||
|
||||
/* line 26, ../sass/app.sass */
|
||||
h2 {
|
||||
font-size: 24px;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
/* line 30, ../sass/app.sass */
|
||||
h3 {
|
||||
font-size: 18px;
|
||||
letter-spacing: 0.1em;
|
||||
}
|
||||
|
||||
/* line 34, ../sass/app.sass */
|
||||
p {
|
||||
margin-bottom: 1.25em;
|
||||
}
|
||||
|
||||
/* line 38, ../sass/app.sass */
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Forms */
|
||||
/* line 44, ../sass/app.sass */
|
||||
input[type=text],
|
||||
input[type=password],
|
||||
textarea {
|
||||
background: #fafafa;
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||
-o-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #dddddd;
|
||||
color: #888888;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
-khtml-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* line 55, ../sass/app.sass */
|
||||
input[type=text]:focus,
|
||||
textarea:focus {
|
||||
color: #373737;
|
||||
}
|
||||
|
||||
/* line 59, ../sass/app.sass */
|
||||
textarea {
|
||||
padding-left: 3px;
|
||||
width: 98%;
|
||||
}
|
||||
|
||||
/* line 63, ../sass/app.sass */
|
||||
input[type=text] {
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
/* line 67, ../sass/app.sass */
|
||||
a {
|
||||
color: #555555;
|
||||
text-decoration: none;
|
||||
}
|
||||
/* line 70, ../sass/app.sass */
|
||||
a:hover {
|
||||
color: #09a1ec;
|
||||
}
|
||||
|
||||
/* line 75, ../sass/app.sass */
|
||||
.button {
|
||||
text-transform: uppercase;
|
||||
font-family: "Terminal Dosis", "lucida grande", tahoma, sans-serif;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.1em;
|
||||
olor: #555555;
|
||||
display: block;
|
||||
float: left;
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
padding: 0.6em 1.5em 0.5em 1.5em;
|
||||
border: 1px solid transparent;
|
||||
-moz-box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
|
||||
-webkit-box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
|
||||
-o-box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
|
||||
box-shadow: inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0, 0, 0, 0.25);
|
||||
background-color: #eeeeee;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
-khtml-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #d6d6d6;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
/* line 92, ../sass/app.sass */
|
||||
.button:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
/* line 94, ../sass/app.sass */
|
||||
.button:active {
|
||||
-moz-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
|
||||
-webkit-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
|
||||
-o-box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
|
||||
box-shadow: inset 0 2px 0 rgba(0, 0, 0, 0.1);
|
||||
top: 2px;
|
||||
margin-bottom: 4px;
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
/* Buttons with dark backgrounds */
|
||||
/* line 103, ../sass/app.sass */
|
||||
.button.nav,
|
||||
.button.warn,
|
||||
.button.primary,
|
||||
.nav-previous .button,
|
||||
.nav-next .button {
|
||||
color: white;
|
||||
text-shadow: rgba(0, 0, 0, 0.2) 1px 1px 0;
|
||||
}
|
||||
|
||||
/* line 112, ../sass/app.sass */
|
||||
.button.nav,
|
||||
.nav-previous .button,
|
||||
.nav-next .button {
|
||||
background-color: #09a1ec;
|
||||
border-color: #0891d4;
|
||||
}
|
||||
/* line 117, ../sass/app.sass */
|
||||
.button.nav:hover,
|
||||
.nav-previous .button:hover,
|
||||
.nav-next .button:hover {
|
||||
background-color: #33b6f7;
|
||||
}
|
||||
|
||||
/* line 123, ../sass/app.sass */
|
||||
.button.warn {
|
||||
background-color: #ee8833;
|
||||
border-color: #ec7818;
|
||||
}
|
||||
/* line 126, ../sass/app.sass */
|
||||
.button.warn:hover {
|
||||
background-color: #f1a05c;
|
||||
}
|
||||
|
||||
/* line 131, ../sass/app.sass */
|
||||
.button.primary {
|
||||
background-color: #6bb445;
|
||||
border-color: #6bb445;
|
||||
}
|
||||
/* line 134, ../sass/app.sass */
|
||||
.button.primary:hover {
|
||||
background-color: #88c568;
|
||||
}
|
||||
|
||||
/* line 143, ../sass/app.sass */
|
||||
h1 {
|
||||
font-size: 36px;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
/* line 16, ../sass/app.sass */
|
||||
/* line 150, ../sass/app.sass */
|
||||
.imageSection {
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
/* line 19, ../sass/app.sass */
|
||||
/* line 153, ../sass/app.sass */
|
||||
.imageSection img {
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
/* line 22, ../sass/app.sass */
|
||||
/* line 156, ../sass/app.sass */
|
||||
.imageSection .colors {
|
||||
width: 400px;
|
||||
float: left;
|
||||
}
|
||||
/* line 25, ../sass/app.sass */
|
||||
/* line 159, ../sass/app.sass */
|
||||
.imageSection .colors .function {
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
/* line 28, ../sass/app.sass */
|
||||
/* line 162, ../sass/app.sass */
|
||||
.imageSection .colors .function .swatch {
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
@@ -108,7 +279,7 @@ h1 {
|
||||
float: left;
|
||||
}
|
||||
|
||||
/* line 35, ../sass/app.sass */
|
||||
/* line 169, ../sass/app.sass */
|
||||
canvas {
|
||||
display: none;
|
||||
}
|
||||
|
||||
48
index.html
48
index.html
@@ -4,6 +4,8 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Varela+Round|Terminal+Dosis:400,700,600' rel='stylesheet' type='text/css'>
|
||||
|
||||
<title>Image Palette</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
@@ -26,15 +28,11 @@
|
||||
<div class="imageSection">
|
||||
<img src="img/icon1.png" />
|
||||
<div class="colors">
|
||||
<div class="function averageRGB">
|
||||
<h3>getAverageRGB()</h3>
|
||||
</div>
|
||||
|
||||
<div class="function dominantColor">
|
||||
<h3>getDominantColor()</h3>
|
||||
</div>
|
||||
<div class="function areaBasedPalette">
|
||||
<h3>createAreaBasedPalette()</h3>
|
||||
</div>
|
||||
|
||||
<div class="function medianCutPalette">
|
||||
<h3>createMedianCutPalette()</h3>
|
||||
</div>
|
||||
@@ -44,15 +42,11 @@
|
||||
<div class="imageSection">
|
||||
<img src="img/icon2.gif" />
|
||||
<div class="colors">
|
||||
<div class="function averageRGB">
|
||||
<h3>getAverageRGB()</h3>
|
||||
</div>
|
||||
|
||||
<div class="function dominantColor">
|
||||
<h3>getDominantColor()</h3>
|
||||
</div>
|
||||
<div class="function areaBasedPalette">
|
||||
<h3>createAreaBasedPalette()</h3>
|
||||
</div>
|
||||
|
||||
<div class="function medianCutPalette">
|
||||
<h3>createMedianCutPalette()</h3>
|
||||
</div>
|
||||
@@ -62,15 +56,11 @@
|
||||
<div class="imageSection">
|
||||
<img src="img/icon3.png" />
|
||||
<div class="colors">
|
||||
<div class="function averageRGB">
|
||||
<h3>getAverageRGB()</h3>
|
||||
</div>
|
||||
|
||||
<div class="function dominantColor">
|
||||
<h3>getDominantColor()</h3>
|
||||
</div>
|
||||
<div class="function areaBasedPalette">
|
||||
<h3>createAreaBasedPalette()</h3>
|
||||
</div>
|
||||
|
||||
<div class="function medianCutPalette">
|
||||
<h3>createMedianCutPalette()</h3>
|
||||
</div>
|
||||
@@ -80,15 +70,9 @@
|
||||
<div class="imageSection">
|
||||
<img src="img/4.png" />
|
||||
<div class="colors">
|
||||
<div class="function averageRGB">
|
||||
<h3>getAverageRGB()</h3>
|
||||
</div>
|
||||
<div class="function dominantColor">
|
||||
<h3>getDominantColor()</h3>
|
||||
</div>
|
||||
<div class="function areaBasedPalette">
|
||||
<h3>createAreaBasedPalette()</h3>
|
||||
</div>
|
||||
<div class="function medianCutPalette">
|
||||
<h3>createMedianCutPalette()</h3>
|
||||
</div>
|
||||
@@ -98,15 +82,9 @@
|
||||
<div class="imageSection">
|
||||
<img src="img/5.png" />
|
||||
<div class="colors">
|
||||
<div class="function averageRGB">
|
||||
<h3>getAverageRGB()</h3>
|
||||
</div>
|
||||
<div class="function dominantColor">
|
||||
<h3>getDominantColor()</h3>
|
||||
</div>
|
||||
<div class="function areaBasedPalette">
|
||||
<h3>createAreaBasedPalette()</h3>
|
||||
</div>
|
||||
<div class="function medianCutPalette">
|
||||
<h3>createMedianCutPalette()</h3>
|
||||
</div>
|
||||
@@ -116,15 +94,9 @@
|
||||
<div class="imageSection">
|
||||
<img src="img/6.jpeg" />
|
||||
<div class="colors">
|
||||
<div class="function averageRGB">
|
||||
<h3>getAverageRGB()</h3>
|
||||
</div>
|
||||
<div class="function dominantColor">
|
||||
<h3>getDominantColor()</h3>
|
||||
</div>
|
||||
<div class="function areaBasedPalette">
|
||||
<h3>createAreaBasedPalette()</h3>
|
||||
</div>
|
||||
<div class="function medianCutPalette">
|
||||
<h3>createMedianCutPalette()</h3>
|
||||
</div>
|
||||
@@ -139,7 +111,9 @@
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
|
||||
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.2.min.js"><\/script>')</script>
|
||||
|
||||
<script src="js/quantize.js"></script>
|
||||
<script src="js/libs/quantize.js"></script>
|
||||
<script src="js/libs/jquery.imagesloaded.js"></script>
|
||||
<script src="js/libs/mustache.js"></script>
|
||||
|
||||
<script src="js/canvasimage.js"></script>
|
||||
<script src="js/functions.js"></script>
|
||||
|
||||
66
js/app.js
66
js/app.js
@@ -1,46 +1,46 @@
|
||||
$(document).ready(function(){
|
||||
|
||||
var view = {
|
||||
title: "Joe",
|
||||
calc: function() {
|
||||
return 2 + 4;
|
||||
}
|
||||
}
|
||||
|
||||
var template = "{{title}} spends {{calc}}";
|
||||
|
||||
var html = Mustache.to_html(template, view);
|
||||
|
||||
$('body').prepend(html);
|
||||
|
||||
$('img').each(function(index){
|
||||
$('img').imagesLoaded(function(){
|
||||
|
||||
$('img').each(function(index){
|
||||
|
||||
var averageRGB = getAverageRGB(this);
|
||||
var dominantColor = getDominantColor(this);
|
||||
var areaPalette = createAreaBasedPalette(this, 9);
|
||||
var medianPalette = createMedianCutPalette(this, 10);
|
||||
var dominantColor = getDominantColor(this);
|
||||
var medianPalette = createPalette(this, 10);
|
||||
|
||||
var imageSection = $(this).closest('.imageSection');
|
||||
|
||||
var swatchEl = $('<div>', {
|
||||
'class': 'swatch'
|
||||
}).css('background-color','rgba('+averageRGB.r+','+averageRGB.g+ ','+averageRGB.b+', 1)');
|
||||
var imageSection = $(this).closest('.imageSection');
|
||||
|
||||
imageSection.find('.averageRGB').append(swatchEl);
|
||||
var switchEl;
|
||||
|
||||
swatchEl = $('<div>', {
|
||||
'class': 'swatch'
|
||||
}).css('background-color','rgba('+dominantColor.r+','+dominantColor.g+ ','+dominantColor.b+', 1)');
|
||||
|
||||
imageSection.find('.dominantColor').append(swatchEl);
|
||||
|
||||
|
||||
var areaBasedPalette = imageSection.find('.areaBasedPalette');
|
||||
|
||||
$.each(areaPalette, function(index, value){
|
||||
swatchEl = $('<div>', {
|
||||
'class': 'swatch'
|
||||
}).css('background-color','rgba('+value.r+','+value.g+ ','+value.b+', 1)');
|
||||
areaBasedPalette.append(swatchEl);
|
||||
});
|
||||
|
||||
var medianCutPalette = imageSection.find('.medianCutPalette');
|
||||
}).css('background-color','rgba('+dominantColor.r+','+dominantColor.g+ ','+dominantColor.b+', 1)');
|
||||
|
||||
$.each(medianPalette, function(index, value){
|
||||
swatchEl = $('<div>', {
|
||||
'class': 'swatch'
|
||||
}).css('background-color','rgba('+value[0]+','+value[1]+ ','+value[2]+', 1)');
|
||||
medianCutPalette.append(swatchEl);
|
||||
});
|
||||
imageSection.find('.dominantColor').append(swatchEl);
|
||||
|
||||
var medianCutPalette = imageSection.find('.medianCutPalette');
|
||||
|
||||
$.each(medianPalette, function(index, value){
|
||||
swatchEl = $('<div>', {
|
||||
'class': 'swatch'
|
||||
}).css('background-color','rgba('+value[0]+','+value[1]+ ','+value[2]+', 1)');
|
||||
medianCutPalette.append(swatchEl);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
196
js/color-thief.js
Normal file
196
js/color-thief.js
Normal file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Image Palette v0.1
|
||||
* by Lokesh Dhakar - http://www.lokeshdhakar.com
|
||||
*
|
||||
* Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
|
||||
*
|
||||
* The median cut palette function uses quantize.js which is written by Nick Rabinowitz
|
||||
* and licensed under the MIT license. Big props to Nick as this is where the magic happens.
|
||||
*
|
||||
* == Functions
|
||||
* getDominantColor()
|
||||
* createPalette()
|
||||
* getAverageRGB()
|
||||
* createAreaBasedPalette()
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* getDominantColor(sourceImage)
|
||||
* returns {r: num, g: num, b: num}
|
||||
*
|
||||
* Use the median cut algorithm provided by quantize.js to cluster similar
|
||||
* colors and return the base color from the largest cluster.
|
||||
*/
|
||||
function getDominantColor(sourceImage){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Store the RGB values in an array format suitable for quantize function
|
||||
var pixelArray = [];
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
// If pixel is mostly opaque
|
||||
if(pixels[i*4+3] >= 125){
|
||||
pixelArray.push( [pixels[i*4], pixels[i*4+1], pixels[i*4+2]]);
|
||||
}
|
||||
};
|
||||
|
||||
// Send array to quantize function which clusters values
|
||||
// using median cut algorithm
|
||||
var cmap = MMCQ.quantize(pixelArray, 5);
|
||||
var newPalette = cmap.palette();
|
||||
|
||||
return {r: newPalette[0][0], g: newPalette[0][1], b: newPalette[0][2]};
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* createPalette(sourceImage)
|
||||
* returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...]
|
||||
*
|
||||
* Use the median cut algorithm provided by quantize.js to cluster similar
|
||||
* colors.
|
||||
*
|
||||
* BUGGY: Function does not always return the requested amount of colors. It can be +/- 2.
|
||||
*/
|
||||
function createPalette(sourceImage, colorCount){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Store the RGB values in an array format suitable for quantize function
|
||||
var pixelArray = [];
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
// If pixel is mostly opaque
|
||||
if(pixels[i*4+3] >= 125){
|
||||
pixelArray.push( [pixels[i*4], pixels[i*4+1], pixels[i*4+2]]);
|
||||
}
|
||||
};
|
||||
|
||||
// Send array to quantize function which clusters values
|
||||
// using median cut algorithm
|
||||
var cmap = MMCQ.quantize(pixelArray, colorCount);
|
||||
var newPalette = cmap.palette();
|
||||
|
||||
return newPalette;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* getAverageRGB(sourceImage)
|
||||
* returns {r: num, g: num, b: num}
|
||||
*
|
||||
* Add up all pixels RGB values and return average.
|
||||
* Tends to return muddy gray/brown color. Most likely, you'll be better
|
||||
* off using getDominantColor() instead.
|
||||
*/
|
||||
function getAverageRGB(sourceImage) {
|
||||
// Config
|
||||
var sampleSize = 10;
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Reset vars
|
||||
var i = 0,
|
||||
count = 0,
|
||||
rgb = {r:0,g:0,b:0};
|
||||
|
||||
// Loop through every # pixels. (# is set in Config above via the blockSize var)
|
||||
// Add all the red values together, repeat for blue and green.
|
||||
// Last step, divide by the number of pixels checked to get average.
|
||||
while ( (i += sampleSize * 4) < pixelCount ) {
|
||||
// if pixel is mostly opaque
|
||||
if(pixels[i+3] > 125){
|
||||
++count;
|
||||
rgb.r += pixels[i];
|
||||
rgb.g += pixels[i+1];
|
||||
rgb.b += pixels[i+2];
|
||||
}
|
||||
}
|
||||
|
||||
rgb.r = Math.floor(rgb.r/count);
|
||||
rgb.g = Math.floor(rgb.g/count);
|
||||
rgb.b = Math.floor(rgb.b/count);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* createAreaBasedPalette(sourceImage, colorCount)
|
||||
* returns array[ {r: num, g: num, b: num}, {r: num, g: num, b: num}, ...]
|
||||
*
|
||||
* Break the image into sections. Loops through pixel RGBS in the section and average color.
|
||||
* Tends to return muddy gray/brown color. You're most likely better off using createPalette().
|
||||
*
|
||||
* BUGGY: Function does not always return the requested amount of colors. It can be +/- 2.
|
||||
*
|
||||
*/
|
||||
function createAreaBasedPalette(sourceImage, colorCount){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
|
||||
// How big a pixel area does each palette color get
|
||||
var rowCount = colCount = Math.round(Math.sqrt(colorCount)),
|
||||
colWidth = Math.round(image.width / colCount),
|
||||
rowHeight = Math.round(image.height / rowCount);
|
||||
|
||||
var count = offset = rowOffset = vertOffset = horizOffset = 0,
|
||||
rgb = {r:0,g:0,b:0};
|
||||
|
||||
// Loop through pixels section by section.
|
||||
// At the end of each section, push the average rgb color to palette array.
|
||||
for(var i=0; i<rowCount; i++){
|
||||
vertOffset = i * rowHeight * image.width * 4;
|
||||
|
||||
for(var j=0; j<colCount; j++){
|
||||
horizOffset = j * colWidth * 4;
|
||||
|
||||
for( var k = 0; k < rowHeight; k++){
|
||||
rowOffset = k * image.width * 4;
|
||||
|
||||
for( var l = 0; l < colWidth; l++){
|
||||
offset = vertOffset + horizOffset + rowOffset + (l * 4);
|
||||
rgb.r += pixels[offset];
|
||||
rgb.g += pixels[offset+1];
|
||||
rgb.b += pixels[offset+2];
|
||||
count++;
|
||||
}
|
||||
|
||||
}
|
||||
rgb.r = Math.floor(rgb.r/count);
|
||||
rgb.g = Math.floor(rgb.g/count);
|
||||
rgb.b = Math.floor(rgb.b/count);
|
||||
palette.push(rgb);
|
||||
|
||||
// reset before next section
|
||||
rgb = {r:0,g:0,b:0};
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
153
js/functions.js
153
js/functions.js
@@ -1,153 +0,0 @@
|
||||
|
||||
function getAverageRGB(sourceImage) {
|
||||
// Config
|
||||
var sampleSize = 10;
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
// Reset vars
|
||||
var i = 0,
|
||||
count = 0,
|
||||
rgb = {r:0,g:0,b:0};
|
||||
|
||||
// Loop through every # pixels. (# is set in Config above via the blockSize var)
|
||||
// Add all the red values together, repeat for blue and green.
|
||||
// Last step, divide by the number of pixels checked to get average.
|
||||
while ( (i += sampleSize * 4) < pixelCount ) {
|
||||
// if pixel is mostly opaque
|
||||
if(pixels[i+3] > 125){
|
||||
++count;
|
||||
rgb.r += pixels[i];
|
||||
rgb.g += pixels[i+1];
|
||||
rgb.b += pixels[i+2];
|
||||
}
|
||||
}
|
||||
|
||||
rgb.r = Math.floor(rgb.r/count);
|
||||
rgb.g = Math.floor(rgb.g/count);
|
||||
rgb.b = Math.floor(rgb.b/count);
|
||||
|
||||
return rgb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getDominantColor(sourceImage){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
var pixelArray = [];
|
||||
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
// If pixel is mostly opaque
|
||||
if(pixels[i*4+3] >= 125){
|
||||
pixelArray.push( [pixels[i*4], pixels[i*4+1], pixels[i*4+2]]);
|
||||
}
|
||||
};
|
||||
|
||||
var cmap = MMCQ.quantize(pixelArray, 5);
|
||||
var newPalette = cmap.palette();
|
||||
|
||||
return {r: newPalette[0][0], g: newPalette[0][1], b: newPalette[0][2]};
|
||||
}
|
||||
|
||||
|
||||
|
||||
function createAreaBasedPalette(sourceImage, colorCount){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
|
||||
// How big a pixel area does each palette color get
|
||||
var rowCount = colCount = Math.round(Math.sqrt(colorCount)),
|
||||
colWidth = Math.round(image.width / colCount),
|
||||
rowHeight = Math.round(image.height / rowCount);
|
||||
|
||||
var count = offset = rowOffset = vertOffset = horizOffset = 0,
|
||||
rgb = {r:0,g:0,b:0};
|
||||
|
||||
for(var i=0; i<rowCount; i++){
|
||||
vertOffset = i * rowHeight * image.width * 4;
|
||||
|
||||
for(var j=0; j<colCount; j++){
|
||||
horizOffset = j * colWidth * 4;
|
||||
|
||||
for( var k = 0; k < rowHeight; k++){
|
||||
rowOffset = k * image.width * 4;
|
||||
|
||||
for( var l = 0; l < colWidth; l++){
|
||||
offset = vertOffset + horizOffset + rowOffset + (l * 4);
|
||||
rgb.r += pixels[offset];
|
||||
rgb.g += pixels[offset+1];
|
||||
rgb.b += pixels[offset+2];
|
||||
count++;
|
||||
}
|
||||
|
||||
}
|
||||
rgb.r = Math.floor(rgb.r/count);
|
||||
rgb.g = Math.floor(rgb.g/count);
|
||||
rgb.b = Math.floor(rgb.b/count);
|
||||
palette.push(rgb);
|
||||
|
||||
// reset before next section
|
||||
rgb = {r:0,g:0,b:0};
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return palette;
|
||||
}
|
||||
|
||||
|
||||
function createMedianCutPalette(sourceImage, colorCount){
|
||||
|
||||
var palette = [];
|
||||
|
||||
// Create custom CanvasImage object
|
||||
var image = new CanvasImage(sourceImage),
|
||||
imageData = image.getImageData(),
|
||||
pixels = imageData.data,
|
||||
pixelCount = image.getPixelCount();
|
||||
|
||||
var pixelArray = [];
|
||||
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
// If pixel is mostly opaque
|
||||
if(pixels[i*4+3] >= 125){
|
||||
pixelArray.push( [pixels[i*4], pixels[i*4+1], pixels[i*4+2]]);
|
||||
}
|
||||
};
|
||||
|
||||
var cmap = MMCQ.quantize(pixelArray, colorCount);
|
||||
var newPalette = cmap.palette();
|
||||
|
||||
return newPalette;
|
||||
}
|
||||
|
||||
/*
|
||||
for (var i = 0; i < pixelCount; i++) {
|
||||
pixels[i*4] = pixels[i*4]; // Red
|
||||
pixels[i*4+1] = pixels[i*4+1]; // Green
|
||||
pixels[i*4+2] = pixels[i*4+2]; // Blue
|
||||
};
|
||||
|
||||
image.clear();
|
||||
imageData.data = pixels;
|
||||
image.update(imageData);
|
||||
*/
|
||||
54
js/libs/jquery.imagesloaded.js
Normal file
54
js/libs/jquery.imagesloaded.js
Normal file
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* jQuery imagesLoaded plugin v1.0.4
|
||||
* http://github.com/desandro/imagesloaded
|
||||
*
|
||||
* MIT License. by Paul Irish et al.
|
||||
*/
|
||||
|
||||
(function($, undefined) {
|
||||
|
||||
// $('#my-container').imagesLoaded(myFunction)
|
||||
// or
|
||||
// $('img').imagesLoaded(myFunction)
|
||||
|
||||
// execute a callback when all images have loaded.
|
||||
// needed because .load() doesn't work on cached images
|
||||
|
||||
// callback function gets image collection as argument
|
||||
// `this` is the container
|
||||
|
||||
$.fn.imagesLoaded = function( callback ) {
|
||||
var $this = this,
|
||||
$images = $this.find('img').add( $this.filter('img') ),
|
||||
len = $images.length,
|
||||
blank = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
|
||||
|
||||
function triggerCallback() {
|
||||
callback.call( $this, $images );
|
||||
}
|
||||
|
||||
function imgLoaded( event ) {
|
||||
if ( --len <= 0 && event.target.src !== blank ){
|
||||
setTimeout( triggerCallback );
|
||||
$images.unbind( 'load error', imgLoaded );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !len ) {
|
||||
triggerCallback();
|
||||
}
|
||||
|
||||
$images.bind( 'load error', imgLoaded ).each( function() {
|
||||
// cached images don't fire load sometimes, so we reset src.
|
||||
if (this.complete || this.complete === undefined){
|
||||
var src = this.src;
|
||||
// webkit hack from http://groups.google.com/group/jquery-dev/browse_thread/thread/eee6ab7b2da50e1f
|
||||
// data uri bypasses webkit log warning (thx doug jones)
|
||||
this.src = blank;
|
||||
this.src = src;
|
||||
}
|
||||
});
|
||||
|
||||
return $this;
|
||||
};
|
||||
})(jQuery);
|
||||
419
js/libs/mustache.js
Normal file
419
js/libs/mustache.js
Normal file
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
mustache.js — Logic-less templates in JavaScript
|
||||
|
||||
See http://mustache.github.com/ for more info.
|
||||
*/
|
||||
|
||||
var Mustache = function() {
|
||||
var regexCache = {};
|
||||
var Renderer = function() {};
|
||||
|
||||
Renderer.prototype = {
|
||||
otag: "{{",
|
||||
ctag: "}}",
|
||||
pragmas: {},
|
||||
buffer: [],
|
||||
pragmas_implemented: {
|
||||
"IMPLICIT-ITERATOR": true
|
||||
},
|
||||
context: {},
|
||||
|
||||
render: function(template, context, partials, in_recursion) {
|
||||
// reset buffer & set context
|
||||
if(!in_recursion) {
|
||||
this.context = context;
|
||||
this.buffer = []; // TODO: make this non-lazy
|
||||
}
|
||||
|
||||
// fail fast
|
||||
if(!this.includes("", template)) {
|
||||
if(in_recursion) {
|
||||
return template;
|
||||
} else {
|
||||
this.send(template);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// get the pragmas together
|
||||
template = this.render_pragmas(template);
|
||||
|
||||
// render the template
|
||||
var html = this.render_section(template, context, partials);
|
||||
|
||||
// render_section did not find any sections, we still need to render the tags
|
||||
if (html === false) {
|
||||
html = this.render_tags(template, context, partials, in_recursion);
|
||||
}
|
||||
|
||||
if (in_recursion) {
|
||||
return html;
|
||||
} else {
|
||||
this.sendLines(html);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
Sends parsed lines
|
||||
*/
|
||||
send: function(line) {
|
||||
if(line !== "") {
|
||||
this.buffer.push(line);
|
||||
}
|
||||
},
|
||||
|
||||
sendLines: function(text) {
|
||||
if (text) {
|
||||
var lines = text.split("\n");
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
this.send(lines[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
Looks for %PRAGMAS
|
||||
*/
|
||||
render_pragmas: function(template) {
|
||||
// no pragmas
|
||||
if(!this.includes("%", template)) {
|
||||
return template;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
var regex = this.getCachedRegex("render_pragmas", function(otag, ctag) {
|
||||
return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
|
||||
});
|
||||
|
||||
return template.replace(regex, function(match, pragma, options) {
|
||||
if(!that.pragmas_implemented[pragma]) {
|
||||
throw({message:
|
||||
"This implementation of mustache doesn't understand the '" +
|
||||
pragma + "' pragma"});
|
||||
}
|
||||
that.pragmas[pragma] = {};
|
||||
if(options) {
|
||||
var opts = options.split("=");
|
||||
that.pragmas[pragma][opts[0]] = opts[1];
|
||||
}
|
||||
return "";
|
||||
// ignore unknown pragmas silently
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
Tries to find a partial in the curent scope and render it
|
||||
*/
|
||||
render_partial: function(name, context, partials) {
|
||||
name = this.trim(name);
|
||||
if(!partials || partials[name] === undefined) {
|
||||
throw({message: "unknown_partial '" + name + "'"});
|
||||
}
|
||||
if(typeof(context[name]) != "object") {
|
||||
return this.render(partials[name], context, partials, true);
|
||||
}
|
||||
return this.render(partials[name], context[name], partials, true);
|
||||
},
|
||||
|
||||
/*
|
||||
Renders inverted (^) and normal (#) sections
|
||||
*/
|
||||
render_section: function(template, context, partials) {
|
||||
if(!this.includes("#", template) && !this.includes("^", template)) {
|
||||
// did not render anything, there were no sections
|
||||
return false;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
|
||||
var regex = this.getCachedRegex("render_section", function(otag, ctag) {
|
||||
// This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
|
||||
return new RegExp(
|
||||
"^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1)
|
||||
|
||||
otag + // {{
|
||||
"(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3)
|
||||
ctag + // }}
|
||||
|
||||
"\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped
|
||||
|
||||
otag + // {{
|
||||
"\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag).
|
||||
ctag + // }}
|
||||
|
||||
"\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped.
|
||||
|
||||
"g");
|
||||
});
|
||||
|
||||
|
||||
// for each {{#foo}}{{/foo}} section do...
|
||||
return template.replace(regex, function(match, before, type, name, content, after) {
|
||||
// before contains only tags, no sections
|
||||
var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
|
||||
|
||||
// after may contain both sections and tags, so use full rendering function
|
||||
renderedAfter = after ? that.render(after, context, partials, true) : "",
|
||||
|
||||
// will be computed below
|
||||
renderedContent,
|
||||
|
||||
value = that.find(name, context);
|
||||
|
||||
if (type === "^") { // inverted section
|
||||
if (!value || that.is_array(value) && value.length === 0) {
|
||||
// false or empty list, render it
|
||||
renderedContent = that.render(content, context, partials, true);
|
||||
} else {
|
||||
renderedContent = "";
|
||||
}
|
||||
} else if (type === "#") { // normal section
|
||||
if (that.is_array(value)) { // Enumerable, Let's loop!
|
||||
renderedContent = that.map(value, function(row) {
|
||||
return that.render(content, that.create_context(row), partials, true);
|
||||
}).join("");
|
||||
} else if (that.is_object(value)) { // Object, Use it as subcontext!
|
||||
renderedContent = that.render(content, that.create_context(value),
|
||||
partials, true);
|
||||
} else if (typeof value === "function") {
|
||||
// higher order section
|
||||
renderedContent = value.call(context, content, function(text) {
|
||||
return that.render(text, context, partials, true);
|
||||
});
|
||||
} else if (value) { // boolean section
|
||||
renderedContent = that.render(content, context, partials, true);
|
||||
} else {
|
||||
renderedContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
return renderedBefore + renderedContent + renderedAfter;
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
Replace {{foo}} and friends with values from our view
|
||||
*/
|
||||
render_tags: function(template, context, partials, in_recursion) {
|
||||
// tit for tat
|
||||
var that = this;
|
||||
|
||||
|
||||
|
||||
var new_regex = function() {
|
||||
return that.getCachedRegex("render_tags", function(otag, ctag) {
|
||||
return new RegExp(otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" + ctag + "+", "g");
|
||||
});
|
||||
};
|
||||
|
||||
var regex = new_regex();
|
||||
var tag_replace_callback = function(match, operator, name) {
|
||||
switch(operator) {
|
||||
case "!": // ignore comments
|
||||
return "";
|
||||
case "=": // set new delimiters, rebuild the replace regexp
|
||||
that.set_delimiters(name);
|
||||
regex = new_regex();
|
||||
return "";
|
||||
case ">": // render partial
|
||||
return that.render_partial(name, context, partials);
|
||||
case "{": // the triple mustache is unescaped
|
||||
return that.find(name, context);
|
||||
default: // escape the value
|
||||
return that.escape(that.find(name, context));
|
||||
}
|
||||
};
|
||||
var lines = template.split("\n");
|
||||
for(var i = 0; i < lines.length; i++) {
|
||||
lines[i] = lines[i].replace(regex, tag_replace_callback, this);
|
||||
if(!in_recursion) {
|
||||
this.send(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if(in_recursion) {
|
||||
return lines.join("\n");
|
||||
}
|
||||
},
|
||||
|
||||
set_delimiters: function(delimiters) {
|
||||
var dels = delimiters.split(" ");
|
||||
this.otag = this.escape_regex(dels[0]);
|
||||
this.ctag = this.escape_regex(dels[1]);
|
||||
},
|
||||
|
||||
escape_regex: function(text) {
|
||||
// thank you Simon Willison
|
||||
if(!arguments.callee.sRE) {
|
||||
var specials = [
|
||||
'/', '.', '*', '+', '?', '|',
|
||||
'(', ')', '[', ']', '{', '}', '\\'
|
||||
];
|
||||
arguments.callee.sRE = new RegExp(
|
||||
'(\\' + specials.join('|\\') + ')', 'g'
|
||||
);
|
||||
}
|
||||
return text.replace(arguments.callee.sRE, '\\$1');
|
||||
},
|
||||
|
||||
/*
|
||||
find `name` in current `context`. That is find me a value
|
||||
from the view object
|
||||
*/
|
||||
find: function(name, context) {
|
||||
name = this.trim(name);
|
||||
|
||||
// Checks whether a value is thruthy or false or 0
|
||||
function is_kinda_truthy(bool) {
|
||||
return bool === false || bool === 0 || bool;
|
||||
}
|
||||
|
||||
var value;
|
||||
|
||||
// check for dot notation eg. foo.bar
|
||||
if(name.match(/([a-z_]+)\./ig)){
|
||||
value = is_kinda_truthy(this.walk_context(name, context));
|
||||
}
|
||||
else{
|
||||
if(is_kinda_truthy(context[name])) {
|
||||
value = context[name];
|
||||
} else if(is_kinda_truthy(this.context[name])) {
|
||||
value = this.context[name];
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof value === "function") {
|
||||
return value.apply(context);
|
||||
}
|
||||
if(value !== undefined) {
|
||||
return value;
|
||||
}
|
||||
// silently ignore unkown variables
|
||||
return "";
|
||||
},
|
||||
|
||||
walk_context: function(name, context){
|
||||
var path = name.split('.');
|
||||
// if the var doesn't exist in current context, check the top level context
|
||||
var value_context = (context[path[0]] != undefined) ? context : this.context;
|
||||
var value = value_context[path.shift()];
|
||||
while(value != undefined && path.length > 0){
|
||||
value_context = value;
|
||||
value = value[path.shift()];
|
||||
}
|
||||
// if the value is a function, call it, binding the correct context
|
||||
if(typeof value === "function") {
|
||||
return value.apply(value_context);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
// Utility methods
|
||||
|
||||
/* includes tag */
|
||||
includes: function(needle, haystack) {
|
||||
return haystack.indexOf(this.otag + needle) != -1;
|
||||
},
|
||||
|
||||
/*
|
||||
Does away with nasty characters
|
||||
*/
|
||||
escape: function(s) {
|
||||
s = String(s === null ? "" : s);
|
||||
return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
|
||||
switch(s) {
|
||||
case "&": return "&";
|
||||
case '"': return '"';
|
||||
case "'": return ''';
|
||||
case "<": return "<";
|
||||
case ">": return ">";
|
||||
default: return s;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// by @langalex, support for arrays of strings
|
||||
create_context: function(_context) {
|
||||
if(this.is_object(_context)) {
|
||||
return _context;
|
||||
} else {
|
||||
var iterator = ".";
|
||||
if(this.pragmas["IMPLICIT-ITERATOR"]) {
|
||||
iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
|
||||
}
|
||||
var ctx = {};
|
||||
ctx[iterator] = _context;
|
||||
return ctx;
|
||||
}
|
||||
},
|
||||
|
||||
is_object: function(a) {
|
||||
return a && typeof a == "object";
|
||||
},
|
||||
|
||||
is_array: function(a) {
|
||||
return Object.prototype.toString.call(a) === '[object Array]';
|
||||
},
|
||||
|
||||
/*
|
||||
Gets rid of leading and trailing whitespace
|
||||
*/
|
||||
trim: function(s) {
|
||||
return s.replace(/^\s*|\s*$/g, "");
|
||||
},
|
||||
|
||||
/*
|
||||
Why, why, why? Because IE. Cry, cry cry.
|
||||
*/
|
||||
map: function(array, fn) {
|
||||
if (typeof array.map == "function") {
|
||||
return array.map(fn);
|
||||
} else {
|
||||
var r = [];
|
||||
var l = array.length;
|
||||
for(var i = 0; i < l; i++) {
|
||||
r.push(fn(array[i]));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
},
|
||||
|
||||
getCachedRegex: function(name, generator) {
|
||||
var byOtag = regexCache[this.otag];
|
||||
if (!byOtag) {
|
||||
byOtag = regexCache[this.otag] = {};
|
||||
}
|
||||
|
||||
var byCtag = byOtag[this.ctag];
|
||||
if (!byCtag) {
|
||||
byCtag = byOtag[this.ctag] = {};
|
||||
}
|
||||
|
||||
var regex = byCtag[name];
|
||||
if (!regex) {
|
||||
regex = byCtag[name] = generator(this.otag, this.ctag);
|
||||
}
|
||||
|
||||
return regex;
|
||||
}
|
||||
};
|
||||
|
||||
return({
|
||||
name: "mustache.js",
|
||||
version: "0.4.0-dev",
|
||||
|
||||
/*
|
||||
Turns a template and view into HTML
|
||||
*/
|
||||
to_html: function(template, view, partials, send_fun) {
|
||||
var renderer = new Renderer();
|
||||
if(send_fun) {
|
||||
renderer.send = send_fun;
|
||||
}
|
||||
renderer.render(template, view || {}, partials);
|
||||
if(!send_fun) {
|
||||
return renderer.buffer.join("\n");
|
||||
}
|
||||
}
|
||||
});
|
||||
}();
|
||||
@@ -1,6 +1,7 @@
|
||||
$color: #555
|
||||
$headingColor: #222
|
||||
$altColor: scale-color($color, $lightness: 50%)
|
||||
$lightGray: #eee
|
||||
$blue: #09a1ec
|
||||
$orange: #e83
|
||||
$green: #6bb445
|
||||
|
||||
146
sass/app.sass
146
sass/app.sass
@@ -1,11 +1,145 @@
|
||||
@import "base"
|
||||
|
||||
body
|
||||
color: #444
|
||||
font-family: 'lucida grande', sans-serif
|
||||
line-height: 1.625em
|
||||
padding: 40px
|
||||
|
||||
|
||||
|
||||
|
||||
/* =Global */
|
||||
|
||||
|
||||
body, input, textarea
|
||||
margin: 40px
|
||||
color: $color
|
||||
font: 16px/1.625em 'Varela Round',"lucida grande",tahoma,sans-serif
|
||||
font-weight: 400
|
||||
-webkit-font-smoothing: antialiased
|
||||
|
||||
|
||||
h1,h2,h3,h4,h5,h6
|
||||
font-family: 'Terminal Dosis', 'lucida grande', tahoma, sans-serif
|
||||
line-height: 1em
|
||||
font-weight: 600
|
||||
|
||||
|
||||
h1
|
||||
font-size: 60px
|
||||
|
||||
h2
|
||||
font-size: 24px
|
||||
line-height: 1.2em
|
||||
|
||||
h3
|
||||
font-size: 18px
|
||||
letter-spacing: 0.1em
|
||||
|
||||
p
|
||||
margin-bottom: 1.25em
|
||||
|
||||
|
||||
strong
|
||||
font-weight: bold
|
||||
|
||||
|
||||
|
||||
/* Forms */
|
||||
input[type=text],
|
||||
input[type=password],
|
||||
textarea
|
||||
background: #fafafa
|
||||
+box-shadow(inset 0 1px 1px rgba(0,0,0,0.1))
|
||||
border: 1px solid #ddd
|
||||
color: #888
|
||||
+border-radius($radius)
|
||||
|
||||
|
||||
|
||||
input[type=text]:focus,
|
||||
textarea:focus
|
||||
color: #373737
|
||||
|
||||
textarea
|
||||
padding-left: 3px
|
||||
width: 98%
|
||||
|
||||
input[type=text]
|
||||
padding: 3px
|
||||
|
||||
/* Links */
|
||||
a
|
||||
color: $color
|
||||
text-decoration: none
|
||||
&:hover
|
||||
color: $blue
|
||||
|
||||
|
||||
|
||||
.button
|
||||
text-transform: uppercase
|
||||
font-family: 'Terminal Dosis', 'lucida grande', tahoma, sans-serif
|
||||
font-weight: 700
|
||||
letter-spacing: 0.1em
|
||||
olor: #555
|
||||
display: block
|
||||
float: left
|
||||
position: relative
|
||||
line-height: 1
|
||||
padding: .6em 1.5em .5em 1.5em
|
||||
border: 1px solid transparent
|
||||
+box-shadow( inset 0 2px 0 rgba(255, 255, 255, 0.1), 0 2px 5px 0 rgba(0,0,0, .25))
|
||||
background-color: $lightGray
|
||||
+border-radius($radius)
|
||||
border: 1px solid scale-color($lightGray, $lightness: -10%)
|
||||
margin-bottom: 6px
|
||||
&:hover
|
||||
background-color: scale-color($lightGray, $lightness: 20%)
|
||||
&:active
|
||||
+box-shadow( inset 0 2px 0 rgba(0, 0, 0, 0.1))
|
||||
top: 2px
|
||||
margin-bottom: 4px
|
||||
border-bottom-width: 0
|
||||
|
||||
|
||||
|
||||
/* Buttons with dark backgrounds */
|
||||
.button.nav,
|
||||
.button.warn,
|
||||
.button.primary,
|
||||
.nav-previous .button,
|
||||
.nav-next .button
|
||||
color: #fff
|
||||
@include text-shadow(rgba(0,0,0, 0.2) 1px 1px 0)
|
||||
|
||||
|
||||
.button.nav,
|
||||
.nav-previous .button,
|
||||
.nav-next .button
|
||||
background-color: $blue
|
||||
border-color: scale-color($blue, $lightness: -10%)
|
||||
&:hover
|
||||
background-color: scale-color($blue, $lightness: 20%)
|
||||
|
||||
|
||||
|
||||
|
||||
.button.warn
|
||||
background-color: $orange
|
||||
border-color: scale-color($orange, $lightness: -10%)
|
||||
&:hover
|
||||
background-color: scale-color($orange, $lightness: 20%)
|
||||
|
||||
|
||||
|
||||
.button.primary
|
||||
background-color: $green
|
||||
border-color: $green
|
||||
&:hover
|
||||
background-color: scale-color($green, $lightness: 20%)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
h1
|
||||
font-size: 36px
|
||||
margin-bottom: .5em
|
||||
|
||||
Reference in New Issue
Block a user