diff --git a/images/blank.svg b/images/blank.svg new file mode 100644 index 0000000..27f6104 --- /dev/null +++ b/images/blank.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/main.js b/main.js index aee1a3b..24d63c4 100644 --- a/main.js +++ b/main.js @@ -5,44 +5,81 @@ import Canvas from "./ui/canvas.js"; import Button from "./ui/button.js"; import Panel from "./ui/panel.js"; +import Form from "./ui/editors/form.js"; +import NumericBox from "./ui/editors/numericBox.js"; +import SwitchBox from "./ui/editors/switchBox.js"; + document.body.innerHTML = ""; const maxPanelWidth = 300; +const panelPaddingTop = 90; + +let random = true; +let amountOfShapes = 100; Shape.setBounding(window.innerWidth, window.innerHeight); let canvas = new Canvas(window.innerWidth, window.innerHeight); -let repaint = new Button("paint"); -repaint.addHandler(canvas.clear.bind(canvas)); -repaint.addHandler(paint); -repaint.setPosition(25, 25); +let paintButton = new Button("paint"); +paintButton.addHandler(paint); -let panel = new Panel(Math.min(maxPanelWidth ,window.innerWidth - 20), window.innerHeight - 20); +let panelWidth = Math.min(maxPanelWidth ,window.innerWidth - 20); +let panelHeight = window.innerHeight - 20; +let panel = new Panel(panelWidth, panelHeight); +panel.element.style.paddingTop = panelPaddingTop + "px"; panel.setPosition(10, 10); let settings = new Button("gear"); settings.addHandler(panel.toggle.bind(panel)); -settings.setPosition(100, 25); + +let clear = new Button("blank"); +clear.addHandler(canvas.clear.bind(canvas)); window.addEventListener("resize", onWindowResize, false); +let form = new Form(panelWidth, panelHeight - panelPaddingTop); +let randomBox = new SwitchBox(random, 50, 30); +let amountBox = new NumericBox(50, 100); +amountBox.setValue(amountOfShapes); + +form.addLine("random", "Random amount of shapes",randomBox); +form.addLine("amount", "Amount of shapes", amountBox); + +panel.add(form); + document.body.appendChild(canvas.element); document.body.appendChild(panel.element); -document.body.appendChild(repaint.element); +document.body.appendChild(paintButton.element); document.body.appendChild(settings.element); +document.body.appendChild(clear.element); +adjustButtons(panelWidth); paint(); function onWindowResize(e) { Shape.setBounding(window.innerWidth, window.innerHeight); canvas.setSize(window.innerWidth, window.innerHeight); - panel.setSize(Math.min(maxPanelWidth ,window.innerWidth - 20), window.innerHeight - 20) + + let panelWidth = Math.min(maxPanelWidth ,window.innerWidth - 20); + panel.setSize(panelWidth, window.innerHeight - 20); + adjustButtons(panelWidth); } function paint() { - let amount = Math.floor(Math.random() * 100 + 50); + let amount; + if (random) { + amount = Math.floor(Math.random() * amountOfShapes); + } else { + amount = amountOfShapes; + } for (let i = 0; i < amount; ++i) { let shape = factory.createRandomShape(); canvas.draw(shape); } +} + +function adjustButtons(width) { + paintButton.setPosition(width / 4, 25); + settings.setPosition(width / 2, 25); + clear.setPosition(width * 0.75, 25); } \ No newline at end of file diff --git a/style.css b/style.css index c0169c5..13f3502 100644 --- a/style.css +++ b/style.css @@ -3,6 +3,10 @@ body { overflow: hidden; } +* { + box-sizing: border-box; +} + button { z-index: 2; overflow: hidden; @@ -44,4 +48,65 @@ button:hover { .shadow { box-shadow: rgba(0, 0, 0, 0.5) 0px 1px 4px 0px; +} + +.switchBox { + position: relative; + overflow: hidden; + -webkit-transition: background-color 0.2s ease-in-out; + -moz-transition: background-color 0.2s ease-in-out; + -ms-transition: background-color 0.2s ease-in-out; + -o-transition: background-color 0.2s ease-in-out; + transition: background-color 0.2s ease-in-out; + background-color: #b8b8b8; + cursor: pointer +} + +.switchBox > .mover { + position: absolute; + width: 100%; + height: 100%; + top: 0; + -webkit-transition: right 0.2s ease-in-out; + -moz-transition: right 0.2s ease-in-out; + -ms-transition: right 0.2s ease-in-out; + -o-transition: right 0.2s ease-in-out; + transition: right 0.2s ease-in-out; +} + +.switchBox .circle { + background-color: #ffffff; + position: absolute; + border-radius: 50%; +} + +.numericBox { + border: none; + height: 100%; + width: 100%; +} + +.form { + overflow-x: hidden; + overflow-y: auto +} + +.form > div { + -webkit-transition: height 0.2s ease-in-out; + -moz-transition: height 0.2s ease-in-out; + -ms-transition: height 0.2s ease-in-out; + -o-transition: height 0.2s ease-in-out; + transition: height 0.2s ease-in-out; +} + +.form > div > div { + float: left; +} + +.form > div > div:nth-child(0) { + width: 50% +} + +.form > div > div:nth-child(1) { + width: 50% } \ No newline at end of file diff --git a/ui/button.js b/ui/button.js index 04af0ed..33c77a9 100644 --- a/ui/button.js +++ b/ui/button.js @@ -2,7 +2,7 @@ import UI from "./ui.js"; class Button extends UI { constructor(image) { - super(document.createElement("button"), 50, 50); + super(document.createElement("button"), Button.width, Button.height); this.element.classList.add("shadow"); this.element.style.backgroundImage = "url(images/" + image + ".svg)"; @@ -31,6 +31,15 @@ class Button extends UI { } } + static get width() { + return width; + } + static get height() { + return height; + } } +const width = 50; +const height = 50; + export default Button; \ No newline at end of file diff --git a/ui/editors/form.js b/ui/editors/form.js new file mode 100644 index 0000000..da5a7d5 --- /dev/null +++ b/ui/editors/form.js @@ -0,0 +1,37 @@ +import UI from "../ui.js"; + +class Form extends UI { + constructor(width, height) { + super(document.createElement("div"), width, height); + + this.element.classList.add("form"); + this._lines = []; + this._linesById = Object.create(null); + } + addLine(id, label, editor) { + let line = document.create("div"); + let labelCell = document.create("div"); + let editorCell = document.create("div"); + + labelCell.innerText = label; + editorCell.appendChild(editor.element); + + line.appendChild(labelCell); + line.appendChild(editorCell); + + let obj = { + id: id, + label: label, + editor: editor, + visible: true, + line: line + }; + + this._lines.push(obj); + this._linesById[id] = obj; + + this.element.appendChild(line); + } +} + +export default Form; \ No newline at end of file diff --git a/ui/editors/numericBox.js b/ui/editors/numericBox.js new file mode 100644 index 0000000..d05c06b --- /dev/null +++ b/ui/editors/numericBox.js @@ -0,0 +1,106 @@ +import UI from "../ui.js"; + +class NumericBox extends UI { + constructor(width, height) { + super(document.createElement("div"), width, height); + + this._valid = false; + this._value = true; + + this._createInput(); + this._bindEvents(); + } + destructor() { + this._input.removeEventListener("keyPress", this._boundKeyPress); + this._input.removeEventListener("input", this._boundInput); + delete this._boundKeyPress; + delete this._boundInput; + delete this._input; + + super.destructor(); + } + get value() { + if (this._valid) { + return this._value; + } else { + throw new Error("An attempt to get value of invalid NumericBox"); + } + } + setValue(value) { + let val = parseFloat(value); + this._value = val; + + this._input.value = val.toString(); + this._valid = true; + } + _bindEvents() { + this._boundInput = this._onInput.bind(this); + this._boundKeyPress = this._onKeyPress.bind(this); + + this._input.addEventListener("keyPress", this._boundKeyPress); + this._input.addEventListener("input", this._boundInput); + } + _createInput() { + this._input = document.createElement("div"); + this._input.classList.add("numericBox"); + + this.element.appendChild(this._input); + } + _onInput(e) { + let oldVal = this._value; + let newVal = this._input.value; + + if (newVal === "" || newVal === "-" || newVal === ".") { + if (newVal === ".") { + this.setValue(0); + this._input.value += '.'; + } else { + this._input.value = newVal; + this._value = null; + this._valid = false; + } + } else if (!newVal.match(/^\-?[0-9]+(\.[0-9]*)?$/)) { + if (oldVal === null) { + this._input.value = ""; + this._valid = false; + this._value = null; + } else { + this.setValue(oldVal); + } + } else { + let dotIndex = newVal.indexOf('.'); + if (newVal[newVal.length-1] === '.') { + this.setValue(parseFloat(newVal)); + this._input.value += '.'; + } else if (dotIndex > 0 && newVal[newVal.length-1] === "0") { + this.setValue(parseFloat(newVal)); + this._input.value = newVal; + } else { + this.setValue(parseFloat(newVal)); + } + } + } + _onKeyPress(e) { + switch (e.charCode) { + case 45: // "-" + case 1102: + case 46: // "." + case 48: //zero + case 49: //other digits + case 50: + case 51: + case 52: + case 53: + case 54: + case 55: + case 56: + case 57: + break; + default: + e.preventDefault(); + break; + } + } +} + +export default NumericBox; \ No newline at end of file diff --git a/ui/editors/switchBox.js b/ui/editors/switchBox.js new file mode 100644 index 0000000..682b748 --- /dev/null +++ b/ui/editors/switchBox.js @@ -0,0 +1,89 @@ +import UI from "../ui.js"; + +class SwitchBox extends UI { + constructor(value, width, height) { + super(document.createElement("div"), width, height); + + this._initialized = true; + + this._boundClick = this._onClick.bind(this); + this.element.addEventListener("click", this._boundClick, false); + this._createInput(); + this._setSize(); + this.setValue(value); + } + destructor() { + this.element.removeEventListener("click", this._boundClick); + + delete this._boundClick; + delete this._input; + delete this._movable; + delete this._circle; + + super.destructor(); + } + setSize(width, height) { + super.setSize(width, height); + + if (this._initialized) { + this._setSize(); + } + } + setValue(val) { + if (this._value !== val) { + this._value = value; + if (this._value) { + this._input.style.backgroundColor = "#00b6ff"; + this._movable.style.right = 0 + "px"; + } else { + this._input.style.backgroundColor = "#b8b8b8"; + this._movable.style.right = (this._iWidth - this._iHeight) + "px"; + } + } + } + + _createInput() { + this._input = document.createElement("div"); + this._input.classList.add("switchBox"); + + this._movable = document.createElement("div"); + this._movable.classList.add("mover"); + + this._circle = document.createElement("div"); + this._circle.classList.add("circle"); + + this._movable.appendChild(this._circle); + this._input.appendChild(this._movable); + this.element.appendChild(this._input); + } + _onClick() { + this.setValue(!this._value); + } + _setSize() { + let dh = this._width / 2.5; + dh = Math.min(dh, this._height); + let dw = dh * 2.5; + + this._iWidth = dw; + this._iHeight = dh; + let circleDiameter = Math.round(dh * 0.80); + + this._input.style.width = dw + "px"; + this._input.style.height = dh + "px"; + this._input.style.borderRadius = dh + "px"; + + let shift = (this._height - dh) / 2; + this.element.style.paddingTop = shift + "px"; + this.element.style.paddingBottom = shift + "px"; + + this._movable.style.right = (dw - dh) + "px"; + + shift = (dh - circleDiameter) / 2; + this._circle.style.width = circleDiameter + "px"; + this._circle.style.height = circleDiameter + "px"; + this._circle.style.right = shift + "px"; + this._circle.style.top = shift + "px"; + } +} + +export default SwitchBox; \ No newline at end of file diff --git a/ui/panel.js b/ui/panel.js index f64e812..76092c8 100644 --- a/ui/panel.js +++ b/ui/panel.js @@ -9,7 +9,9 @@ class Panel extends UI { this.element.classList.add("shadow"); this.element.classList.add("hidden"); } - + add(ui) { + this.element.appendChild(ui.element); + } toggle() { if (this._hidden) { this.show();