5 front-end practice projects (html css js canvas)

Foreword:

First of all, I wish everyone a happy Dragon Boat Festival. There are 5 exercises in this article
For those of you who just finished learning the front-end Three Musketeers. should be a good practice

Table of contents

?. Marquee

1.1 renderings:

1.2 Analysis of ideas

1.3 Source code

?.Rainbow Heart

2.1 Rendering

2.2 Analysis of ideas

2.3 Source code

?.Alarm clock

3.1 Rendering

3.2 Analysis of ideas

3.3 Source code

?. Homemade Notebook

4.1 Effect display

4.2 Analysis of ideas

4.3 Source code

?.Custom writing desk (you can also customize the style of the word)

5.1 Effect display

5.2 Analysis of ideas

5.3 Source code



1. Marquee

1.1 renderings:


1.2 Analysis of ideas

In this project, inhtml中创立20个span标签

per span tag settingstyle为–i:The style of the numbers is used for

Dynamically allocate several parts of the circle in css, transform: rotate(calc(18deg*var(–i)))

usefilter property combined with keyframesDynamically switch colors. Set each span tag at the same time

to rotate


1.3 Source code

<style>
	* {
	padding: 0;
	margin: 0;
	box-sizing: border-box;
	}
main{
	display: flex;
    background-color: #2c3a47;
	/* used to set the center of the image */
	align-items: center;
	justify-content: center;
	width: 1920px;
	height: 1000px;
	animation: animate1 10s linear infinite;
	}
/* Used to set the animation properties where the filter is used to make a sharp mirror and the hue-rotate property allows the image to use hue rotation*/
@keyframes animate1 {
	0% {
		filter: hue-rotate(0deg);
		}
	100% {
		filter: hue-rotate(360deg);
			}
		}
main .cube {
		position: relative;
		height: 120px;
		width: 120px;
	    }
main .cube span {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	/* Used to set a circle to be divided into several parts */
	transform: rotate(calc(18deg*var(--i)));
	}
	/* :before is used to set the effect before the given property */
main .cube span::before {
		content: '';
		position: absolute;
		top: 0;
		left: 0;
		width: 15px;
		height: 15px;
		border-radius: 50%;
		background-color: aqua;
		box-shadow: 0 0 10px aqua ,0 0 20px aqua,0 0 40px aqua,0 0 80px aqua,0 0 100px aqua;
animation: animate 2s linear infinite;
		animation-delay: calc(0.1s*var(--i));
		}
@keyframes animate {
	0% {
		transform: scale(1);
		}
	80%,
	100% {
	    transform: scale(0);
		}
	}
.loading{
		color:#fff;
		font-size: 20px;
		position: relative;
		top:100px;
		right:100px;
          }
@media (min-width:765px){ 
			
	}

</style>
</head>
<body>
<main>
<div class="cube">
	<span style="--i:1;"></span>
	<span style="--i:2;"></span>
    <span style="--i:3;"></span>
	<span style="--i:4;"></span>
	<span style="--i:5;"></span>
	<span style="--i:6;"></span>
	<span style="--i:7;"></span>
	<span style="--i:8;"></span>
	<span style="--i:9;"></span>
	<span style="--i:10;"></span>
	<span style="--i:11;"></span>
	<span style="--i:12;"></span>
	<span style="--i:13;"></span>
	<span style="--i:14;"></span>
	<span style="--i:15;"></span>
	<span style="--i:16;"></span>
	<span style="--i:17;"></span>
	<span style="--i:18;"></span>
	<span style="--i:19;"></span>
	<span style="--i:20;"></span>
</div>
<div class="loading">
    <p>loading</p>
</div>
</main>
</body>

2. Rainbow Love


2.1 Rendering


2.2 Analysis of ideas

Build the basic html structure, usingsvg技术

Dynamically via jschange color, and the dynamic implementation of switching graphics


2.3 Source code

<svg id="hearts" viewBox="-600 -400 1200 800" preserveAspectRatio="xMidYMid slice">
  
<defs>
    
<symbol  id="heart" viewBox="-69 -16 138 138">
    
<path d="M0,12
         C 50,-30 110,50  0,120
         C-110,50 -50,-30 0,12z"/>
    
</symbol>

</defs>

</svg>


const colors = ["#e03776","#8f3e98","#4687bf","#3bab6f","#f9c25e","#f47274"];
const SVG_NS = 'http://www.w3.org/2000/svg';
const SVG_XLINK = "http://www.w3.org/1999/xlink";

let heartsRy = []

function useTheHeart(n){
  let use = document.createElementNS(SVG_NS, 'use');
  use.n = n;
  use.setAttributeNS(SVG_XLINK, 'xlink:href', '#heart');
  use.setAttributeNS(null, 'transform', `scale(${use.n})`);
  use.setAttributeNS(null, 'fill', colors[n%colors.length]);
  use.setAttributeNS(null, 'x', -69);
  use.setAttributeNS(null, 'y', -69);
  use.setAttributeNS(null, 'width', 138);
  use.setAttributeNS(null, 'height', 138);
  
  heartsRy.push(use)
  hearts.appendChild(use);
}

for(let n = 18; n >= 0; n--){useTheHeart(n)}

function Frame(){
  window.requestAnimationFrame(Frame);
  for(let i = 0; i < heartsRy.length; i++){
    if(heartsRy[i].n < 18){heartsRy[i].n +=.01
     }else{
     heartsRy[i].n = 0;
     hearts.appendChild(heartsRy[i])
    }
    heartsRy[i].setAttributeNS(null, 'transform', `scale(${heartsRy[i].n})`);
  }
}

Frame()

3. Alarm clock


3.1 Rendering


3.2 Analysis of ideas

Build the basic html structure,动态得到实时的时,分,秒

Obtained by the Date() function. will get the numbers according to the logic,绑定

给各div结构, perform dynamic rotation. Click the button to change背景颜色


3.3 Source code

html:

<body>
  <button class="toggle">Dark mode</button>
 <div class="clock-container">
   <div class="clock">
     <div class="needle hour"></div>
     <div class="needle minute"></div>
     <div class="needle second"></div>
     <div class="center-point"></div>
   </div>
      <div class="time"></div>
      <div class="date"></div>
  </div>
</body>

css:

@import url('https://fonts.googleapis.com/css?family=Heebo:300&display=swap');

* {
  box-sizing: border-box;
}

:root {
  --primary-color: #000;
  --secondary-color: #fff;
}

html {
  transition: all 0.5s ease-in;
}

html.dark {
  --primary-color: #fff;
  --secondary-color: #333;
}

html.dark {
  background-color: #111;
  color: var(--primary-color);
}

body {
  font-family: 'Heebo', sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  overflow: hidden;
  margin: 0;
}

.toggle {
  cursor: pointer;
  background-color: var(--primary-color);
  color: var(--secondary-color);
  border: 0;
  border-radius: 4px;
  padding: 8px 12px;
  position: absolute;
  top: 100px;
}

.toggle:focus {
  outline: none;
}

.clock-container {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
}

.clock {
  position: relative;
  width: 200px;
  height: 200px;
}

.needle {
  background-color: var(--primary-color);
  position: absolute;
  top: 50%;
  left: 50%;
  height: 65px;
  width: 3px;
  transform-origin: bottom center;
  transition: all 0.5s ease-in;
}

.needle.hour {
  transform: translate(-50%, -100%) rotate(0deg);
}

.needle.minute {
  transform: translate(-50%, -100%) rotate(0deg);
  height: 100px;
}

.needle.second {
  transform: translate(-50%, -100%) rotate(0deg);
  height: 100px;
  background-color: #e74c3c;
}

.center-point {
  background-color: #e74c3c;
  width: 10px;
  height: 10px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}

.center-point::after {
  content: '';
  background-color: var(--primary-color);
  width: 5px;
  height: 5px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  border-radius: 50%;
}

.time {
  font-size: 60px;
}

.date {
  color: #aaa;
  font-size: 14px;
  letter-spacing: 0.3px;
  text-transform: uppercase;
}

.date .circle {
  background-color: var(--primary-color);
  color: var(--secondary-color);
  border-radius: 50%;
  height: 18px;
  width: 18px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 18px;
  transition: all 0.5s ease-in;
  font-size: 12px;
}

js:

const hourEl = document.querySelector('.hour')
const minuteEl = document.querySelector('.minute')
const secondEl = document.querySelector('.second')
const timeEl = document.querySelector('.time')
const dateEl = document.querySelector('.date')
const toggle = document.querySelector('.toggle')

const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

toggle.addEventListener('click', (e) => {
    const html = document.querySelector('html')
    if (html.classList.contains('dark')) {
        html.classList.remove('dark')
        e.target.innerHTML = 'Dark mode'
    } else {
        html.classList.add('dark')
        e.target.innerHTML = 'Light mode'
    }
})

function setTime() {
    const time = new Date();
    const month = time.getMonth()
    const day = time.getDay()
    const date = time.getDate()
    const hours = time.getHours()
    const hoursForClock = hours >= 13 ? hours % 12 : hours;
    const minutes = time.getMinutes()
    const seconds = time.getSeconds()
    const ampm = hours >= 12 ? 'PM' : 'AM'

    hourEl.style.transform = `translate(-50%, -100%) rotate(${scale(hoursForClock, 0, 12, 0, 360)}deg)`
    minuteEl.style.transform = `translate(-50%, -100%) rotate(${scale(minutes, 0, 60, 0, 360)}deg)`
    secondEl.style.transform = `translate(-50%, -100%) rotate(${scale(seconds, 0, 60, 0, 360)}deg)`

    timeEl.innerHTML = `${hoursForClock}:${minutes < 10 ? `0${minutes}` : minutes} ${ampm}`
    dateEl.innerHTML = `${days[day]}, ${months[month]} <span class="circle">${date}</span>`
}

// StackOverflow https://stackoverflow.com/questions/10756313/javascript-jquery-map-a-range-of-numbers-to-another-range-of-numbers
const scale = (num, in_min, in_max, out_min, out_max) => {
    return (num - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

setTime()

setInterval(setTime, 1000)


4. Homemade Notebook


4.1 Effect display


4.2 Analysis of ideas

Implemented by js动态添加DOM结构, the bindings that create the DOM structure

Add, remove buttons.Implement listener events. Implement dynamic changes to the DOM structure

The other is to set the relevant properties of css,


4.3 Source code

html:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" />
  </head>
  <body>
    <button class="add" id="add">
      <i class="fas fa-plus"></i> Add note
    </button>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.2.2/marked.min.js"></script>

  </body>

 css:

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@200;400&display=swap');

* {
  box-sizing: border-box;
  outline: none;
}

body {
  background-color: #7bdaf3;
  font-family: 'Poppins', sans-serif;
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  padding-top: 3rem;
}

.add {
  position: fixed;
  top: 1rem;
  right: 1rem;
  background-color: #9ec862;
  color: #fff;
  border: none;
  border-radius: 3px;
  padding: 0.5rem 1rem;
  cursor: pointer;
}

.add:active {
  transform: scale(0.98);
}

.note {
  background-color: #fff;
  box-shadow: 0 0 10px 4px rgba(0, 0, 0, 0.1);
  margin: 30px 20px;
  height: 400px;
  width: 400px;
  overflow-y: scroll;
}

.note .tools {
  background-color: #9ec862;
  display: flex;
  justify-content: flex-end;
  padding: 0.5rem;
}

.note .tools button {
  background-color: transparent;
  border: none;
  color: #fff;
  cursor: pointer;
  font-size: 1rem;
  margin-left: 0.5rem;
}

.note textarea {
  outline: none;
  font-family: inherit;
  font-size: 1.2rem;
  border: none;
  height: 400px;
  width: 100%;
  padding: 20px;
}

.main {
  padding: 20px;
}

.hidden {
  display: none;
}

js:

const addBtn = document.getElementById('add')

const notes = JSON.parse(localStorage.getItem('notes'))

if(notes) {
    notes.forEach(note => addNewNote(note))
}

addBtn.addEventListener('click', () => addNewNote())

function addNewNote(text = '') {
    const note = document.createElement('div')
    note.classList.add('note')

    note.innerHTML = `
    <div class="tools">
        <button class="edit"><i class="fas fa-edit"></i></button>
        <button class="delete"><i class="fas fa-trash-alt"></i></button>
    </div>

    <div class="main ${text ? "" : "hidden"}"></div>
    <textarea class="${text ? "hidden" : ""}"></textarea>
    `

    const editBtn = note.querySelector('.edit')
    const deleteBtn = note.querySelector('.delete')
    const main = note.querySelector('.main')
    const textArea = note.querySelector('textarea')

    textArea.value = text
    main.innerHTML = marked(text)

    deleteBtn.addEventListener('click', () => {
        note.remove()

        updateLS()
    })

    editBtn.addEventListener('click', () => {
        main.classList.toggle('hidden')
        textArea.classList.toggle('hidden')
    })

    textArea.addEventListener('input', (e) => {
        const { value } = e.target

        main.innerHTML = marked(value)

        updateLS()
    })

    document.body.appendChild(note)
}

function updateLS() {
    const notesText = document.querySelectorAll('textarea')

    const notes = []

    notesText.forEach(note => notes.push(note.value))

    localStorage.setItem('notes', JSON.stringify(notes))
}

5. Customize the writing desk (you can also customize the style of the word)


5.1 Effect display


5.2 Analysis of ideas

build html structure,创建canvas标签

The structure of binding settings such as +, -, color change

动态设置and get his values, then put these values ​​dynamically

Set to canvas syntaxrenderwidth, and set

properties of color


5.3 Source code

html:

<canvas id="canvas" width="800" height="700"></canvas>
 <div class="toolbox">
<button id="decrease">-</button>
 <span id="size">10</span>
 <button id="increase">+</button>
 <input type="color" id="color">
 <button id="clear">X</button>
</div>

css:

@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');

* {
  box-sizing: border-box;
}

body {
  background-color: #f5f5f5;
  font-family: 'Roboto', sans-serif;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100vh;
  margin: 0;
}

canvas {
  border: 2px solid steelblue;
}

.toolbox {
  background-color: steelblue;
  border: 1px solid slateblue;
  display: flex;
  width: 804px;
  padding: 1rem;
}

.toolbox > * {
  background-color: #fff;
  border: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 2rem;
  height: 50px;
  width: 50px;
  margin: 0.25rem;
  padding: 0.25rem;
  cursor: pointer;
}

.toolbox > *:last-child {
  margin-left: auto;
}

js:

const canvas = document.getElementById('canvas');
const increaseBtn = document.getElementById('increase');
const decreaseBtn = document.getElementById('decrease');
const sizeEL = document.getElementById('size');
const colorEl = document.getElementById('color');
const clearEl = document.getElementById('clear');

const ctx = canvas.getContext('2d');

let size = 10
let isPressed = false
colorEl.value = 'black'
let color = colorEl.value
let x
let y

canvas.addEventListener('mousedown', (e) => {
    isPressed = true

    x = e.offsetX
    y = e.offsetY
})

document.addEventListener('mouseup', (e) => {
    isPressed = false

    x = undefined
    y = undefined
})

canvas.addEventListener('mousemove', (e) => {
    if(isPressed) {
        const x2 = e.offsetX
        const y2 = e.offsetY

        drawCircle(x2, y2)
        drawLine(x, y, x2, y2)

        x = x2
        y = y2
    }
})

function drawCircle(x, y) {
    ctx.beginPath();
    ctx.arc(x, y, size, 0, Math.PI * 2)
    ctx.fillStyle = color
    ctx.fill()
}

function drawLine(x1, y1, x2, y2) {
    ctx.beginPath()
    ctx.moveTo(x1, y1)
    ctx.lineTo(x2, y2)
    ctx.strokeStyle = color
    ctx.lineWidth = size * 2
    ctx.stroke()
}

function updateSizeOnScreen() {
    sizeEL.innerText = size
}

increaseBtn.addEventListener('click', () => {
    size += 5

    if(size > 50) {
        size = 50
    }

    updateSizeOnScreen()
})

decreaseBtn.addEventListener('click', () => {
    size -= 5

    if(size < 5) {
        size = 5
    }

    updateSizeOnScreen()
})

colorEl.addEventListener('change', (e) => color = e.target.value)

clearEl.addEventListener('click', () => ctx.clearRect(0,0, canvas.width, canvas.height))

✍At the end, if you think the blogger’s writing is okay, look forward to like it, comment, favorite

Related Posts

Mysql 8.0.28 version installation and configuration method graphic tutorial

A small CSS effect every day, the text flashes——[Iron Man: Love You Three Thousand Times]

[CSS] Box Model

Learn WEB front-end from scratch – HTML theory explanation

Jiandaoyun – a flexible and easy-to-use application building platform

Web project actual combat (simple implementation of shopping mall project)

A small CSS effect every day, the text flickers——[Iron Man: Love You Three Thousand Times]

[Crazy World Cup] css animation to achieve beating football

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*