diff --git a/README.md b/README.md new file mode 100644 index 00000000..21d5f0d2 --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +This is my JavaScript final project of the CDV Frontend Developer's classes. + +It's web application, that allows you to draw any shapes using randomly selected colors. +You can also add emoji to your drawing and save it to your device. \ No newline at end of file diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 00000000..a1c312f3 Binary files /dev/null and b/images/logo.png differ diff --git a/images/sitting-person.png b/images/sitting-person.png new file mode 100644 index 00000000..134af21e Binary files /dev/null and b/images/sitting-person.png differ diff --git a/index.html b/index.html index e69de29b..456dbfb6 100644 --- a/index.html +++ b/index.html @@ -0,0 +1,81 @@ + + + + + + + Anna's canvas + + + + + +
+ +
+
+
+ +
+
+ + + + +
+
+ The canva is error +
+ + Save as jpeg +
+
+ +
+

You haven't got projects yet. Draw something!

+
+
+ +
+

Hello!

+

+ Lorem ipsum dolor, sit amet consectetur adipisicing elit. Corporis + dolorum ab incidunt ipsum, officiis delectus repudiandae quaerat, + voluptatibus ipsam asperiores eveniet? Dolores tenetur rem veritatis + perferendis reiciendis corporis laboriosam dolore! Provident, + quaerat ab nesciunt amet saepe dicta, modi necessitatibus + repudiandae ex, debitis iste! Hic ratione animi quis esse saepe ad + accusamus quae, laudantium placeat debitis harum maiores pariatur + nam necessitatibus. Laudantium dolor praesentium, voluptatum facilis + ea reiciendis porro maiores velit neque rem. Inventore, praesentium? + Architecto labore ut totam repellat nam debitis ratione illum, quam + aspernatur fuga consectetur amet nulla enim? +

+ My image +
+
+
+ + + diff --git a/main.js b/main.js index e69de29b..cfae5e9e 100644 --- a/main.js +++ b/main.js @@ -0,0 +1,234 @@ +document.addEventListener("DOMContentLoaded", () => { + const api = "https://x-colors.herokuapp.com/api/random"; + const apiKey = "b2d5f5b8a462e384858bbfeaf3f0bf1b84fcd82e"; + const emojiList = `https://emoji-api.com/emojis?access_key=${apiKey}`; + + // DOM Elements + const $previousButton = document.getElementById("previous"); + const $previousTab = document.getElementById("previous-project-btn"); + const $aboutMeTab = document.getElementById("me-btn"); + const $drawTab = document.getElementById("new-image-btn"); + const $previousSection = document.getElementById("previous-project-display"); + const $nextButton = document.getElementById("next"); + const $genEmojis = document.getElementById("generated-emojis"); + const $save = document.getElementById("save-button"); + const $clearBttn = document.getElementById("clear-button"); + const $colorButton = document.getElementById("color-button"); + const $emojiButton = document.getElementById("emojis-button"); + const $colors = document.getElementById("generated-colors"); + + function openPage(pageName, elmnt) { + var i, tabcontent, tablinks; + tabcontent = document.getElementsByClassName("page-content"); + for (i = 0; i < tabcontent.length; i++) { + tabcontent[i].style.display = "none"; + } + tablinks = document.getElementsByClassName("tablink"); + for (i = 0; i < tablinks.length; i++) { + tablinks[i].style.backgroundColor = ""; + } + document.getElementById(pageName).style.display = "block"; + elmnt.style.backgroundColor = "#8573f8"; + } + + $drawTab.addEventListener("click", function () { + openPage("draw-page", this); + }); + $previousTab.addEventListener("click", function () { + openPage("previous-projects-page", this); + }); + $aboutMeTab.addEventListener("click", function () { + openPage("about-me-page", this); + }); + $drawTab.click(); + + // -------------------------CANVAS----------------------- + const $canvas = document.getElementById("canvas"); + const ctx = $canvas.getContext("2d"); + + // Resizing + canvas.height = window.innerHeight / 1.5; + canvas.width = window.innerWidth / 2; + window.addEventListener("resize", () => { + canvas.height = window.innerHeight / 1.5; + canvas.width = window.innerWidth / 2; + }); + + // Canvas position + function getMousePos(canvas, e) { + var rect = canvas.getBoundingClientRect(); + return { + x: ((e.clientX - rect.left) / (rect.right - rect.left)) * canvas.width, + y: ((e.clientY - rect.top) / (rect.bottom - rect.top)) * canvas.height, + }; + } + + // PAINTING + + let painting = false; + const startPosition = function () { + painting = true; + }; + const finishPosition = function () { + painting = false; + ctx.beginPath(); + }; + + function draw(e) { + if (!painting) return; + ctx.lineWidth = 10; + ctx.lineCap = "round"; + var mousePos = getMousePos(canvas, e); + ctx.lineTo(mousePos.x, mousePos.y); + ctx.stroke(); + ctx.save(); + } + + // Canvas event listeners + canvas.addEventListener("mousedown", startPosition); + canvas.addEventListener("mouseup", finishPosition); + canvas.addEventListener("mousemove", draw); + + // Clearing canvas and adding previous project + + $clearBttn.addEventListener("click", () => { + if (($previousSection.firstElementChild.tagName = "h2")) { + $previousSection.firstElementChild.className = "hide"; + } + const addImg = document.createElement("img"); + addImg.classList.add("saved-image"); + addImg.src = imgLink(); + addImg.alt = "Previous project"; + addImg.style.alignContent = "center"; + $previousSection.append(addImg); + ctx.clearRect(0, 0, canvas.width, canvas.height); + }); + + // ------------------------CANVAS-END----------------------------------------- + + function getApiResponse(url) { + const apiRequest = fetch(url); + return (apiResponse = apiRequest + .then((response) => response.json()) + .catch((error) => { + alert( + `Error - data can't be loaded from: + ${url}` + ); + })); + } + + // Generating colors + + function addColorStyle(hex, i) { + const colorsElement = document.createElement("span"); + colorsElement.style.color = hex; + colorsElement.classList = "material-symbols-rounded"; + colorsElement.id = i; + colorsElement.innerText = "circle"; + colorsElement.title = "Click to choose"; + colorsElement.addEventListener("click", () => ctx.strokeStyle = `${hex}`); + $colors.append(colorsElement); + } + + function getColors() { + let oldColors = document.getElementsByClassName("material-symbols-rounded"); + for (var i = oldColors.length - 1; i >= 0; i--) { + oldColors[i].parentNode.removeChild(oldColors[i]); + } + getApiResponse(api).then((colors) => + addColorStyle(colors.hex, "color1") + ); + getApiResponse(api).then((colors) => + addColorStyle(colors.hex, "color2") + ); + getApiResponse(api).then((colors) => + addColorStyle(colors.hex, "color3") + ); + } + + getColors(); + $colorButton.addEventListener("click", () => getColors()); + + // ------------------------emojis----------------- + + + class Emoji { + constructor(group, character, id) { + this.id = id; + this.group = group; + this.character = character; + } + emojis = document.getElementById("generated-emojis"); + renderGroup() { + const groupElement = document.createElement("span"); + groupElement.innerText = this.group; + groupElement.addEventListener("click", () => { + console.log("clicked group"); + }); + this.emojis.append(groupElement); + } + renderEmoji() { + const emojisElement = document.createElement("span"); + emojisElement.innerText = this.character; + emojisElement.title = "Click to choose"; + emojisElement.addEventListener("click", () => { + ctx.font = "12vh verdana"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; + painting = false; + // draw the emoji + canvas.addEventListener( + "click", + (e) => { + var mousePos = getMousePos(canvas, e); + ctx.fillText(this.character, mousePos.x, mousePos.y); + }, + { once: true } + ); + }); + this.emojis.append(emojisElement); + } + } + + $emojiButton.addEventListener("click", async () => { + const emojiJson = await getApiResponse(emojiList); + var counter = 0; + function changeEmojis() { + for (let i = counter; i < counter + 10; i++) { + const emoji = new Emoji(emojiJson[i].group, emojiJson[i].character, i); + emoji.renderEmoji(); + } + } + function delateEmojis() { + while ($genEmojis.firstChild) { + $genEmojis.removeChild($genEmojis.lastChild); + } + } + delateEmojis(); + changeEmojis(); + $nextButton.addEventListener("click", () => { + delateEmojis(); + counter += 10; + changeEmojis(); + }); + $previousButton.addEventListener("click", () => { + delateEmojis(); + counter -= 10; + changeEmojis(); + }); + }); + + // Save image + function imgLink() { + const link = canvas.toDataURL("image/png"); + $save.href = link; + $save.download = "IMAGE.jpeg"; + return link; + } + + $save.addEventListener("click", imgLink); + $emojiButton.click(); + + // end of DOMContentLoaded +}); diff --git a/style.css b/style.css index e69de29b..8d164977 100644 --- a/style.css +++ b/style.css @@ -0,0 +1,226 @@ +@import url("https://fonts.googleapis.com/css2?family=Orbitron:wght@700&family=Special+Elite&display=swap"); + +* { + margin: 0; + padding: 0; + box-sizing: inherit; + font-family: "Special Elite", cursive; + font: bold; + background-color: #8573f8; +} + +body { + height: 100%; + box-sizing: border-box; + -ms-overflow-style: none; /* Internet Explorer 10+ */ + scrollbar-width: none; /* Firefox */ +} +body::-webkit-scrollbar { + display: none; /* Safari and Chrome */ +} + +#nav { + top: 0; + left: 0; + width: 100%; + height: 10vh; + min-height: 50px; + background-color: #f8a500; + align-items: flex-end; + display: flex; + justify-content: space-around; + text-transform: uppercase; +} +#nav button { + min-height: 48px; + margin-top: 2px; + background-color: #f8a500; + padding: 3vh; + border-top-right-radius: 20px; + border-top-left-radius: 20px; + color: #f8e9b5; + cursor: pointer; + outline: none; + border: none; + width: 30%; + float: left; + font-size: large; +} +#nav .tablink:hover { + background-color: #bb8f00; +} +.page-content { + color: white; + display: none; + padding: 20px 20px; + height: 100%; +} + +#rendered-elements { + display: flex; + height: 12vh; + background-color: #8573f8; + align-items: center; + justify-content: space-around; +} + +#draw-page .single-section { + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; +} +.left { + flex-direction: column; + align-items: center; + float: left; + border: 0; + padding: 0; + width: 20%; + margin-top: 10%; + justify-content: space-between; +} +.right { + flex-direction: column; + align-items: center; + float: right; + border: 0; + width: 20%; + margin-top: 15%; +} + +.btn { + background-color: #0019d988; + color: ghostwhite; + border: 2px #0019d988; + border-radius: 5px; + padding: 18px; + margin: 4px; + cursor: pointer; + width: 200px; + text-align: center; + font-size: medium; + border: 2px solid #001ad9; +} +.btn:hover { + background-color: #ffc400; + color: #001ad9; +} +.btn:active { + background-color: #ffc400; + box-shadow: 0 1px #001ad9; + transform: translateY(2px); +} +canvas { + border: 2px solid #cd81d4; + position: absolute; + top: 55%; + left: 50%; + transform: translate(-50%, -50%); + background-color: ghostwhite; +} +a { + text-decoration: none; + display: inline-block; + padding: 4px 12px; +} + +a:hover { + background-color: #ddd; + color: black; +} + +#previous-projects-page { + margin: auto; + display: block; + padding: 10px 30px; + text-align: center; + max-width: fit-content; +} +#previous-project-display { + display: inline-block; + margin-left: 30vh; +} +#rendered-elements { + justify-content: space-between; +} + +#previous { + background-color: #001ad9; + color: rgb(255, 255, 255); + border-radius: 50%; +} +#next { + background-color: #001ad9; + color: white; + border-radius: 50%; +} +#generated-colors { + text-align: center; +} +#generated-colors span:active { + border: #001ad9 solid 2px; + border-radius: 50%; +} +.emojis { + text-align: center; + /* display: contents; */ + display: block; + font-size: 30px; + margin: 10px; +} +#generated-emojis { + display: inline-block; +} +#generated-emojis span { + cursor: pointer; +} +#emojis-button { + display: block; + margin: auto; + margin-top: 5px; +} +.saved-image { + height: 33vh; + align-items: center; + margin: 15px 10px; + background-color: #43da532b; +} + +#nav #logo { + cursor: default; + border-bottom-left-radius: 50%; + border-bottom-right-radius: 50%; + height: 181px; + margin-top: auto; + width: 16%; + min-width: fit-content; + z-index: 10; +} +#logo img { + height: 16vh; + background: none; + border-radius: 50%; +} +#about-me { + text-align: center; +} +.text { + display: block; + text-align: center; + padding: 20px 30px; + justify-content: space-between; + max-width: 100vh; + margin: auto; +} +#about-me img { + max-width: 30vh; + max-height: fit-content; +} +.show { + display: block; + margin-top: 50%; +} +.hide { + display: none; +}