PK Creative Spring Festival, I am participating in the “Spring Festival Creative Submission contest”, please see:Spring Festival creative Submission contest
introduce
The Spring Festival will come, the Chinese New Year when I was a kid is carefree, the adults will buy a lot of toys to play to us, which is the most bizarre – cloth tiger, cloth tiger feels like nian, again want to altman, for there is a toy big shark bite fingers that we don’t know if you remember it and play with the friend who was bitten to who will be punished, just this year is the year of the tiger, So we will use CSS + JS to combine the two toys and make an ugly ugly cloth tiger toy that can bite your fingers.
What is the final result? Here’s a sneak peek:
Next, we will divide into SCSS drawing tiger parts and pure JS hand biting logic, where you can learn some front-end knowledge such as box-shadow, Boder-radius, animation, animationEnd listening and so on. Are you ready? We’re ready to go
The body of the
1. The HTML structure
<div class="tiger">
<div class="tiger-beard"></div>
<div class="tiger-ear"></div>
<div class="tiger-head">
<div class="tiger-eye left"><span></span></div>
<div class="tiger-eye right"><span></span></div>
<div class="tiger-nose"><span></span><span></span><span></span></div>
<div class="tiger-mouth">
<div>
<div class="tooth">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<div class="tooth down">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
</div>
</div>
</div>
Copy the code
Let’s start by explaining what each part does:
-
Div. tiger: Main container for cloth tigers
-
Div. Tiger-beard: Fuzz around the face
-
Div.tiger-ear: Inside will be a pair of wiggling ears with false elements
-
Div. tiger-head: Face container, nose, eyes, mouth, etc. All done here
2. Draw the outline
$blue: rgb(58.106.179);
$red: rgb(158.14.24);
$yellow: rgb(255.186.13);
$tomato: rgb(194.39.54);
.tiger {
position: relative;
width: 300px;
height: 300px;
.tiger-head {
position: relative;
width: 100%;
height: 85%;
border-radius: 50% 50% 30% 30%;
background-color: $blue;
&::before {
content: "";
display: block;
width: 320px;
height: 120px;
background-color: $yellow;
position: absolute;
bottom: 0px;
left: 50%;
margin-left: -160px;
border-radius: 100px; }}}Copy the code
Before we do this, let’s define four primary colors, and then define the main container of the cloth tiger as 300*300. As for div.tiger-head, fill it with blue, and use the false element before to fill it with yellow to make the lower jaw of the cloth tiger.
3. Paint ears
.tiger-ear {
position: absolute;
width: 100%;
top: -30px;
&::before {
content: "";
left: 10px;
display: block;
position: absolute;
width: 140px;
height: 160px;
border-radius: 0 100% 0 100%;
background-color: $yellow;
transform: rotate(10deg);
animation: ear-left-move .9s infinite alternate linear;
}
&::after {
content: "";
right: 10px;
display: block;
position: absolute;
width: 140px;
height: 160px;
border-radius: 100% 0 100% 0;
background-color: $yellow;
transform: rotate(-10deg);
animation: ear-right-move .9s infinite alternate linear;
}
@keyframes ear-left-move {
0%{
transform: rotate(5deg);
}
100%{
transform: rotate(15deg); }}@keyframes ear-right-move {
0%{
transform: rotate(-15deg);
}
100%{
transform: rotate(-5deg); }}}Copy the code
Two ears? We can imagine it as two petals. This can be drawn directly with border-radius: 0 100% 0 100%.
Using cSS3’s animation, we can create an animation that changes rotate.
Step 4 Paint down
.tiger-beard {
position: absolute;
border-radius: 50%;
width: 110px;
height: 110px;
background-color: transparent;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
box-shadow: -120px 0px 0 $blue.120px 0px 0 $blue.60px 70px 0 $blue, -60px 70px 0 $blue.0px 80px 0 $blue;
}
Copy the code
In fact, it is five blue circles placed around the face. If you are a novice, you may put five divs below to locate the face. However, here we introduce a new method, such as using box-shadow in the code above, you can make the shadow of the ball and control the coordinate position of x and y in front of it.
5. Paint eyes
.tiger-eye {
width: 110px;
height: 110px;
border-radius: 50%;
background-color: $red;
position: absolute;
top: 28px;
display: flex;
align-items: center;
justify-content: center;
transition:.15s transform ease-in;
&.big{
&>span{
transform: scale(1.05); }} & >span {
display: block;
width: 80px;
height: 80px;
box-sizing: border-box;
border-radius: 50%;
border: 10px solid white;
display: flex;
align-items: center;
justify-content: center;
&::after {
content: "";
display: block;
background-color: black;
border-radius: 50%;
width: 30px;
height: 30px; }} &.left {
left: -5px;
border-radius: 0% 50% 50% 50%;
}
&.right {
right: -5px;
border-radius: 50% 0% 50% 50%; }}Copy the code
The eye drawing is relatively simple, which is actually a set of circles. I will not repeat too much here, but I will add a big class in advance to prepare for the bite animation later, because the eyes will be bigger when the bite animation is triggered.
6. Paint your nose
.tiger-nose {
position: absolute;
bottom: 100px;
left: 50%;
width: 70px;
height: 190px;
margin-left: -35px;
background-color: $red;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 100% 100% 0 0;
span {
width: 30px;
height: 30px;
box-sizing: border-box;
display: block;
background-color: white;
border: 10px solid $blue;
border-radius: 50%;
margin: 15% 0;
position: relative;
}
&::before {
content: "";
display: block;
position: absolute;
top: 0;
background-color: $red;
width: 118px;
height: 118px;
border-radius: 0 100% 0 100%;
transform: rotate(45deg); }}Copy the code
The nose is made of red rectangle as the main body and pseudo-elements like the upper part of petals. In order not to show monotony, three dots were added to decorate it. We used an elastic layout and changed the Flex-direction to Column so that the dots would be distributed vertically and regularly.
7. Paint the mouth
.tiger-mouth {
position: absolute;
width: 270px;
height: 80px;
left: 50%;
margin-left: -135px;
border-radius: 15px;
bottom: 20px;
background-color: $red;
display: flex;
align-items: center;
justify-content: center;
& > div {
position: relative;
height: 50px;
width: 85%;
background-color: $tomato;
border-radius: 50px;
overflow: hidden; }}Copy the code
The mouth is simple. We drew a rounded rectangle and ellipse to complete it, and used Flex to center it.
.tooth {
position: absolute;
top: 50%;
margin-top: -30px;
left: 20px;
right: 20px;
display: flex;
justify-content: center;
span {
position: relative;
display: block;
width: 0;
height: 0;
margin: 0 5px;
border-width: 20px 15px;
border-style: solid;
border-color: white transparent transparent transparent;
cursor: pointer;
transition:.2s transform;
&.active{
transform: translateY(-10px); }} &.down {
transform: scaleY(-1);
margin-top: -10px; }}Copy the code
Next, let’s talk about teeth, teeth are small white triangles, the method of drawing here is also simple, the above code border part can achieve a perfect triangle. In addition, we need to make two rows of teeth. Here, if you want to be lazy, you can use the lower teeth instead of one. We will introduce a small technique, which can be achieved by turning the Y-axis of the upper teeth upside down (transform: scaleY(-1)), and of course, we need to fine-tune the distance. As for the addition of an active class, this will serve the js logic of the tooth when we press it later, which is to make it shrink down the Y-axis.
8. Tooth retraction
let $tooth = document.querySelectorAll(".tooth span"); // Get the tooth
let $mouth = document.querySelector(".tiger-mouth>div"); // Get the mouth
let $eye = document.querySelectorAll(".tiger-eye"); // Get the eyes
let activeIndex = -1; // Teeth trigger value
let tigerState = "" // Trigger state
// Execute the initialization event
function initTiger() {
activeIndex = getRandom($tooth);
tigerState = "normal"
}
initTiger()
// Get the random value of tooth trigger
function getRandom(list) {
return ~~(list.length * Math.random());
}
// Bite action
function handleBite() {}
// Bind the tooth trigger event
$tooth.forEach((el, index) = > {
el.addEventListener("click".e= > {
const { target } = e;
if (target.classList.value == "active" || tigerState == "active") return;
if (activeIndex == index) return handleBite()
target.classList.add('active')})})Copy the code
The business logic here is very simple, basically, to initialize the current state tigerState to normal, and then change it to active to trigger the tooth button so that it can no longer click the tooth button. Of course, we also need to randomly obtain an activeIndex as the trigger value of our tooth mechanism. When the subscript of the tooth is the same as the trigger value, the bite action will be triggered, indicating the end of the game. Of course, if the trigger is not triggered, pressing a tooth will attach the CSS active class to the tooth to make it sink, indicating that it is safe.
9. Bite action
.tiger-mouth{& >div{&.bite{
animation: bite-mouth .75s ease-in;
span{
animation: bite-tooth .85sease-in; }}@keyframes bite-mouth {
0%,100%{
height: 50px;
}
50%{
height: 10px; }}@keyframes bite-tooth {
0%,100%{
top: 0;
}
50%{
top: 10px; }}}}Copy the code
// Bite action
function handleBite() {
$tooth.forEach(el => el.classList.remove('active')) // Restore the tooth
$eye.forEach(el=>el.classList.add("big")) // Eyes widen
tigerState = "active"; // Change the state
$mouth.classList.add("bite") // Add occlusal animation
}
Copy the code
The bite animation here is mainly completed by cSS3 animation. At the same time, we need to immediately restore the pressed teeth and make the eyes wide, and then we need to write the animation (i.e., the up and down changes of lips and teeth). When the bite event is triggered, the bite will be automatically executed once. Of course, we also need to change the status of the tiger to active (i.e., tigerState->”active”), so the tooth will not let you click. Of course, there is another solution that can be implemented without writing JS. For example, adding pointer-events: None to a BITE using CSS could easily do the same.
And then finally, we’re going to reuse it to make sure that the next turn, the tooth is back to its initial state, and then we’re going to listen for the end of the bite animation and initialize it.
$mouth.addEventListener("animationend".() = > {
$mouth.classList.remove("bite") // Remove the bite animation
$eye.forEach(el= >el.classList.remove("big"))
initTiger();
})
Copy the code
The animationEnd event is an event that listens to the CSS animation trigger. It can accurately detect when the CSS3 animation is over. No need to use setTimeout timer to trigger. But there are also some disadvantages, that is, compatibility is not so good, we only do the effect display on Google, if partners want better compatibility or use timer to judge.
conclusion
We’re done here, and I wonder if this ugly cloth tiger toy takes you back to your childhood.
For this animation, you can find the demo and code on my Codepen.
This period is based on and animation creative, mainly is the novice to, bosses do not spray, often with CSS and js write about animation is interesting, after all, every day to write business code is too boring, not only can these familiar with CSS and js background, the more creative, and will burst into your own learning style, is also a kind of exercise practice, together with progress, Finally, I wish you all a happy year of the Tiger