Last active
March 27, 2017 22:44
-
-
Save sgnl/913efaa9ac13ca5992a40b17c1c4fd25 to your computer and use it in GitHub Desktop.
OOP PixelPainter - an example for dev league students
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Document</title> | |
<link rel="stylesheet" href="/css/styles.css"> | |
</head> | |
<body> | |
<div id="painter-app"></div> | |
<script src="/js/painter-app.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Pixel { | |
constructor(color, width, height) { | |
this.color = color; | |
this.element = document.createElement('div'); // public DOM access | |
this.element.classList.add('pixel'); | |
/** | |
* styling | |
*/ | |
this.element.style.backgroundColor = this.color; | |
this.element.style.height = `${height}px`; | |
this.element.style.width = `${width}px`; | |
} | |
} | |
class Swatch { | |
constructor(parent, colors) { | |
// Parent is an instance of Painter class | |
// we will need to use some public methods | |
this.parent = parent; | |
this.currentColor = null; | |
this.element = document.createElement('div'); | |
this.element.classList.add('swatch'); | |
// create colors | |
// a Swatch contains many Pixels | |
colors.forEach(color => { | |
let colorPixel = new Pixel(color, 30, 30); | |
this.element.appendChild(colorPixel.element); | |
}); | |
/** | |
* events | |
*/ | |
this.element.addEventListener('click', this.setCurrentColor.bind(this)); | |
} | |
/** | |
* public methods | |
*/ | |
setCurrentColor(e) { | |
// only care if the the clicked element is an instance of Pixel | |
// by checking if the element has a class name of `pixel` | |
if (e.target.classList.contains('pixel')) { | |
// set the current color of the app via Parent's public method | |
this.parent.currentColor = e.target.style.backgroundColor; | |
} | |
} | |
} | |
class Canvas { | |
constructor(parent, size) { | |
// Parent is an instance of Painter class | |
// we will need to use some public methods | |
this.parent = parent; | |
this.element = document.createElement('div'); | |
this.element.classList.add('canvas'); | |
let pixelSize = 20; | |
// a Canvas contains many Pixels | |
// create canvas { size x size } | |
for (let i = size; i > 0; i--) { | |
let rowDiv = document.createElement('div'); | |
rowDiv.classList.add('row'); | |
for (let j = size; j > 0; j--) { | |
let blankPixel = new Pixel('white', pixelSize, pixelSize); | |
rowDiv.appendChild(blankPixel.element); | |
} | |
this.element.appendChild(rowDiv); | |
} | |
/** | |
* styling | |
*/ | |
this.element.style.height = `${size * 20}px`; | |
/** | |
* events | |
*/ | |
this.element.addEventListener('click', e => this.setPixelColor(e)); | |
} | |
/** | |
* public methods | |
*/ | |
reset() { | |
// find all Pixel elements inside of the Canvas grid | |
// iterate through and set the background-color to 'white' | |
let canvasPixels = document.querySelectorAll('.canvas .pixel'); | |
canvasPixels.forEach(pixel => pixel.style.backgroundColor = 'white'); | |
} | |
setPixelColor(e) { | |
// retrieve color value from public method on Parent class | |
// and set it to the element which was clicked | |
e.target.style.backgroundColor = this.parent.currentColor; | |
} | |
} | |
/** | |
* helper function for creating interactive elements with do 'things' | |
*/ | |
class Clickable { | |
// options { | |
// type: String, | |
// text: String, | |
// events: Array[ String{event name}, Function{event handler}] | |
// } | |
constructor(parent, options) { | |
// Parent is an instance of Painter class | |
// we will need to use some public methods | |
this.parent = parent; | |
this.element = document.createElement(options.type); | |
this.element.innerText = options.text; | |
// add events dynamically | |
// | |
options.events.forEach(eventTuple => { | |
this.element.addEventListener(eventTuple[0], eventTuple[1]); | |
}); | |
} | |
} | |
class Painter { | |
constructor(target, size, colors) { | |
this.element = document.createElement('div'); | |
this.container = document.querySelector(target); | |
this.element.classList.add('painter-main-app'); | |
this._currentColor = null; | |
this.swatch = new Swatch(this, colors); | |
this.canvas = new Canvas(this, size); | |
this.clearButton = new Clickable(this, { | |
type: 'button', | |
text: 'clear', | |
events: [ | |
['click', e => this.resetCanvas()], | |
['click', e => console.log('tracking')], | |
] | |
}); | |
this.eraseButton = new Clickable(this, { | |
type: 'button', | |
text: 'erase', | |
events: [ | |
['click', e => this.currentColor = 'white'] | |
] | |
}); | |
this.swatch.element.appendChild(this.clearButton.element); | |
this.swatch.element.appendChild(this.eraseButton.element); | |
this.element.appendChild(this.swatch.element); | |
this.element.appendChild(this.canvas.element); | |
this.container.appendChild(this.element); | |
} | |
/** | |
* public methods | |
*/ | |
set currentColor(value) { | |
this._currentColor = value; | |
} | |
get currentColor() { | |
return this._currentColor; | |
} | |
resetCanvas() { | |
this.canvas.reset(); | |
} | |
} | |
/** | |
* 🎉 | |
*/ | |
new Painter('#painter-app', 10, ['red', 'green', 'yellow', 'blue']); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.pixel { | |
box-sizing: border-box; | |
border: 1px solid black; | |
} | |
.swatch { | |
display: flex; | |
flex-flow: column nowrap; | |
width: 30%; | |
} | |
.swatch .pixel {} | |
.canvas { | |
display: flex; | |
flex-flow: row wrap; | |
justify-content: flex-start; | |
} | |
.painter-main-app { | |
display: flex; | |
width: 660px; | |
margin: 0 auto; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment