react模仿iphone14灵动岛ui交互设计效果代码
代码语言:html
所属分类:布局界面
代码描述:react模仿iphone14灵动岛ui交互设计效果代码,包含消息提示、视频小窗播放、电池余量提醒、loading加载动画等。
代码标签: react 模仿 iphone14 灵动岛 ui 交互 设计
下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开
<!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <style> @import 'https://unpkg.com/open-props/open-props.min.css'; @import 'https://unpkg.com/open-props/normalize.min.css'; main { display: grid; place-items: center; min-height: 100vh; background: var(--gradient-11); } button { padding: var(--size-2) var(--size-4); border-radius: var(--radius-3); } .dynamic-island { --height: 36px; --font-size: calc(var(--height) * 0.35); --camera-size: calc(3.6 * var(--height)); position: fixed; top: var(--size-4); left: 50%; transform: translateX(-50%); /*min-width: var(--size-10);*/ min-height: var(--height); transition: all 0.2s ease; display: inline-flex; /*gap: var(--size-4);*/ justify-content: center; align-items: center; font-size: var(--font-size-1); font-size: var(--font-size); color: var(--gray-0); /*background: grey;*/ /*opacity: 0.5;*/ display: grid; align-items: center; grid-template-columns: var(--auxiliary-width, 1fr) var(--camera-size) var(--auxiliary-width, 1fr); grid-template-rows: var(--height) 1fr; } @media(min-width: 768px) { .dynamic-island { --height: 50px; } } .dynamic-island:after { content: ""; min-height: var(--height); position: absolute; top: 0; left: 50%; transform: translate(-50%, 0) scaleX(var(--scale-x, 1)); border-radius: calc(var(--font-size) + var(--size-2)); min-width: var(--camera-size); width: calc(var(--width-imposed, 40) * 1px); height: calc(var(--height-imposed, 40) * 1px); background: var(--gray-9); transition: width 0.2s var(--ease-elastic-2), height 0.2s var(--ease-elastic-2); z-index: -1; /*opacity: 0.8;*/ } .dynamic-island__media { display: flex; -webkit-animation: enter-media 0.2s 0.1s both; animation: enter-media 0.2s 0.1s both; white-space: nowrap; } .dynamic-island__stage--camera { width: var(--camera-size); display: flex; justify-content: flex-end; padding-right: var(--size-4); } .dynamic-island__lens { height: calc(var(--height) * 0.5); opacity: 0.5; aspect-ratio: 1; } .dynamic-island__stage--center { grid-column: 1 / -1; display: grid; place-items: center; width: 100%; max-width: 100%; overflow: hidden; } #player { max-width: 100%; width: 100%; height: auto; aspect-ratio: 16 / 9; } .dynamic-island__center { padding: var(--size-4); -webkit-animation: enter-info 0.2s 0.1s both; animation: enter-info 0.2s 0.1s both; width: 100%; } .dynamic-island__info { padding-left: var(--size-4); white-space: nowrap; -webkit-animation: enter-info 0.2s 0.1s both; animation: enter-info 0.2s 0.1s both; } .dynamic-island__media { padding-right: var(--size-4); display: flex; justify-content: flex-end; } @-webkit-keyframes enter-info { from { opacity: 0; } } @keyframes enter-info { from { opacity: 0; } } @-webkit-keyframes enter-media { from { transform: scale(0); } } @keyframes enter-media { from { transform: scale(0); } } .template { display: none; position: fixed; opacity: 0.2; transform: translate(0, -19%); } .battery { display: flex; } .globe { display: inline-block; position: relative; } .globes { position: relative; overflow: hidden; -webkit-clip-path: inset(0 0 0 0); clip-path: inset(0 0 0 0); } .battery__icon--lightning { display: inline-block; -webkit-animation: lightning 1s infinite; animation: lightning 1s infinite; } @-webkit-keyframes lightning { 0%, 10%, 20% { transform: skew(15deg); } 5%, 15%, 25% { transform: skew(-15deg); } 30%, 100% { transform: skew(0deg); } } @keyframes lightning { 0%, 10%, 20% { transform: skew(15deg); } 5%, 15%, 25% { transform: skew(-15deg); } 30%, 100% { transform: skew(0deg); } } .globes__placeholder { color: transparent; } .loader { height: calc(var(--height) * 0.6); aspect-ratio: 1; position: relative; display: grid; place-items: center; -webkit-animation: load 1s infinite steps(var(--count)); animation: load 1s infinite steps(var(--count)); } @-webkit-keyframes load { to { transform: rotate(360deg); } } @keyframes load { to { transform: rotate(360deg); } } .loader > span { width: 25%; height: 10%; background: white; position: absolute; transform: rotate(calc((360 / var(--count)) * var(--index) * 1deg)) translateX(150%); opacity: calc(1 / var(--count) * var(--index)); } .globes__translater { position: absolute; top: 50%; left: 0; display: inline-block; transform: translate(0, -50%); white-space: nowrap; -webkit-animation: globe-spin 0.5s infinite both steps(3); animation: globe-spin 0.5s infinite both steps(3); } @-webkit-keyframes globe-spin { to { transform: translate(-100%, -50%); } } @keyframes globe-spin { to { transform: translate(-100%, -50%); } } </style> </head> <body > <div id="app"></div> <main> <div class="controls"> <button class="hello">Hello</button> <button class="charge">Battery</button> <button class="loading">Loading</button> <button class="youtube">Media</button> </div> </main> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/babel.7.18.13.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/react.production.16.13.js"></script> <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/react-dom.production.16.13.js"></script> <script type="text/babel"> const ROOT = document.getElementById('app') const DynamicIsland = () => { const timerRef = React.useRef(null) const islandRef = React.useRef(null) const mediaRef = React.useRef(null) const infoRef = React.useRef(null) const centerRef = React.useRef(null) const scaleRef = React.useRef(null) const cbRef = React.useRef(null) const [info, setInfo] = React.useState(null) const [media, setMedia] = React.useState(null) const [box, setBox] = React.useState(null) React.useEffect(() => { const winddown = () => { const anims = [] if (mediaRef.current) anims.push(mediaRef.current.animate({ scale: 0 }, { duration: 200, fill: 'forwards' }).finished) if (infoRef.current) anims.push(infoRef.current.animate({ opacity: 0, }, { duration: 200, fill: 'forwards' }).finished) if (centerRef.current) anims.push(centerRef.current.animate({ opacity: 0, }, { duration: 200, fill: 'forwards' }).finished) if (anims.length) { Promise.all(anims).then(() => { setInfo(null) setMedia(null) setBox(null) }) } } const processIsland = ({ detail: { box, info, media, timeout, cb, nuke } }) => { if (nuke) return winddown() setInfo(info) setMedia(media) setBox(box) cbRef.current = cb if (timeout) { if (timerRef.current) clearTimeout(timerRef.current) timerRef.current = setTimeout(winddown, timeout) } } document.body.addEventListener('island:event', processIsland) .........完整代码请登录后点击上方下载按钮下载查看
网友评论0