5个前端练手项目(html css js canvas)

Posted 言不及行yyds

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5个前端练手项目(html css js canvas)相关的知识,希望对你有一定的参考价值。

 前言:

首先祝大家端午节快乐。本篇文章有5个练手项目
对于刚学完前端三剑客的你们。应该是一个很好的实践

目录

🥩.跑马灯

1.1效果图:

1.2思路解析

1.3源码

🍧.彩虹爱心

2.1效果图

2.2思路解析

2.3源码

🌮.闹钟

3.1效果图

3.2思路解析

3.3源码

🍲.自制笔记本

4.1效果展示

4.2思路解析

4.3源码

🍣.自定义写字台(也可自定义字的样式)

5.1效果展示

 5.2思路解析

5.3源码



1.跑马灯

1.1效果图:


1.2思路解析

在这个项目中,在html中创立20个span标签

每个span标签设置style为--i:数字的样式用于

在css中动态分配圆圈分几份,transform: rotate(calc(18deg*var(--i)))

利用filter属性结合关键帧动态切换颜色。同时设置每一个span标签进行

旋转


1.3源码

<style>
	* 
	padding: 0;
	margin: 0;
	box-sizing: border-box;
	
main
	display: flex;
    background-color: #2c3a47;
	/*用于设置图像居中 */
	align-items: center;
	justify-content: center;
	width: 1920px;
	height: 1000px;
	animation: animate1 10s linear infinite;
	
/* 用于设置动画属性 其中filter用于做利镜其中的hue-rotate属性让图像运用色相旋转*/
@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%;
	/* 用于设置一个圆圈被分成几份 */
	transform: rotate(calc(18deg*var(--i)));
	
	/* :before用于设置在给定的属性之前添加效果 */
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.彩虹爱心


2.1效果图


2.2思路解析

搭建基本的html结构,采用的svg技术

通过js动态改变颜色,以及动态实现切换图形


2.3源码

<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.闹钟


3.1效果图


3.2思路解析

搭建基本的html结构,动态得到实时的时,分,秒

通过Date()函数获得。将得到的数字根据逻辑,绑定

给各div结构,实行动态旋转。点击按钮,改变背景颜色


3.3源码

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.自制笔记本


4.1效果展示


4.2思路解析

通过js实现动态添加DOM结构,绑定创建出DOM结构的

添加,删除按钮。实现监听事件。实现动态改变DOM结构

其他的就是设置css的相关属性,


4.3源码

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.自定义写字台(也可自定义字的样式)


5.1效果展示


 5.2思路解析

搭建html结构,创建canvas标签

绑定设置的结构比如+,-,颜色改变

动态设置并获取他的值,然后将这些值动态的

设置为canvas语法中设置渲染的宽度,以及设置

颜色的属性


5.3源码

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))

✍在最后,如果觉得博主写的还行,期待🍟点赞  🍬评论 🍪收藏

以上是关于5个前端练手项目(html css js canvas)的主要内容,如果未能解决你的问题,请参考以下文章

2022最新版40个前端练手项目附视频+源码

前端练手项目合集40.0个,附源码,2022年最新

原生js,面向过程的方法,写个选项卡练练手

黑马程序员前端-CSS练手之学成在线页面制作

学了半年前端,基本的html+css+js都会了,有没有啥好的项目可以当案例做的。

618快到了送上自制前端小项目(html css js)