3D个人简历网站 1.准备工作
获取资料,关注微信公众号“90后小陈老师”,回复“Web3D”
技术栈:React+React-three-fiber (three.js)+Tailwind CSS
Vite搭建React结构
Vite 是一个由 Vue.js 作者尤雨溪开发的新一代前端构建工具。它的名字来源于法语中的“快速”(vite),旨在提供更快的开发环境启动速度和热更新速度。Vite 利用了现代浏览器对 ES 模块的支持,允许开发者在开发过程中直接使用原生 JavaScript 模块导入导出功能,而不需要打包整个应用。这种方式显著减少了开发服务器的启动时间,并且提供了即时的代码更新反馈。
使用Vite快速搭建项目主体结构
# 创建项目结构(React、JavaScript)
npm create vite@latest
# 安装对应包
npm install
# 运行项目
npm run dev
清空src文件下所有文件
src下新建main.jsx
JSX 是 JavaScript 的语法扩展,全称为 JavaScript XML。它结合了 JavaScript 与 XML 语法,让开发者能在 JavaScript 代码里更直观地编写类似 HTML 的结构,常被用于 React 项目。
import ReactDom from 'react-dom';//导入react-dom库
ReactDom.createRoot(document.getElementById('root')).render(<App/>);//将App组件渲染到页面上
src下新建App.jsx
安装插件ES7+ React/Redux/React-Native snippets
rafce
import React from 'react'
const App = () => {
return (
<div>App</div>
)
}
export default App
main.jsx新增代码
import ReactDom from 'react-dom/client';//导入react-dom/client模块
import App from './App';//导入App组件
ReactDom.createRoot(document.getElementById('root')).render(<App/>);//将App组件渲染到页面上
Tailwind CSS
Tailwind CSS 是一个高度可定制的、低级(low-level)CSS 框架,它提供了一组预定义的 CSS 类,这些类可以直接在 HTML 中使用,以快速构建自定义设计。与传统的 CSS 框架如 Bootstrap 不同,Tailwind CSS 更注重于提供灵活的基础工具,而不是预先设计好的组件样式。这意味着开发者可以利用 Tailwind 提供的大量实用程序类来自由地创建独特的布局和风格,而不需要编写额外的 CSS 代码。
https://www.tailwindcss.cn/docs/guides/vite
npm install -D tailwindcss@3.4.17 postcss autoprefixer
npx tailwindcss init -p
生成tailwind.config.js
和 postcss.config.js
文件
修改tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
gray: {
200: "#D5DAE1"
},
black: {
DEFAULT: "#000",
500: "#1D2235"
},
blue: {
500: "#2b77e7"
}
},
fontFamily: {
worksans: ["Work Sans", "sans-serif"],
poppins: ['Poppins', "sans-serif"]
},
boxShadow: {
card: '0px 1px 2px 0px rgba(0, 0, 0, 0.05)'
}
},
},
plugins: [],
}
src下新增index.css
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@100;200;300;400;500;600;700;800;900&family=Work+Sans:wght@100;200;300;400;500;600;700;800;900&display=swap");
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--blue-rgb: 237 245 255;
--green-rgb: 125 161 35;
}
body {
font-family: "Work Sans", sans-serif;
}
body:has(.card[data-color="blue"]:hover) {
background-color: rgb(var(--blue-rgb) / 25%);
}
body:has(.card[data-color="green"]:hover) {
background-color: rgb(var(--green-rgb) / 25%);
}
@layer utilities {
.max-container {
@apply max-w-5xl mx-auto sm:p-16 pb-12 !pt-[126px] px-8 min-h-[calc(100vh-80px)];
}
.head-text {
@apply sm:text-5xl text-3xl font-semibold sm:leading-snug font-poppins;
}
.subhead-text {
@apply font-semibold sm:text-3xl text-xl relative font-poppins;
}
.blue-gradient_text {
@apply bg-gradient-to-r from-[#00c6ff] to-[#0072ff] bg-clip-text text-transparent;
}
.input {
@apply bg-white border border-gray-200 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 mt-2.5 font-normal shadow-card;
}
.textarea {
@apply block p-2.5 w-full text-sm text-gray-900 bg-white rounded-lg border border-gray-200 focus:ring-blue-500 focus:border-blue-500 mt-2.5 font-normal shadow-card;
}
.btn {
@apply text-white bg-gradient-to-r from-[#00c6ff] to-[#0072ff] focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center;
}
.header {
@apply flex justify-between items-center sm:px-16 px-8 py-4 max-w-5xl mx-auto absolute top-0 bg-transparent z-10 right-0 left-0;
}
.footer {
@apply max-w-5xl mx-auto sm:px-16 pb-6 px-8 flex flex-col gap-7;
}
.footer-container {
@apply flex flex-wrap gap-7 items-center justify-between;
}
.info-box {
@apply mx-5 relative flex text-white flex-col gap-3 max-w-2xl neo-brutalism-blue pt-4 pb-12 px-8;
}
.neo-btn {
@apply py-3 px-6 rounded-lg text-blue-500 text-center font-semibold sm:w-1/2 w-[90%] -bottom-5 absolute mx-auto right-0 left-0 flex justify-center items-center gap-3;
}
.cta {
@apply w-full flex items-center md:flex-row flex-col sm:mt-16 mt-8 gap-7;
}
.cta-text {
@apply text-black-500 font-extrabold flex-1 text-3xl max-md:text-center;
}
}
.glassmorphism {
background: rgba(8, 116, 239, 0.07);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.18);
}
.logo {
border-radius: 8.889px;
background: #fff;
box-shadow: 0px 10px 35px -4px rgba(67, 83, 255, 0.15),
0px 1.5px 4px -1px rgba(67, 83, 255, 0.2);
}
.block-container {
position: relative;
transition: 250ms;
perspective: 500px;
}
.block-container .btn-back {
position: absolute;
inset: 0;
z-index: -1;
width: inherit;
height: inherit;
transition: 250ms;
transform-style: preserve-3d;
transform-origin: bottom right;
transform: rotateZ(15deg);
will-change: transform;
box-shadow: 16px 0 40px #e4e4e4;
}
.block-container .btn-back-red {
background: linear-gradient(135deg, #ff4b1f -20%, #ff9068 120%);
}
.block-container .btn-back-green {
background: linear-gradient(135deg, #adfda2 -20%, #11d3f3 120%);
}
.block-container .btn-back-yellow {
background: linear-gradient(135deg, #f7971e -20%, #ffd200 120%);
}
.block-container .btn-back-blue {
background: linear-gradient(135deg, #0061ff -20%, #60efff 120%);
}
.block-container .btn-back-orange {
background: linear-gradient(135deg, #ff0f7b -20%, #f89b29 120%);
}
.block-container .btn-back-pink {
background: linear-gradient(135deg, #e81cff -20%, #40c9ff 120%);
}
.block-container .btn-back-black {
background: linear-gradient(135deg, #0a1647 -20%, #e4e7e4 120%);
}
.block-container .btn-front {
position: absolute;
inset: 0;
z-index: 1;
width: inherit;
height: inherit;
background-color: #ffffff33;
-webkit-backdrop-filter: blur(20px);
backdrop-filter: blur(20px);
transition: 250ms;
transform-style: preserve-3d;
transform-origin: top left;
overflow: hidden;
}
.block-container:hover > .btn-back {
transform: translateZ(20px) rotateZ(15deg) rotateX(-20deg) rotateY(-20deg);
}
.block-container:hover > .btn-front {
transform: translateZ(80px) translateY(-5px) rotateX(15deg) rotateY(15deg);
}
/* Neo Brutalism */
.neo-brutalism-blue {
background: #2b77e7;
position: relative;
border-radius: 10px;
border: #2b77e7;
box-shadow: 0.6vmin 0.6vmin #336cc1, 1vmin 1vmin #0092db, 1vmin 1vmin #0092db,
0.65vmin 1vmin #0092db, 1vmin 0.65vmin #0092db;
}
.neo-brutalism-white {
background: #fff;
border: #fff;
box-shadow: 0.6vmin 0.6vmin #fff, 1vmin 1vmin #d2e4ff, 1vmin 1vmin #d2e4ff,
0.65vmin 1vmin #d2e4ff, 1vmin 0.65vmin #d2e4ff;
}
安装插件Tailwind CSS IntelliSense
实现初步效果
main.jsx中引入index.css
import ReactDom from 'react-dom/client';//导入react-dom/client模块
import App from './App';//导入App组件
import './index.css';//导入index.css文件
ReactDom.createRoot(document.getElementById('root')).render(<App/>);//将App组件渲染到页面上
修改App.jsx实现文字变成红色下划线
import React from 'react'
const App = () => {
return (
<h1 className="text-3xl font-bold underline text-red-500">
Hello world!
</h1>
)
}
export default App
Reference:
https://www.youtube.com/watch?v=FkowOdMjvYo
https://github.com/adrianhajdin/3D_portfolio/tree/main?tab=readme-ov-file