Skip to content

Instantly share code, notes, and snippets.

@yoksel
Created February 17, 2014 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yoksel/9045639 to your computer and use it in GitHub Desktop.
Save yoksel/9045639 to your computer and use it in GitHub Desktop.
A Pen by yoksel.
<div class="l-wrapper" data-size="300" data-oneside="9">
<div class="b-box b-box--paint"><span class="dot"></div>
<div class="b-box b-box--result"><span class="dot is-running"></span></div>
<div class="b-palette"></div>
<div class="b-steps"></div>
<div class="b-codes">
<span class="b-codes__toggle" data-init = "Get codes" data-opened = "Close">Get codes</span>
<div class="b-codes__wrapper">
<h3 class="b-codes--title">CSS</h3>
<textarea class="b-codes__textarea textarea--css"></textarea>
<h3 class="b-codes--title">HTML</h3>
<textarea class="b-codes__textarea textarea--html"></textarea>
</div>
</div>
</div>
console.log( "Hello!" );
var line = "------------------------";
function Pixelator() {
var doc = document;
var colors = ["#3FB8AF","#7FC7AF","#DAD8A7","#FF9E9D","#FF3D7F"];
var currentColorNum = 0;
var currentColor = colors[currentColorNum];
var currentColorClass = "color--" + currentColorNum;
var transparent = "rgba(255,255,255,0)";
var wrapper = doc.querySelector(".l-wrapper");
var paintBox = doc.querySelector(".b-box--paint");
var resultBox = doc.querySelector(".b-box--result");
var palette = doc.querySelector(".b-palette");
var steps = doc.querySelector(".b-steps");
var codes = doc.querySelector(".b-codes");
var codesToggle = doc.querySelector(".b-codes__toggle");
var codesCss = doc.querySelector(".textarea--css");
var codesHtml = doc.querySelector(".textarea--html");
var is_opened = false;
var oneSide = 7;// dottes in line
var dotSize = 30;// pixels
var size = oneSide * dotSize;
var padding = 20;// pixels. Don't change it
var border = 1;// pixels
var configElemParams = {
".l-wrapper": {
"width": size * 2 + padding * 3 + border*6,
"height": size + padding * 2 + border*4,
"padding": padding
},
".b-box": {
"width": size + border*2,
"height": size + border*2
},
".cell__lbl": {
"width": dotSize,
"height": dotSize
},
".dot": {
"width": dotSize,
"height": dotSize,
"margin": "-" + dotSize + " 0 0 -" + dotSize
},
".b-box--paint": {
"background-size": dotSize + " " + dotSize
}
};
var stepsMax = 5;
var stylesShadowsClass = "stylesBox";
var stylesColorsClass = "colorsBox";
var stylesConfigClass = "configBox";
var cellClass = "cell";
var cellInpClass = cellClass + "__inp";
var cellLblClass = cellClass + "__lbl";
var colorClass = "color";
var colorInpClass = colorClass + "__inp";
var colorLblClass = colorClass + "__lbl";
var stepClass = "step";
var stepInpClass = stepClass + "__inp";
var stepLblClass = stepClass + "__lbl";
var currentStepNum = 0;
var colorStyleTempl = "." + colorClass + "--{i} {background: {color};}\n";
var classIsRunning = "is-running";
var frames = {};
var currentFrame = 0;
this.init = function(){
this.cellTempl = createTemplate ( cellClass, "checkbox", "data-hpos=\"{hpos}\" data-vpos=\"{vpos}\" ", "" );
this.colorTempl = createTemplate ( colorClass, "radio", "data-color=\"{color}\" ", "" );
this.stepTempl = createTemplate ( stepClass, "radio", "", "{i+1}" );
this.stylesConfig = addStylesBox(stylesConfigClass);
this.stylesColors = addStylesBox(stylesColorsClass);
this.stylesShadows = addStylesBox(stylesShadowsClass);
this.addConfig();
this.createInputsSet();
this.createFramesSet();
this.createPalette();
this.createSteps();
}
// FUNCTIONS
// -----------------------------------------
function findKeyFrames(name){
var sheets = doc.styleSheets[1].cssRules;
var keyFrames;
for (var i = 0; i < doc.styleSheets.length; i++) {
var stylesList = doc.styleSheets[i].cssRules;
for (var k = 0; k < stylesList.length; k++) {
if ( stylesList[k].name == name ){
keyFrames = stylesList[k];
}
};
};
return keyFrames;
}
// -----------------------------------------
this.addConfig = function(){
var styles = "";
out("make config");
//out( configElemParams );
for ( var elem in configElemParams ){
var className = elem;
var elemStyles = "";
var params = configElemParams[elem];
for (var item in params){
var value = addUnits( params[item] );
elemStyles += item + ": " + value + ";\n";
}
styles += className + " {\n" + elemStyles + "}\n";
}
this.stylesConfig.innerHTML = styles;
}
// -----------------------------------------
function addStylesBox(elemClass){
var elem = doc.createElement( "style" );
elem.classList.add( elemClass );
var head = doc.querySelector( "head" );
head.appendChild( elem );
return elem;
}
// -----------------------------------------
function createTemplate ( itemType, inputType, data_attr, lblContent ){
var itemInpClass = itemType + "__inp";
var itemLblClass = itemType + "__lbl";
var replacements = {
"{inputType}": inputType,
"{itemType}": itemType,
"{itemClass}": itemType,
"{itemLblClass}": itemLblClass,
"{itemInpClass}": itemInpClass,
"{lblContent}": lblContent
};
var itemInputTempl = "<input type='{inputType}' id='{itemType}-{i}' class='" + itemInpClass +"' name='{itemType}' data-{itemType}-num='{i}' " + data_attr + ">";//
var itemLabelTempl = "<label for='{itemType}-{i}' class='{itemLblClass} {itemType}--{i}'>{lblContent}</label>";
var itemTempl = "<span class='{itemType}'>" + itemInputTempl + itemLabelTempl +"</span>";
var result = fillTemplate( itemTempl, replacements );
return result;
}
// -----------------------------------------
this.addEvents = function ( itemsClass, func ){
var items = doc.querySelectorAll("." + itemsClass);
var parent = this;
for (var i = 0; i < items.length; i++) {
items[i].onclick = function() {
func.call(parent, this);
}
}
}
// -----------------------------------------
this.createInputsSet = function() {
for (var i = 0; i < oneSide * oneSide; i++) {
var hpos = i % oneSide + 1;
var vpos = Math.floor(i / oneSide) + 1;
var replacements = {
"{i}": i,
"{hpos}": hpos,
"{vpos}": vpos
};
var checkBox = fillTemplate( this.cellTempl, replacements );
paintBox.innerHTML += checkBox;
}
this.addEvents( cellInpClass, this.onClickCell);
}
// -----------------------------------------
this.createFramesSet = function() {
for (var k = 0; k < stepsMax; k++) {
frames[k] = { active: 0 };
for (var i = 0; i < oneSide * oneSide; i++) {
var hpos = i % oneSide + 1;
var vpos = Math.floor(i / oneSide) + 1;
frames[k]["cell-" + i] = {
"hpos": hpos,
"vpos": vpos,
"color": transparent
};
}
};
}
// -----------------------------------------
this.onClickCell = function( elem ) {
if( elem !== undefined ){
var cellLbl = elem.nextSibling;
this.updateFrames( elem );
}
}
// -----------------------------------------
this.toggleColorClass = function( elem ) {
var findClass = colorClass + "--";
var classes = elem.classList;
for (var i = 0; i < classes.length; i++) {
if(classes[i].indexOf(findClass) >= 0 ){
classes.remove(classes[i]);
return;
}
}
classes.add(findClass + currentColorNum);
}
// -----------------------------------------
this.updateFrames = function( elem ) {
out( "currentColor: " + currentColor);
out( frames[currentFrame] );
//if ( frames[currentFrame] == undefined ){
//frames[currentFrame] = {};
//}
var place = frames[currentFrame];
var color = transparent;
if ( elem.checked ){
color = currentColor;
place.active++;
}
else {
place.active--;
}
place[elem.id].color = color;
this.paintShadow();
}
// -----------------------------------------
this.paintShadow = function(){
var styles = "";
var animName = "shadows";
var animFrames = {};
var framesLength = objLength(frames);
var perc = (100 / framesLength).toFixed(3);
var dottes = frames[currentFrame];
var shadows = this.createShadow( dottes );
styles = ".b-box--paint .dot {\n " + shadows + " \n}\n";
dottes = frames[0];
shadows = this.createShadow( dottes );
styles += ".b-box--result .dot {\n " + shadows + " \n}\n";
this.stylesShadows.innerHTML = styles;
this.replaceAnimation({perc: perc});
}
// -----------------------------------------
this.createShadow = function( dottes ){
if ( dottes == undefined ){
return;
}
var shadows = "";
var if_first = true;
var cellsMax = oneSide * oneSide;
for (var i = 0; i < cellsMax; i++) {
var dot = dottes["cell-" + i];
var hpos = dot.hpos * dotSize + "px";
var vpos = dot.vpos * dotSize + "px";
var color = transparent;
if ( dot.color != transparent ) {
color = dot.color;
}
if ( if_first ){
if_first = false;
}
else {
shadows += ", ";
}
shadows += hpos + " " + vpos + " 0 0 " + color;
};
shadows = "box-shadow: " + shadows + ";";
return shadows;
}
// -----------------------------------------
this.replaceAnimation = function(animation){
var keyframes = findKeyFrames("shadows");
var rules = keyframes.cssRules;
if ( rules.length > 0 ){
for ( var keyframe in rules ) {
var keyText = rules[keyframe].keyText;
keyframes.deleteRule(keyText);
}
}
for ( var step in frames ){
if ( step == 0 ) continue;
var anim_dottes = frames[step];
var anim_shadows = this.createShadow( anim_dottes );
keyframes.insertRule(animation.perc*step + "% {" + anim_shadows + "}");
}
var resultDot = doc.querySelector(".b-box--result .dot");
resultDot.classList.remove(classIsRunning);
resultDot.offsetWidth = resultDot.offsetWidth;
resultDot.classList.add(classIsRunning);
}
// -----------------------------------------
this.createPalette = function () {
var styles = "";
palette.innerHTML += "<h4 class='b-title'>Colors</h4> ";
for (var i = 0; i < colors.length; i++) {
var replacements = {
"{i}": i,
"{color}": colors[i]
};
var colorItem = fillTemplate( this.colorTempl, replacements );
var colorStyle = fillTemplate( colorStyleTempl, replacements );
this.stylesColors.innerHTML += colorStyle;
palette.innerHTML += colorItem;
}
var first = doc.querySelector("." + colorInpClass);
first.checked = true;
this.addEvents( colorInpClass, this.onClickColor );
}
// -----------------------------------------
this.onClickColor = function( elem ){
currentColor = elem.getAttribute("data-color");
currentColorNum = elem.getAttribute("data-color-num");
currentColorClass = colorClass + "--" + currentColorNum;
}
// -----------------------------------------
this.createSteps = function(){
steps.innerHTML += "<h4 class='b-title'>Frames</h4> ";
for (var i = 0; i < stepsMax; i++) {
var replacements = {
"{i}": i,
"{i+1}": i+1,
};
var step = fillTemplate( this.stepTempl, replacements );
steps.innerHTML += step;
}
var first = doc.querySelector("." + stepInpClass);
first.checked = true;
this.addEvents( stepInpClass, this.onClickStep );
}
// -----------------------------------------
this.onClickStep = function( elem ){
currentFrame = elem.getAttribute("data-step-num");
this.paintShadow();
this.updateCells();
}
// -----------------------------------------
this.updateCells = function() {
var checkboxes = paintBox.querySelectorAll("input");
var frameCells = frames[currentFrame];
var colored = 0;
for (var i = 0; i < checkboxes.length; i++) {
var cell = checkboxes[i];
var id = cell.id;
var color = frameCells[id].color;
if ( color == transparent ){
cell.checked = false;
}
else {
colored++;
cell.checked = true;
}
};
}
codesToggle.onclick = function(){
out("Click!");
var textInit = this.getAttribute("data-init");
var textClose = this.getAttribute("data-opened");
var text = textInit;
if ( is_opened ){
is_opened = false;
}
else {
is_opened = true;
text = textClose;
}
codes.classList.toggle("is-open");
this.innerText = text;
var styleBox = doc.querySelector(".b-box--result");//resultBox
var styleDot = doc.querySelector(".b-box--result .dot");
var styles = getComputedStyle(styleBox, '');//.cssText
out( "styleBox" );
out( styles );
}
}// End Pixelator
// Common
// -----------------------------------------
function out ( data ) {
console.log( data );
}
function addUnits( str ){
str = String(str);
var arr = str.split(" ");
if ( arr.length > 1
&& arr[0].indexOf("px") < 0
&& arr[0].indexOf("em") < 0
&& arr[0].indexOf("%") < 0 ){
str = arr.join("px ") + "px";
return str;
}
if ( str.indexOf("px") < 0
&& str.indexOf("em") < 0
&& arr[0].indexOf("%") < 0 ) {
str += "px";
}
return str;
}
function fillTemplate( dataStr, replacements ) {
for ( var key in replacements ){
var findStr = key;
var replaceWithStr = replacements[key];
dataStr = dataStr.split(findStr).join(replaceWithStr);
}
return dataStr;
}
function objLength( obj ) {
var count = 0;
for ( var key in obj ){
count++;
}
return count;
}
// Init
// -----------------------------------------
var painter = new Pixelator();
painter.init();
@import "compass";
$sideCells: 10;
$dotSize: 30px;
$box-size: $dotSize * $sideCells;
$radius: 10%;
$padding: 20px;
$color-border: #CCC;
$color-active: orange;
$time: 2s;
* {
box-sizing: border-box;
}
LABEL {
cursor: pointer;
}
.l-wrapper {
position: absolute;
display: inline-block;
margin: auto;
left: 1em;
right: 1em;
top: 1em;
bottom: 1em;
border: 1px solid $color-border;
white-space: nowrap;
&:after {
content: '';
display: table;
width: 100%;
clear: both;
}
}
.b-box {
display: inline-block;
border: 1px solid $color-border;
&:nth-of-type(1){
margin-right: $padding;
}
}
.b-title {
float: left;
padding-right: $padding/2;
line-height: $dotSize;
color: #888;
}
/* Paint Box
----------------------------- */
.b-box--paint {
overflow: hidden;
background-image:
linear-gradient( to right,
$color-border 1px,
transparent 1px
),
linear-gradient( to bottom,
$color-border 1px,
transparent 1px
);
background-position: 0 0;
}
/* Labels
----------------------------- */
.cell {
display: block;
float: left;
}
.cell__inp {
position: absolute;
display: none;
}
.cell__lbl {
display: block;
border-radius: $radius;
}
:checked + .cell__lbl {
position: relative;
/* z-index: 5;
background: gold;
opacity: .5*/
}
.is-colored {
background: $color-active;
}
/* Result Box
----------------------------- */
.b-box--result {
overflow: hidden;
}
.dot {
display: block;
position: relative;
border-radius: $radius;
}
//.b-box--result .dot
.is-running{
-webkit-animation: $time shadows linear infinite;
animation: $time shadows linear infinite;
}
@keyframes shadows {
}
@-webkit-keyframes shadows {
}
/* Palette
----------------------------- */
.b-palette {
position: absolute;
border: 1px solid $color-border;
top: -($dotSize + $padding);
left: $padding/2;
height: $dotSize + $padding;
padding: $padding/2;
}
.color {
display: block;
float: left;
width: $dotSize;
height: $dotSize;
}
.color__inp {
display: none;
}
.color__lbl {
display: block;
height: $dotSize;
}
:checked + .color__lbl {
position: relative;
z-index: 1;
box-shadow: 0 0 0 3px rgba(0, 0, 0, .3);
}
/* Steps
----------------------------- */
.b-steps {
position: absolute;
border: 1px solid $color-border;
left: $padding/2;
bottom: -($dotSize + $padding);
height: $dotSize + $padding;
padding: $padding/2;
}
.step {
display: block;
float: left;
width: $dotSize;
height: $dotSize;
margin-right: 1px;
line-height: $dotSize;
background: gainsboro;
text-align: center;
}
.step__inp {
position: absolute;
display: none;
}
.step__lbl {
display: block;
height: $dotSize;
}
:checked + .step__lbl {
position: relative;
z-index: 1;
box-shadow: 0 0 0 3px rgba(0, 0, 0, .3);
}
.step--filled {
background: paleturquoise;
}
/* Codes
----------------------------- */
.b-codes {
display: none;
position: absolute;
z-index: 10;
top: 0;
right: 0;
left: 0;
background: rgba(240, 240, 240, .9);
}
.is-open {
top: -$padding*3;
right: -1em;
bottom: -$padding*3;
left: -1em;
}
.b-codes__toggle {
position: absolute;
top: -$padding*1.2;
right: $padding/2;
border-bottom: 1px dotted;
color: #555;
}
.b-codes__wrapper {
display: none;
padding: $padding;
.is-open & {
display: block;
}
}
.b-codes--title {
margin-bottom: $padding/3;
color: #333;
}
.b-codes__textarea {
display: block;
width: 100%;
height: $dotSize*2;
border: 1px solid $color-border;
}
.textarea--css {
margin-bottom: $padding;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment