<div id="app">
<div class="icon-container">
<div id="eaicon" class="shape-square bg-dark">
<div class="background bg-redorange"></div>
<div class="icon">
<img class="face" src="https://cldup.com/MitITBt1_i.png">
<img class="eyebase" src="https://cldup.com/FN7dGVFgVA.png">
<img class="eyes" src="https://cldup.com/CRO0fbUPUk.png">
<img class="mouth" src="https://cldup.com/EFgudoA6nX.png">
</div>
<div class="border bg-redorange"></div>
</div>
</div>
<form id="editor">
<fieldset class="general">
<legend>General</legend>
<div>
<label for="icon_shape">Shape:</label>
<select id="icon_shape">
<option value="shape-square">Square</option>
<option value="shape-rounded">Rounded</option>
<option value="shape-circle">Circle</option>
</select>
</div>
<div>
<label for="icon_background_color">Background Color:</label>
<select id="icon_background_color">
<option value="bg-lime">Lime</option>
<option value="bg-green">Green</option>
<option value="bg-yellow">Yellow</option>
<option value="bg-orange">Orange</option>
<option value="bg-cyan">Cyan</option>
<option value="bg-black">Black</option>
<option value="bg-redorange" selected>Redorange</option>
<option value="bg-blue">Blue</option>
<option value="bg-purple">Purple</option>
<option value="bg-red">Red</option>
<option value="custom">Custom</option>
</select>
</div>
<div name="icon_background_color_custom" style="display: none;">
<label for="icon_background_color_custom_color">Background Custom Color:</label>
<input id="icon_background_color_custom_color" type="text"></input>
</div>
<div>
<label for="icon_border_color">Border Color:</label>
<select id="icon_border_color">
<option value="bg-lime">Lime</option>
<option value="bg-green">Green</option>
<option value="bg-yellow">Yellow</option>
<option value="bg-orange">Orange</option>
<option value="bg-cyan">Cyan</option>
<option value="bg-black">Black</option>
<option value="bg-redorange" selected>Redorange</option>
<option value="bg-blue">Blue</option>
<option value="bg-purple">Purple</option>
<option value="bg-red">Red</option>
<option value="custom">Custom</option>
</select>
</div>
<div name="icon_border_color_custom" style="display: none;">
<label for="icon_border_color_custom_color">Border Custom Color:</label>
<input id="icon_border_color_custom_color" type="text"></input>
</div>
</fieldset>
<fieldset class="eyes">
<legend>Eyes</legend>
<div>
<label for="eyes_shape">Shape:</label>
<select id="eyes_shape">
<option value="normal">Normal</option>
<option value="stick">Stick</option>
<option value="circle">Circle</option>
<option value="circle2">Circle2</option>
<option value="phonecat">電話猫</option>
</select>
</div>
<div>
<label for="eyes_hue">Hue:</label>
<input id="eyes_hue" type="range" value="0" min="0" max="360"></input>
<output name="eyes_hue_value" id="eyes_hue_value">0</output>
</div>
<div>
<label for="eyes_saturation">Saturation:</label>
<input id="eyes_saturation" type="range" value="100" min="0" max="300"></input>
<output name="eyes_saturation_value" id="eyes_saturation_value">100</output>
</div>
<div>
<label for="eyes_brightness">Brightness:</label>
<input id="eyes_brightness" type="range" value="100" min="0" max="300"></input>
<output name="eyes_brightness_value" id="eyes_brightness_value">100</output>
</div>
</fieldset>
<fieldset class="mouth">
<legend>Mouth</legend>
<div>
<label for="mouth_shape">Shape:</label>
<select id="mouth_shape">
<option value="none">None</option>
<option value="open" selected>Open</option>
<option value="smile">Smile</option>
<option value="close">Closed</option>
<option value="anger">Anger</option>
<option value="circle">Circle</option>
<option value="phonecat">電話猫</option>
</select>
</div>
</fieldset>
<fieldset class="eyebrows">
<legend>Eyebrows</legend>
<div>
<label for="">Shape:</label>
<select id="" disabled>
<option value="">Unavailable</option>
</select>
</div>
</fieldset>
<fieldset class="hair">
<legend>Hair</legend>
<div>
<label for="">Color:</label>
<select id="" disabled>
<option value="">Unavailable</option>
</select>
</div>
</fieldset>
<fieldset class="options">
<legend>Options</legend>
<div>
<label for="bleeding">Bleeding:</label>
<input type="checkbox" id="option_bleeding" name="bleeding" value="bleeding" disabled />
<!-- https://mstdn.maud.io/users/pikepikeid/statuses/100702747059289318 -->
</div>
</fieldset>
<fieldset class="ebi">
<legend>EBI</legend>
<span id="ebi">🦐</span>
</fieldset>
</form>
</div>
<footer>
<p>
<span class="title">CUSTOM EAI 2D</span> by
</p>
<address>
<a href="//mizle.net" target="_blank"><img src="//github.com/eai04191.png">Eai</a>.
</address>
</footer>
// $width: 256px;
// $height: 256px;
$width: 512px;
$height: 512px;
$dark: #242f3d;
$light: #e5eaf0;
$lime: #90ba3c;
$green: #55943c;
$yellow: #ded357;
$orange: #eea557;
$cyan: #57cbde;
$black: #808080;
$redorange: #de6957;
$blue: #3f4ed9;
$purple: #574ede;
$red: #de4657;
:root {
font-family: "Open Sans", sans-serif;
font-weight: 400;
body {
background-color: $dark;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
animation: gradation 60s infinite;
}
footer {
display: flex;
color: #9396a4;
background: #34363f;
border-top: 1px solid #3f414b;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
padding: 0.5rem;
box-sizing: border-box;
.title {
font-weight: 700;
}
p {
margin: 0;
max-width: 1920px;
}
address {
font-style: inherit;
a {
color: inherit;
}
img {
width: 1rem;
height: 1rem;
border-radius: 12%;
margin: 0 0.25rem;
}
}
}
}
@keyframes gradation {
0% {
background-color: rgba($lime, 0.25);
}
10% {
background-color: rgba($green, 0.25);
}
20% {
background-color: rgba($yellow, 0.25);
}
30% {
background-color: rgba($orange, 0.25);
}
40% {
background-color: rgba($cyan, 0.25);
}
50% {
background-color: rgba($black, 0.25);
}
60% {
background-color: rgba($redorange, 0.25);
}
70% {
background-color: rgba($blue, 0.25);
}
80% {
background-color: rgba($purple, 0.25);
}
90% {
background-color: rgba($red, 0.25);
}
100% {
background-color: rgba($lime, 0.25);
}
}
:root {
.bg-dark {
background-color: $dark;
}
.bg-lime {
background-color: $lime;
}
.bg-green {
background-color: $green;
}
.bg-yellow {
background-color: $yellow;
}
.bg-orange {
background-color: $orange;
}
.bg-cyan {
background-color: $cyan;
}
.bg-black {
background-color: $black;
}
.bg-redorange {
background-color: $redorange;
}
.bg-blue {
background-color: $blue;
}
.bg-purple {
background-color: $purple;
}
.bg-red {
background-color: $red;
}
}
#app {
overflow: hidden;
position: relative;
padding: 80px;
width: 70%;
max-width: 1000px;
color: white;
&::before {
background-color: rgba($dark, 0.75);
position: absolute;
top: 0;
left: 0;
content: " ";
display: block;
width: 100%;
height: 100%;
filter: blur(1px);
}
.icon-container {
position: relative;
width: 100%;
height: 100%;
&::before {
font-family: "Open Sans", sans-serif;
font-weight: 700;
content: "PREVIEW";
position: absolute;
top: -2rem;
left: 0;
font-size: 4rem;
line-height: 1;
color: rgba($dark, 0.25);
}
#eaicon {
position: relative;
width: $width;
height: $height;
overflow: hidden;
margin: auto;
margin-bottom: 40px;
.background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
filter: blur(20px);
}
.border {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5));
mask-size: cover;
// TODO: 内側のシャドウ
// box-shadow: inset 0 0 10px 2px rgba(0, 0, 0, 0.1);
}
.icon {
.face {
width: $width;
height: $height;
position: relative;
filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5));
}
.eyebase,
.eyes,
.mouth {
width: $width;
height: $height;
position: absolute;
top: 0;
left: 0;
}
}
&.shape-square {
.border {
mask-image: url(https://cldup.com/N3d-dGMJo0.png);
}
}
&.shape-rounded {
&,
.background,
.border,
.face img {
border-radius: 12%;
}
.border {
mask-image: url(https://cldup.com/A7B1owThlI.png);
}
}
&.shape-circle {
&,
.background,
.border,
.face img {
border-radius: 50%;
}
.border {
mask-image: url(https://cldup.com/09o5ejxIeB.png);
}
}
}
}
#editor {
display: flex;
flex-wrap: wrap;
position: relative;
margin: auto;
&::before {
font-family: "Open Sans", sans-serif;
font-weight: 700;
content: "EDITOR";
position: absolute;
bottom: -2rem;
right: 0;
font-size: 4rem;
line-height: 1;
color: rgba($dark, 0.25);
}
fieldset {
flex-grow: 1;
display: flex;
flex-direction: column;
margin: 0 2px;
margin-bottom: 10px;
box-sizing: border-box;
padding: 1rem;
legend {
padding: 0 0.5rem;
}
div {
display: flex;
flex-direction: row;
align-items: center;
input,
select {
width: 10rem;
height: 2rem;
}
label {
flex-grow: 1;
}
output {
width: 3rem;
}
}
&.general {
}
&.eyes {
min-width: calc(50% - 4px);
}
&.mouth {
}
&.eyebrows {
}
&.hair {
}
&.ebi {
text-align: center;
span {
font-size: 3rem;
line-height: 1;
margin: 0;
cursor: default;
user-select: none;
}
}
}
}
.animation-spin {
animation: spin 1.5s cubic-bezier(1, -0.6, 0, 1.65);
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
}
View Compiled
document.addEventListener(
"DOMContentLoaded",
function() {
// General
document.getElementById("icon_shape").onchange = eShape;
document.getElementById(
"icon_background_color"
).onchange = eBackgroundColor;
document.getElementById(
"icon_background_color_custom_color"
).onchange = eBackgroundColorCustom;
document.getElementById("icon_border_color").onchange = eBorderColor;
document.getElementById(
"icon_border_color_custom_color"
).onchange = eBorderColorCustom;
// Eyes
document.getElementById("eyes_shape").onchange = eEyesShape;
document.getElementById("eyes_hue").oninput = eEyesHue;
document.getElementById("eyes_saturation").oninput = eEyesSaturation;
document.getElementById("eyes_brightness").oninput = eEyesBrightness;
// Mouth
document.getElementById("mouth_shape").onchange = eMouthShape;
// Other
document.getElementById("ebi").onmouseover = eEbi;
},
false
);
function eShape(event) {
removeShapeClass();
addShapeClass(event.target.value);
function removeShapeClass() {
const eaicon = document.getElementById("eaicon");
// アロー関数何もわからん
eaicon.className.split(" ").forEach(function(c) {
if (c.match(/shape-*/)) {
eaicon.classList.remove(c);
}
});
}
function addShapeClass(shape) {
const eaicon = document.getElementById("eaicon");
eaicon.classList.add(shape);
}
}
function eBackgroundColor(event) {
removeBackgroundColorClass();
if (event.target.value == "custom") {
openBackgroundColorCustom();
} else {
addBackgroundColorClass(event.target.value);
}
function removeBackgroundColorClass() {
const background = document.querySelector("#eaicon .background");
background.className.split(" ").forEach(function(c) {
if (c.match(/bg-*/)) {
background.classList.remove(c);
}
});
}
function addBackgroundColorClass(color) {
const background = document.querySelector("#eaicon .background");
background.classList.add(color);
}
function openBackgroundColorCustom() {
const backgroundColorCustom = document.querySelector(
"[name='background_color_custom']"
);
backgroundColorCustom.style.display = "inherit";
}
}
function eBackgroundColorCustom(event) {
const background = document.querySelector("#eaicon .background");
background.style.backgroundColor = event.target.value;
}
function eBorderColor(event) {
removeBorderColorClass();
if (event.target.value == "custom") {
openBorderColorCustom();
} else {
addBorderColorClass(event.target.value);
}
function removeBorderColorClass() {
const border = document.querySelector("#eaicon .border");
border.className.split(" ").forEach(function(c) {
if (c.match(/bg-*/)) {
border.classList.remove(c);
}
});
}
function addBorderColorClass(color) {
const border = document.querySelector("#eaicon .border");
border.classList.add(color);
}
function openBorderColorCustom() {
const borderColorCustom = document.querySelector(
"[name='border_color_custom']"
);
borderColorCustom.style.display = "inherit";
}
}
function eBorderColorCustom(event) {
const border = document.querySelector("#eaicon .border");
border.style.backgroundColor = event.target.value;
}
function eEyesShape(event) {
const value = event.target.value;
const eyes = document.querySelector("#eaicon .icon .eyes");
const eyebase = document.querySelector("#eaicon .icon .eyebase");
switch (value) {
case "stick":
eyebase.style.visibility = "hidden";
eyes.src = "https://cldup.com/B01QF5P5eJ.png";
break;
case "circle":
eyebase.style.visibility = "hidden";
eyes.src = "https://cldup.com/9P3fLi7XMh.png";
break;
case "circle2":
eyebase.style.visibility = "hidden";
eyes.src = "https://cldup.com/Jv8_8PpQic.png";
break;
case "phonecat":
eyebase.style.visibility = "hidden";
eyes.src = "https://cldup.com/SlYAJzrZ_S.png";
break;
case "normal":
default:
eyebase.style.visibility = "visible";
eyes.src = "https://cldup.com/CRO0fbUPUk.png";
break;
}
}
function eEyesHue(event) {
const value = event.target.value;
const eyes = document.querySelector("#eaicon .icon .eyes");
document.getElementById("eyes_hue_value").value = value;
eyes.style.filter = eyes.style.filter.replace(/hue-rotate\(\d+deg\)/g, "");
eyes.style.filter += `hue-rotate(${value}deg)`;
}
function eEyesSaturation(event) {
const value = event.target.value;
const eyes = document.querySelector("#eaicon .icon .eyes");
document.getElementById("eyes_saturation_value").value = value;
eyes.style.filter = eyes.style.filter.replace(/saturate\(\d+%\)/g, "");
eyes.style.filter += `saturate(${value}%)`;
}
function eEyesBrightness(event) {
const value = event.target.value;
const eyes = document.querySelector("#eaicon .icon .eyes");
document.getElementById("eyes_brightness_value").value = value;
eyes.style.filter = eyes.style.filter.replace(/brightness\(\d+%\)/g, "");
eyes.style.filter += `brightness(${value}%)`;
}
function eMouthShape(event) {
const value = event.target.value;
const mouth = document.querySelector("#eaicon .icon .mouth");
switch (value) {
case "none":
mouth.src = "";
break;
case "smile":
mouth.src = "https://cldup.com/DipipKtMUt.png";
break;
case "open":
mouth.src = "https://cldup.com/_Cc07lJcE6.png";
break;
case "anger":
mouth.src = "https://cldup.com/oaz8IJZ1aN.png";
break;
case "close":
mouth.src = "https://cldup.com/zcucjx3bXw.png";
break;
case "circle":
mouth.src = "https://cldup.com/VA9yQrEuMu.png";
break;
case "phonecat":
mouth.src = "https://cldup.com/hNjRvYeosx.png";
break;
}
}
function eEbi(event) {
const ebi = document.getElementById("ebi");
ebi.addEventListener("animationend", function(event) {
removeAnimationClass(ebi);
});
addAnimationClass(ebi, "spin");
function removeAnimationClass(element) {
element.className.split(" ").forEach(function(c) {
if (c.match(/animation-*/)) {
element.classList.remove(c);
}
});
}
function addAnimationClass(element, animation) {
element.classList.add(`animation-${animation}`);
}
}