react+use-web-animations实现横向和竖向图标菜单滑动效果代码

代码语言:html

所属分类:菜单导航

代码描述:react+use-web-animations实现横向和竖向图标菜单滑动效果代码

代码标签: react use-web-animations 横向 竖向 图标 菜单 滑动

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  

  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  
  <link rel='stylesheet' href='https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz@0,9..40;1,9..40&amp;display=swap'>
  
<style>
* {
  border: 0;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  --bg: hsl(0,0%,90%);
  --fg: hsl(0,0%,10%);
  --trans-dur: 0.3s;
  font-size: calc(16px + (32 - 16) * (100vw - 240px) / (1920 - 240));
}

body,
button {
  color: var(--fg);
  font: 1em/1.5 "DM Sans", sans-serif;
  transition: background-color var(--trans-dur), color var(--trans-dur);
}

body {
  background-color: var(--bg);
  transition: background-color var(--trans-dur);
}

button {
  outline: transparent;
  -webkit-appearance: none;
  appearance: none;
  -webkit-tap-highlight-color: transparent;
}

main {
  display: flex;
  flex-direction: column;
  gap: 3em;
  align-items: center;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
main > svg {
  position: fixed;
}

.toolbar {
  background-color: var(--fg);
  border-radius: 1em;
  display: inline-flex;
  gap: 0.125em;
  align-items: center;
  position: relative;
  padding: 0.125em;
  min-width: 2em;
  height: 2em;
  transition: background-color var(--trans-dur);
}
.toolbar__button {
  background-color: rgba(128, 128, 128, 0);
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  position: relative;
  width: 1.75em;
  height: 1.75em;
}
.toolbar__button[aria-pressed=false]:hover {
  background-color: rgba(128, 128, 128, 0.5);
}
.toolbar__button-tip {
  background-color: var(--fg);
  border-radius: 0.5625rem;
  color: var(--bg);
  font-size: 0.625em;
  line-height: 1;
  margin-top: 0.375rem;
  opacity: 0;
  padding: 0.25rem 0.5rem;
  pointer-events: none;
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, -25%);
  transition: background-color var(--trans-dur), color var(--trans-dur), opacity var(--trans-dur), transform var(--trans-dur), visibility var(--trans-dur);
  visibility: hidden;
}
.toolbar__button:focus-visible .toolbar__button-tip, .toolbar__button:hover .toolbar__button-tip {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
.toolbar__highlight {
  background-color: white;
  border-radius: 0.875em;
  margin: 0.125em;
  mix-blend-mode: difference;
  pointer-events: none;
  position: absolute;
  top: 0;
  left: 0;
  width: 1.75em;
  height: 1.75em;
  transition: background-color var(--trans-dur);
}
[dir=rtl] .toolbar__highlight {
  right: 0;
  left: auto;
}
.toolbar__icon {
  color: var(--bg);
  display: block;
  margin: auto;
  width: 1em;
  height: auto;
  transition: color var(--trans-dur);
}
.toolbar--vertical {
  flex-direction: column;
  width: 2em;
  min-height: 2em;
  height: auto;
}
.toolbar--vertical .toolbar__button-tip {
  margin-inline-start: 0.375rem;
  margin-top: 0;
  top: 50%;
  left: 100%;
  transform: translate(-25%, -50%);
}
[dir=rtl] .toolbar--vertical .toolbar__button-tip {
  right: 100%;
  left: auto;
  transform: translate(25%, -50%);
}
.toolbar--vertical .toolbar__button:focus-visible .toolbar__button-tip, .toolbar--vertical .toolbar__button:hover .toolbar__button-tip {
  transform: translate(0, -50%);
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
  :root {
    --bg: hsl(0,0%,10%);
    --fg: hsl(0,0%,90%);
  }
}
/* Beyond mobile */
@media (min-width: 768px) {
  main {
    flex-direction: row;
  }
}
</style>

  
</head>

<body translate="no">
  <div id="root"></div>
  
      <script type="module">
import React, { createContext, StrictMode, useContext, useRef, useState } from "https://esm.sh/react";
import { createRoot } from "https://esm.sh/react-dom/client";
import useWebAnimations from "https://esm.sh/@wellyshen/use-web-animations";
const ToolbarContext = createContext(undefined);
const ToolbarProvider = ({ children }) => {
    const [tool, setTool] = useState("select");
    return (React.createElement(ToolbarContext.Provider, { value: { tool, setTool } }, children));
};
const useTool = () => {
    const context = useContext(ToolbarContext);
    if (!context) {
        throw new Error("useTool must be used inside ToolbarProvider");
    }
    return context;
};
createRoot(document.getElementById("root")).render(React.createElement(StrictMode, null,
    React.createElement("main", null,
        React.createElement(ToolbarIconSprites, null),
        React.createElement(ToolbarProvider, null,
            React.createElement(Toolbar, { name: "Horizontal" })),
        React.createElement(ToolbarProvider, null,
            React.createElement(Toolbar, { name: "Vertical", orientation: "vertical" })))));
function Toolbar({ name, orientation = "horizontal" }) {
    const { tool, setTool } = useTool();
    const [toolPrev, setToolPrev] = useState(tool);
    const toolbarRef = useRef(null);
    const { ref, animate } = useWebAnimations();
    const isRTL = document.dir === "rtl";
    const isVertical = orientation === "vertical";
    const tools = [
        {
            icon: "select",
            label: "Select",
            tool: "select"
        },
        {
            icon: "draw",
            label: "Draw",
            tool: "draw"
        },
        {
            icon: "fill",
            label: "Fill",
            tool: "fill"
        },
        {
            icon: "erase",
            label: "Erase",
            tool: "erase"
        }
    ];
    function handleKeyDown(e) {
        var _a;
        const toolButtons = (_a = toolbarRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll("[tabindex]");
        if (!toolButtons)
            return;
        const toolIndex = tools.findIndex(item => item.tool === tool);
        const forward = () => {
            e.preventDefault();
            const nextToolIndex = (toolIndex + 1) % tools.length;
            const toolName = tools[nextToolIndex].tool;
            setTool(() => {
                reAnimate(toolName);
                return toolName;
            });
            toolButtons[nextToolIndex].focus();
        };
        const backward = () => {
            e.preventDefault();
            let prevToolIndex = toolIndex - 1;
            if (prevToolIndex < 0)
                prevToolIndex = tools.length - 1;
            const toolName = tools[prevToolIndex].tool;
            setTool(() => {
                reAnimate(toolName);
                return toolName;
            });
            toolButtons[prevToolIndex].focus();
        };
        switch (e.code) {
            case "ArrowRight": {
                if (isRTL) {
                    backward();
                }
                else {
                    forward();
                }
                break;
            }
            case "ArrowDown": {
                forward();
                break;
            }
            case "ArrowLeft": {
                if (isRTL) {
                    forward();
                }
                else {
                    backward();
 .........完整代码请登录后点击上方下载按钮下载查看

网友评论0