all other staff
This commit is contained in:
78
src/pages/Journal.tsx
Normal file
78
src/pages/Journal.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import dayjs from 'dayjs';
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import {
|
||||
ArrowImg,
|
||||
IconButton,
|
||||
InputElement,
|
||||
InputLabel,
|
||||
InputWrapper,
|
||||
StartWrapper,
|
||||
LessonItem,
|
||||
Lessonname,
|
||||
} from './style';
|
||||
|
||||
import arrow from '../assets/36-arrow-right.svg';
|
||||
import { connect, getSocket } from "../socket";
|
||||
|
||||
export const Journal = () => {
|
||||
const [lessons, setLessons] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
connect();
|
||||
const socket = getSocket();
|
||||
socket.on('lessons', data => {
|
||||
setLessons(data)
|
||||
})
|
||||
}, []);
|
||||
|
||||
const [value, setValue] = useState('');
|
||||
const handleChange = useCallback(event => {
|
||||
setValue(event.target.value.toUpperCase())
|
||||
}, [setValue]);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
const handleSubmit = useCallback((event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const socket = getSocket();
|
||||
socket.emit('create-lesson', { lessonName: value });
|
||||
setValue('')
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
<StartWrapper>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<InputWrapper>
|
||||
<InputLabel
|
||||
htmlFor='input'
|
||||
>
|
||||
Название новой лекции:
|
||||
</InputLabel>
|
||||
<InputElement
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
ref={inputRef}
|
||||
id="input"
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
/>
|
||||
<IconButton type="submit">
|
||||
<ArrowImg src={arrow} />
|
||||
</IconButton>
|
||||
</InputWrapper>
|
||||
</form>
|
||||
<ul style={{ paddingLeft: 0 }}>
|
||||
{lessons?.map((lesson) => (
|
||||
<LessonItem key={lesson.id}>
|
||||
<Link to={`/journal/l/${lesson.id}`}>
|
||||
<Lessonname>{lesson.name}</Lessonname>
|
||||
<span>{dayjs(lesson.ts).format('DD MMMM YYYYг.')}</span>
|
||||
</Link>
|
||||
</LessonItem>
|
||||
))}
|
||||
</ul>
|
||||
</StartWrapper>
|
||||
)
|
||||
};
|
||||
44
src/pages/Lesson.tsx
Normal file
44
src/pages/Lesson.tsx
Normal file
@@ -0,0 +1,44 @@
|
||||
import React, { useEffect, useState, useRef } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import dayjs from 'dayjs';
|
||||
import QRCode from 'qrcode';
|
||||
|
||||
import { connect, getSocket } from '../socket';
|
||||
import { MainWrapper, StartWrapper, QRCanvas, LessonItem, Lessonname } from './style';
|
||||
|
||||
export const Lesson = () => {
|
||||
const { lessonId } = useParams();
|
||||
const canvRef = useRef(null);
|
||||
const [lesson, setLesson] = useState(null);
|
||||
useEffect(() => {
|
||||
connect();
|
||||
const socket = getSocket();
|
||||
socket.on('lessons', data => {
|
||||
setLesson(data.find(lesson => lesson.id === lessonId));
|
||||
})
|
||||
|
||||
QRCode.toCanvas(canvRef.current, `${location.origin}/journal/u/${lessonId}` , function (error) {
|
||||
if (error) console.error(error)
|
||||
console.log('success!');
|
||||
})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<MainWrapper>
|
||||
<StartWrapper>
|
||||
<h1>Lesson - {lesson?.name}</h1>
|
||||
<span>{dayjs(lesson?.ts).format('DD MMMM YYYYг.')}</span>
|
||||
|
||||
<QRCanvas ref={canvRef} />
|
||||
|
||||
<ul style={{ paddingLeft: 0 }}>
|
||||
{lesson?.padavans?.map((padavan, index) => (
|
||||
<LessonItem key={index}>
|
||||
<Lessonname>{padavan.name}</Lessonname>
|
||||
</LessonItem>
|
||||
))}
|
||||
</ul>
|
||||
</StartWrapper>
|
||||
</MainWrapper>
|
||||
)
|
||||
}
|
||||
72
src/pages/UserPage.tsx
Normal file
72
src/pages/UserPage.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { connect, getSocket } from '../socket';
|
||||
import { ArrowImg, IconButton, InputElement, InputLabel, InputWrapper, MainWrapper, StartWrapper } from './style';
|
||||
import arrow from '../assets/36-arrow-right.svg';
|
||||
|
||||
export const UserPage = () => {
|
||||
const [socketId, setSocketId] = useState(null);
|
||||
const { lessonId } = useParams();
|
||||
useEffect(() => {
|
||||
connect();
|
||||
const socket = getSocket();
|
||||
socket.on('connect', () => {
|
||||
const id = localStorage.getItem('socketId');
|
||||
if (!id) {
|
||||
localStorage.setItem('socketId', socket.id);
|
||||
setSocketId(socket.id);
|
||||
} else {
|
||||
setSocketId(id);
|
||||
}
|
||||
|
||||
const name = localStorage.getItem('name');
|
||||
if (name) {
|
||||
const socket = getSocket();
|
||||
socket.emit('add', { socketId: id || socket.id, name, lessonid: lessonId });
|
||||
}
|
||||
})
|
||||
socket.on('lessons', data => {
|
||||
// setLessons(data)
|
||||
})
|
||||
}, []);
|
||||
|
||||
const [value, setValue] = useState(localStorage.getItem('name') || '');
|
||||
const handleChange = useCallback(event => {
|
||||
setValue(event.target.value.toUpperCase())
|
||||
}, [setValue]);
|
||||
|
||||
const handleSubmit = useCallback((event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const socket = getSocket();
|
||||
localStorage.setItem('name', value)
|
||||
socket.emit('add', { socketId, name: value, lessonid: lessonId });
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
<MainWrapper>
|
||||
<StartWrapper>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<InputWrapper>
|
||||
<InputLabel
|
||||
htmlFor='input'
|
||||
>
|
||||
Как вас зовут:
|
||||
</InputLabel>
|
||||
<InputElement
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
id="input"
|
||||
type="text"
|
||||
autoComplete="off"
|
||||
/>
|
||||
<IconButton type="submit">
|
||||
<ArrowImg src={arrow} />
|
||||
</IconButton>
|
||||
</InputWrapper>
|
||||
</form>
|
||||
</StartWrapper>
|
||||
</MainWrapper>
|
||||
)
|
||||
}
|
||||
@@ -1,41 +1,16 @@
|
||||
import React, {useState, useCallback, useRef, useMemo} from 'react';
|
||||
import { getFeatures } from '@ijl/cli';
|
||||
import React, {useState, useCallback, useRef, useEffect} from 'react';
|
||||
|
||||
import logo from '../assets/logo.svg';
|
||||
import arrow from '../assets/36-arrow-right.svg';
|
||||
import fullScreen from '../assets/fullscreen.svg';
|
||||
import logoShort from '../assets/logo-short.svg';
|
||||
|
||||
import { Keyboard } from '../components/keyboard';
|
||||
|
||||
import {
|
||||
MainWrapper,
|
||||
InputElement,
|
||||
InputLabel,
|
||||
InputWrapper,
|
||||
LogoImg,
|
||||
ArrowImg,
|
||||
IconButton,
|
||||
StartWrapper,
|
||||
StartI,
|
||||
StartInput,
|
||||
StartLabel,
|
||||
HalfLine,
|
||||
HideGroup,
|
||||
Circle,
|
||||
LineSvg,
|
||||
Svg,
|
||||
CircleDiv,
|
||||
FullScreenButton,
|
||||
InputHolder,
|
||||
Blow,
|
||||
BigLogo,
|
||||
} from './style';
|
||||
import { socket } from "../socket";
|
||||
|
||||
const keyboardFeature = getFeatures('hub-video-start')?.keyboard;
|
||||
const fullScreenFeature = getFeatures('hub-video-start')?.fullScreen;
|
||||
const blowAnimFeature = getFeatures('hub-video-start')?.blowAnim;
|
||||
import { Journal } from './Journal';
|
||||
|
||||
const Input = ({ onStart }) => {
|
||||
const [value, setValue] = useState('');
|
||||
@@ -45,9 +20,18 @@ const Input = ({ onStart }) => {
|
||||
}, [setValue]);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const pass = localStorage.getItem('pass')
|
||||
|
||||
if (pass) {
|
||||
onStart();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleSubmit = useCallback((event) => {
|
||||
event.preventDefault();
|
||||
if (value === 'SBER') {
|
||||
localStorage.setItem('pass', 'true')
|
||||
if (value === 'OYB0Y') {
|
||||
onStart()
|
||||
}
|
||||
}, [value])
|
||||
@@ -59,219 +43,33 @@ const Input = ({ onStart }) => {
|
||||
<InputLabel
|
||||
htmlFor='input'
|
||||
>
|
||||
Ввод:
|
||||
Введите пароль:
|
||||
</InputLabel>
|
||||
<InputElement
|
||||
value={value}
|
||||
onChange={handleChange}
|
||||
onFocus={() => setInfocuse(true)}
|
||||
ref={inputRef}
|
||||
onClick={(event) => {
|
||||
if (keyboardFeature) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
inputRef.current.blur();
|
||||
}
|
||||
}}
|
||||
id="input"
|
||||
type="password"
|
||||
autoComplete="off"
|
||||
/>
|
||||
{keyboardFeature && <InputHolder onClick={() => setInfocuse(true)} />}
|
||||
<IconButton type="submit">
|
||||
<ArrowImg src={arrow} />
|
||||
</IconButton>
|
||||
</InputWrapper>
|
||||
</form>
|
||||
{keyboardFeature && inFocuse && (
|
||||
<Keyboard onChange={setValue} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const Line = ({ hide, reverse, speed, delay, radius, progress, width, color }) => (
|
||||
<LineSvg
|
||||
delay={delay}
|
||||
reverse={reverse}
|
||||
animationSpeed={speed}
|
||||
width={(radius * 2) + 20 + width}
|
||||
height={(radius * 2) + 20 + width}
|
||||
>
|
||||
<HideGroup hide={hide} delay={delay}>
|
||||
<Circle
|
||||
percent={progress}
|
||||
circumference={radius * 2 * Math.PI}
|
||||
stroke={color}
|
||||
strokeWidth={width}
|
||||
fill="transparent"
|
||||
r={radius}
|
||||
cx={radius + 10 + width/2}
|
||||
cy={radius + 10 + width/2}
|
||||
/>
|
||||
</HideGroup>
|
||||
</LineSvg>
|
||||
)
|
||||
|
||||
Line.defaultProps = {
|
||||
reverse: false
|
||||
}
|
||||
|
||||
const Start = () => {
|
||||
const [sended, setSend] = useState(false);
|
||||
|
||||
const handleCheck = () => {
|
||||
if (!sended) {
|
||||
socket.emit('play')
|
||||
setSend(true)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<StartWrapper>
|
||||
{sended && blowAnimFeature && (
|
||||
<>
|
||||
<Blow
|
||||
delay={.3}
|
||||
color="#83e973"
|
||||
/>
|
||||
<Blow
|
||||
delay={.4}
|
||||
color="#97e043"
|
||||
/>
|
||||
<Blow
|
||||
delay={.5}
|
||||
color="#d0eb04"
|
||||
/>
|
||||
<Blow
|
||||
delay={.6}
|
||||
color="#3fc0e4"
|
||||
/>
|
||||
<Blow
|
||||
delay={.7}
|
||||
color="#daf4ff"
|
||||
/>
|
||||
<BigLogo src={logoShort} />
|
||||
</>
|
||||
)}
|
||||
{/* <Svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1200"
|
||||
height="1200"
|
||||
viewBox="0 0 400 400">
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||
<stop offset="50%" stop-color="#f7f7f720" />
|
||||
<stop offset="100%" stop-color="#4aa9edca" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<circle cx="200" cy="-100" r="90" stroke="url(#gradient)" stroke-width="46" fill="none" transform='rotate(90 50 50)'/>
|
||||
</Svg> */}
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={24}
|
||||
delay={3}
|
||||
radius={122}
|
||||
progress={2}
|
||||
width={3}
|
||||
reverse
|
||||
color="white"
|
||||
/>
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={12}
|
||||
delay={9}
|
||||
radius={122}
|
||||
progress={2}
|
||||
width={3}
|
||||
color="white"
|
||||
/>
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={53}
|
||||
radius={220}
|
||||
delay={6}
|
||||
progress={22}
|
||||
width={12}
|
||||
color="#92de22"
|
||||
/>
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={53}
|
||||
radius={220}
|
||||
delay={17.8}
|
||||
progress={.5}
|
||||
width={12}
|
||||
color="#92de22"
|
||||
/>
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={53}
|
||||
radius={220}
|
||||
delay={18.3}
|
||||
progress={.2}
|
||||
width={12}
|
||||
color="#92de22"
|
||||
/>
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={54}
|
||||
radius={220}
|
||||
delay={30}
|
||||
progress={44}
|
||||
width={15}
|
||||
color="#92de22"
|
||||
/>
|
||||
<Line
|
||||
hide={sended}
|
||||
speed={12}
|
||||
radius={120}
|
||||
delay={0}
|
||||
progress={13}
|
||||
width={6}
|
||||
color="white"
|
||||
/>
|
||||
<StartInput
|
||||
id="check"
|
||||
type="checkbox"
|
||||
onChange={handleCheck}
|
||||
/>
|
||||
<StartLabel
|
||||
htmlFor='check'
|
||||
>
|
||||
<StartI>СТАРТ</StartI>
|
||||
</StartLabel>
|
||||
<CircleDiv />
|
||||
</StartWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export const MainPage = () => {
|
||||
const [showStart, setShowStart] = useState(false);
|
||||
const [isFull, setFull] = useState(false);
|
||||
|
||||
const handleFullScreen = useCallback(() => {
|
||||
const elem = document.documentElement;
|
||||
if (elem.requestFullscreen) {
|
||||
elem.requestFullscreen();
|
||||
} else if (elem.webkitRequestFullscreen) { /* Safari */
|
||||
elem.webkitRequestFullscreen();
|
||||
} else if (elem.msRequestFullscreen) { /* IE11 */
|
||||
elem.msRequestFullscreen();
|
||||
}
|
||||
setFull(true);
|
||||
}, []);
|
||||
const [shoList, setShoList] = useState(false);
|
||||
|
||||
return (
|
||||
<MainWrapper>
|
||||
{fullScreenFeature && !isFull && (
|
||||
<FullScreenButton onClick={handleFullScreen}>
|
||||
<img src={fullScreen} />
|
||||
</FullScreenButton>
|
||||
)}
|
||||
<LogoImg src={logo} />
|
||||
{/* <Start /> */}
|
||||
{!showStart && <Input onStart={() => setShowStart(true)} />}
|
||||
{showStart && <Start />}
|
||||
{!shoList && <Input onStart={() => setShoList(true)} />}
|
||||
{shoList && <Journal />}
|
||||
</MainWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -33,12 +33,6 @@ export const InputElement = styled.input`
|
||||
max-width: 90vw;
|
||||
`;
|
||||
|
||||
export const LogoImg = styled.img`
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
`;
|
||||
|
||||
export const ArrowImg = styled.img`
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
@@ -65,177 +59,12 @@ const reveal = keyframes`
|
||||
export const StartWrapper = styled.div`
|
||||
animation: ${reveal} 1s ease forwards;
|
||||
/* box-shadow: 0 -2px 5px rgba(255,255,255,0.05), 0 2px 5px rgba(255,255,255,0.1); */
|
||||
width: 350px;
|
||||
height: 350px;
|
||||
width: 650px;
|
||||
height: calc(100vh - 300px);
|
||||
/* margin: 60px auto; */
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
export const StartLabel = styled.label`
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
background: #b25244;
|
||||
/* background: linear-gradient(#f7f2f6, #b2ac9e); */
|
||||
/* background: linear-gradient(#b52a2a, #e10ff1); */
|
||||
background: linear-gradient(rgb(255 251 251), rgb(140 219 35));
|
||||
position: relative;
|
||||
color: #a5a39d;
|
||||
font-size: 70px;
|
||||
text-align: center;
|
||||
line-height: 150px;
|
||||
transition: all 0.3s ease-out;
|
||||
text-shadow: 0 2px 1px rgba(0,0,0,0.25);
|
||||
z-index: 1;
|
||||
box-shadow:
|
||||
inset 0 2px 3px rgba(255,255,255,0.13),
|
||||
0 5px 8px rgba(0,0,0,0.3),
|
||||
0 10px 10px 4px rgba(0,0,0,0.3);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -20px;
|
||||
right: -20px;
|
||||
top: -20px;
|
||||
bottom: -20px;
|
||||
z-index: -2;
|
||||
border-radius: inherit;
|
||||
box-shadow:
|
||||
inset 0 1px 0 rgba(255,255,255,0.1),
|
||||
0 1px 2px rgba(0,0,0,0.3),
|
||||
0 0 10px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
right: -10px;
|
||||
top: -10px;
|
||||
bottom: -10px;
|
||||
z-index: -1;
|
||||
border-radius: inherit;
|
||||
box-shadow: inset 0 10px 10px rgba(0,0,0,0.13);
|
||||
-webkit-filter:blur(1px);
|
||||
filter: blur(1px);
|
||||
}
|
||||
`;
|
||||
|
||||
export const StartInput = styled.input`
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
z-index: 100;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
&:checked ~ label {
|
||||
box-shadow:
|
||||
inset 0 2px 3px rgba(255,255,255,0.13),
|
||||
0 5px 8px rgba(0,0,0,0.35),
|
||||
0 3px 10px 4px rgba(0,0,0,0.2);
|
||||
color: #9abb82;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StartI = styled.i`
|
||||
content: "";
|
||||
display: flex;
|
||||
position: absolute;
|
||||
width: 70%;
|
||||
height: 70%;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
z-index: 1;
|
||||
color: white;
|
||||
margin: -35% 0 0 -35%;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(#22a037, #98e221);
|
||||
box-shadow:
|
||||
0 -2px 5px rgba(255,255,255,0.05),
|
||||
0 2px 5px rgba(255,255,255,0.1);
|
||||
-webkit-filter:blur(1px);
|
||||
filter: blur(1px);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-style: normal;
|
||||
`;
|
||||
|
||||
// const LineRotation = keyframes
|
||||
//`
|
||||
// 0% {
|
||||
// transform: translate(-50%, -100%) rotate(0);
|
||||
// }
|
||||
|
||||
// 100% {
|
||||
// transform: translate(-50%, -100%) rotate(1turn);
|
||||
// }
|
||||
// `;
|
||||
|
||||
|
||||
// type LineProps = {
|
||||
// radius: number;
|
||||
// width: number;
|
||||
|
||||
// }
|
||||
|
||||
// export const HalfLine = styled.div<LineProps>(({
|
||||
// radius,
|
||||
// width,
|
||||
// }) =>css`
|
||||
// transform-origin: 50% 100%;
|
||||
// animation: ${LineRotation} 3s linear infinite;
|
||||
// width: ${radius * 2}px;
|
||||
// height: ${radius}px;
|
||||
// border-top-left-radius: ${radius}px;
|
||||
// border-top-right-radius: ${radius}px;
|
||||
// border: ${width}px solid gray;
|
||||
// border-bottom: 0;
|
||||
// position: absolute;
|
||||
// top: 50%;
|
||||
// left: 50%;
|
||||
// transform: translate(-50%, -100%);
|
||||
// `);
|
||||
|
||||
const LineRotation = keyframes`
|
||||
0% {
|
||||
transform: translate(-50%, -50%) rotate(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(-50%, -50%) rotate(1turn);
|
||||
}
|
||||
`;
|
||||
|
||||
const LineHideAnimation = keyframes`
|
||||
0% {
|
||||
/* transform: scale(1); */
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
/* transform: scale(0); */
|
||||
opacity: 0;
|
||||
}
|
||||
`;
|
||||
|
||||
export const Svg = styled.svg`
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@@ -245,120 +74,20 @@ export const Svg = styled.svg`
|
||||
/* stroke-dasharray: 600; */
|
||||
`;
|
||||
|
||||
export const CircleDiv = styled.div`
|
||||
width: 700px;
|
||||
height: 700px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform-origin: 50% 50%;
|
||||
transform: translate(-50%, -50%) rotate(270deg);
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(
|
||||
farthest-side at bottom center,
|
||||
rgba(35, 235, 4, 0.709),
|
||||
rgba(255, 255, 255, 0) 65%
|
||||
),
|
||||
radial-gradient(
|
||||
farthest-corner at bottom left,
|
||||
rgba(244, 244, 8, 0.9),
|
||||
rgba(255, 255, 255, 0) 40%
|
||||
),
|
||||
radial-gradient(
|
||||
farthest-side at bottom right,
|
||||
rgba(0, 195, 255, 0.648),
|
||||
rgba(255, 255, 255, 0) 65%
|
||||
);
|
||||
export const LessonItem = styled.li`
|
||||
list-style: none;
|
||||
background-color: #ffffff;
|
||||
padding: 16px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 2px 2px 6px #0000005c;
|
||||
margin-bottom: 12px;
|
||||
`;
|
||||
|
||||
export const LineSvg = styled.svg<{ animationSpeed: number; delay: number; reverse: boolean }>`
|
||||
animation: ${LineRotation} ${({ animationSpeed }) => animationSpeed}s linear infinite${({ reverse }) => reverse ? ' reverse' : ''};
|
||||
animation-delay: -${({ delay }) => delay}s;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform-origin: 50% 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 2;
|
||||
export const Lessonname = styled.span`
|
||||
display: inline-box;
|
||||
margin-right: 12px;
|
||||
`;
|
||||
|
||||
export const HideGroup = styled.g<{ hide: boolean; delay: number; }>`
|
||||
animation: ${({ hide }) => hide ? css`${LineHideAnimation} 3s ease-in forwards`: ''};
|
||||
transform-origin: 50% 50%;
|
||||
animation-delay: ${({ delay }) => delay / 10}s;
|
||||
`;
|
||||
export const Circle = styled.circle<{ circumference: number; percent: number }>`
|
||||
transition: 0.35s stroke-dashoffset;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: 50% 50%;
|
||||
stroke-dasharray: ${({ circumference }) => `${circumference} ${circumference}`};
|
||||
stroke-dashoffset: ${({ circumference, percent }) => circumference - percent / 100 * circumference};
|
||||
`;
|
||||
|
||||
export const FullScreenButton = styled.button`
|
||||
padding: 12px;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
right: 50px;
|
||||
border: none;
|
||||
background-color: rgba(0, 0, 0, .07);
|
||||
`;
|
||||
|
||||
export const InputHolder = styled.div`
|
||||
background-color: rgba(0, 0, 0, .0);
|
||||
width: calc(100% - 70px);
|
||||
height: 60px;
|
||||
right: 70px;
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
position: absolute;
|
||||
|
||||
@media screen and (max-width: 600px) {
|
||||
width: 100%;
|
||||
}
|
||||
`;
|
||||
|
||||
const blowAnim = keyframes`
|
||||
to {
|
||||
width: 200vw;
|
||||
height: 200vw;
|
||||
}
|
||||
`;
|
||||
|
||||
type BlowProps = {
|
||||
delay: number;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export const Blow = styled.div<BlowProps>`
|
||||
z-index: 10;
|
||||
border-radius: 50%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
height: 0%;
|
||||
background-color: ${({ color }) => color};
|
||||
animation: ${blowAnim} 1s ease-out forwards;
|
||||
animation-delay: ${({ delay }) => delay}s;
|
||||
transform: translate(-50%, -50%);
|
||||
`;
|
||||
|
||||
const blowAnimShort = keyframes`
|
||||
to {
|
||||
width: 50vw;
|
||||
height: 50vw;
|
||||
}
|
||||
`;
|
||||
|
||||
export const BigLogo = styled.img`
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
width: 0;
|
||||
height: 0;
|
||||
animation: ${blowAnimShort} 2s ease-out forwards;
|
||||
animation-delay: .7s;
|
||||
transform: translate(-50%, -50%);
|
||||
export const QRCanvas = styled.canvas`
|
||||
display: block;
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user