finish splash and quick start
parent
a3338c5e33
commit
8d63c87eb9
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 407 KiB |
|
@ -25,12 +25,10 @@ if (process.env.NODE_ENV === 'production') {
|
|||
const visitedFlagStorage = sessionStorage
|
||||
|
||||
const App = ({ store }) => {
|
||||
const [modal, setModal] = useState(!visitedFlagStorage.getItem('visited'))
|
||||
return <Provider store={store}>
|
||||
<NavBar />
|
||||
<Tree />
|
||||
<ToolTip />
|
||||
{modal && < Help {...{ setModal }} />}
|
||||
</Provider>
|
||||
}
|
||||
|
||||
|
|
|
@ -15,20 +15,26 @@ export const Clip = ({ setClip, clip }) => {
|
|||
// console.log(width, width/1.6, window.innerHeight, top)
|
||||
|
||||
return (
|
||||
<div className='absolute left-0 right-0 m-auto bg-gray-700 flex flex-col
|
||||
border-2 border-gray-500 rounded-2xl overflow-hidden
|
||||
<div className='absolute left-0 right-0 m-auto flex flex-col
|
||||
overflow-hidden
|
||||
'
|
||||
style={{
|
||||
width,
|
||||
top,
|
||||
}}
|
||||
>
|
||||
<div className='text-2xl flex justify-center items-center'>
|
||||
<div className='text-xl flex justify-center items-center bg-green-900 '>
|
||||
<div className='text-gray-50'>
|
||||
{clip[1]}
|
||||
</div>
|
||||
<MdCancel className="absolute cursor-pointer text-gray-50 hover:text-gray-400 right-2"
|
||||
onClick={() => setClip(null)}
|
||||
/>
|
||||
</div>
|
||||
<video src={clip[0]} width='100%' controls muted type="video/mp4" />
|
||||
<video
|
||||
className='border-2 border-gray-500'
|
||||
|
||||
src={clip[0]} width='100%' controls muted type="video/mp4" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ function reducer(state, action) {
|
|||
case 'drag':
|
||||
const dragLeft = state.dragLeft - action.move
|
||||
|
||||
if (dragLeft < 0 || dragLeft > state.rect * arr.length) {
|
||||
if (dragLeft < 0 || dragLeft > state.rect * arr.length - 1) {
|
||||
return state
|
||||
} else {
|
||||
return {
|
||||
|
@ -77,7 +77,7 @@ const arr = [
|
|||
['Sketch out your idea in a 2D outline.', 'sketch.png'],
|
||||
['Transform the sketched shape into a 3D solid.', 'extrude.png'],
|
||||
['Use additional sketches to sculpt or extend the model.', 'sculpt.gif'],
|
||||
['Export your design to a 3D printer and turn into reality.', ''],
|
||||
['Export your design to a 3D printer and turn into reality.', '3dprint.mp4'],
|
||||
]
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@ const arr = [
|
|||
|
||||
|
||||
|
||||
export const Help = ({ setModal }) => {
|
||||
export const Help = ({ setModal, setQs }) => {
|
||||
|
||||
|
||||
|
||||
|
@ -150,38 +150,53 @@ export const Help = ({ setModal }) => {
|
|||
<div className='bg-transparent h-full flex select-none'
|
||||
|
||||
style={{
|
||||
width: state.rect * (arr.length + 1),
|
||||
width: state.rect * (arr.length),
|
||||
transform: `translateX(${state.dragging ? -state.dragLeft - 4 : -state.pg * state.rect - 4}px)`,
|
||||
transition: state.dragging ? null : elastic
|
||||
}}
|
||||
>
|
||||
{
|
||||
arr.map(
|
||||
(e, idx) => <div className='flex flex-col items-center'
|
||||
(e, idx) => {
|
||||
const isVideo = e[1].match(/\.[0-9a-z]+$/i)[0] == '.mp4'
|
||||
return <div className='flex flex-col items-center'
|
||||
style={{ width: state.rect, height: '100%' }} key={idx}
|
||||
>
|
||||
<img className="bg-gray-800"
|
||||
{
|
||||
isVideo ?
|
||||
<video src={e[1]}
|
||||
style={{
|
||||
width: state.rect * 0.8,
|
||||
height: state.rect * 0.8,
|
||||
}}
|
||||
autoPlay loop
|
||||
muted type="video/mp4" />
|
||||
:
|
||||
<img
|
||||
src={e[1]}
|
||||
style={{
|
||||
width: state.rect * 0.8,
|
||||
height: state.rect * 0.8,
|
||||
}}
|
||||
></img>
|
||||
}
|
||||
|
||||
|
||||
<div className='my-auto text-center text-gray-50 text-sm sm:text-base md:text-xl'>
|
||||
{e[0]}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
<div className='flex flex-col items-center'
|
||||
{/* <div className='flex flex-col items-center'
|
||||
style={{ width: state.rect, height: '100%' }}
|
||||
>
|
||||
<QuickStart {...{ setModal }} />
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -192,7 +207,10 @@ export const Help = ({ setModal }) => {
|
|||
// style={{
|
||||
// position:'absolute'
|
||||
// bottom: 0.1 * state.rect}}
|
||||
onClick={() => setModal(false)}
|
||||
onClick={() => {
|
||||
setModal(false)
|
||||
setQs(true)
|
||||
}}
|
||||
>
|
||||
Get Started
|
||||
</div>
|
||||
|
@ -208,14 +226,14 @@ export const Help = ({ setModal }) => {
|
|||
<div className='cursor-pointer select-none absolute w-12 h-12 top-0 bottom-0 my-auto -right-24 fill-current bg-gray-100 hover:bg-gray-300 rounded-full'
|
||||
onClick={() => carouselDispatch({ type: "move", del: 1 })}
|
||||
style={{
|
||||
visibility: state.pg == arr.length ? 'hidden' : 'visible'
|
||||
visibility: state.pg == arr.length - 1 ? 'hidden' : 'visible'
|
||||
}}
|
||||
>
|
||||
<MdArrowForward className="w-full h-full text-gray-700 p-3" />
|
||||
</div>
|
||||
|
||||
<div className="flex -bottom-8 absolute flex justify-center items-center">
|
||||
{Array(arr.length + 1).fill().map((ele, idx) => (
|
||||
{Array(arr.length).fill().map((ele, idx) => (
|
||||
<div key={idx} className={`h-2 w-2 mx-1 rounded-full ${idx == state.pg ? 'bg-gray-50' : 'bg-gray-500'}`}></div>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
@ -12,13 +12,12 @@ export class Modal extends React.Component {
|
|||
|
||||
this.handleClickout = this.handleClickout.bind(this)
|
||||
|
||||
this.clickOut = props.clickOut == undefined ? true : props.clickOut
|
||||
}
|
||||
|
||||
handleClickout(e) {
|
||||
if (modalRoot.lastChild != this.el) return
|
||||
|
||||
console.log(this.id, e.composedPath())
|
||||
|
||||
|
||||
if (!e.composedPath().includes(this.el)) {
|
||||
this.setModal(false)
|
||||
|
@ -28,13 +27,14 @@ export class Modal extends React.Component {
|
|||
|
||||
componentDidMount() {
|
||||
modalRoot.appendChild(this.el);
|
||||
|
||||
if (this.clickOut) {
|
||||
document.addEventListener( // handles click outside buttona & dropdown
|
||||
'click', this.handleClickout
|
||||
,
|
||||
{ capture: true } // capture phase to allow for stopPropogation on others
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.handleClickout, { capture: true })
|
||||
|
|
|
@ -12,7 +12,8 @@ import { Dialog } from './dialog'
|
|||
import { Modal } from './modal'
|
||||
import { STLExport, saveFile, openFile } from './fileHelpers'
|
||||
import { QuickStart } from './quickStart';
|
||||
|
||||
import { Help } from './help'
|
||||
const visitedFlagStorage = sessionStorage
|
||||
const buttonIdx = {
|
||||
'line': 1,
|
||||
'arc': 2,
|
||||
|
@ -170,9 +171,10 @@ export const NavBar = () => {
|
|||
|
||||
const [_, forceUpdate] = useReducer(x => x + 1, 0);
|
||||
|
||||
const [splash, setSplash] = useState(!visitedFlagStorage.getItem('visited'))
|
||||
const [modal, setModal] = useState(false)
|
||||
|
||||
return <div className='topNav flex justify-center bg-gray-800'>
|
||||
return <div className='topNav flex justify-center bg-gray-800 text-gray-200 '>
|
||||
|
||||
<div className='w-auto h-full flex-1 flex justify-end lg:justify-between'>
|
||||
<div className='w-100 h-full font-mono text-lg text-gray-200 select-none hidden lg:flex mr-8 items-center'>
|
||||
|
@ -187,8 +189,8 @@ export const NavBar = () => {
|
|||
{(sketchActive ? sketchModeButtons : partModeButtons).map(
|
||||
([Icon, fcn, txt], idx) => (
|
||||
Icon !== undefined ?
|
||||
<Icon className={`cursor-pointer fill-current text-gray-200 w-auto h-full p-3.5
|
||||
${idx == buttonIdx[mode] ? 'bg-green-600' : 'hover:bg-gray-600 bg-transparent'}`} tooltip={txt}
|
||||
<Icon className={`cursor-pointer fill-current w-auto h-full p-3.5
|
||||
${idx == buttonIdx[mode] ? 'bg-green-800' : 'hover:bg-gray-600 bg-transparent'}`} tooltip={txt}
|
||||
onClick={fcn} key={idx}
|
||||
/> :
|
||||
<div className="w-12 h-full"></div>
|
||||
|
@ -197,23 +199,27 @@ export const NavBar = () => {
|
|||
</div>
|
||||
<div className='w-auto h-full flex-1 justify-end flex-shrink-1 hidden md:flex'>
|
||||
|
||||
<MdHelpOutline className="btn-green w-auto h-full p-3" onClick={() => {
|
||||
<MdHelpOutline className={`cursor-pointer fill-current w-auto h-full p-3
|
||||
${modal ? 'bg-green-800' : 'hover:bg-gray-600 bg-transparent'}`} onClick={() => {
|
||||
setModal(true)
|
||||
}
|
||||
} />
|
||||
|
||||
<a href='https://github.com/twpride/three.cad' className='h-full w=auto'>
|
||||
<FaGithub className="btn-green w-auto h-full p-3.5"></FaGithub>
|
||||
<a href='https://github.com/twpride/three.cad' className='h-full w-auto'>
|
||||
<FaGithub className="text-gray-200 cursor-pointer hover:bg-gray-600 bg-transparent w-auto h-full p-3.5"></FaGithub>
|
||||
</a>
|
||||
<a href='https://www.linkedin.com/in/howard-hwang-b3000335' className='h-full w=auto'>
|
||||
<FaLinkedin className="btn-green w-auto h-full p-3.5"></FaLinkedin>
|
||||
<a href='https://www.linkedin.com/in/howard-hwang-b3000335' className='h-full w-auto'>
|
||||
<FaLinkedin className="text-gray-200 cursor-pointer hover:bg-gray-600 bg-transparent w-auto h-full p-3.5"></FaLinkedin>
|
||||
</a>
|
||||
</div>
|
||||
{
|
||||
splash && <Modal {...{ setModal: setSplash, clickOut: false}}>
|
||||
<Help {...{ setModal: setSplash, setQs: setModal }} />
|
||||
</Modal>
|
||||
}
|
||||
{
|
||||
modal && <Modal {...{ setModal, id: 'navbar' }}>
|
||||
<QuickStartWrapper>
|
||||
<QuickStart {...{ setModal }} />
|
||||
</QuickStartWrapper>
|
||||
</Modal>
|
||||
}
|
||||
|
||||
|
@ -222,29 +228,4 @@ export const NavBar = () => {
|
|||
|
||||
|
||||
|
||||
export const QuickStartWrapper = ({ children }) => {
|
||||
const [rect, setRect] = useState(Math.min(Math.min(window.innerHeight * 0.8, window.innerWidth * 0.7), 800))
|
||||
|
||||
const updateSize = () => {
|
||||
setRect(Math.min(Math.min(window.innerHeight * 0.8, window.innerWidth * 0.7), 800))
|
||||
}
|
||||
useEffect(() => {
|
||||
window.addEventListener('resize', updateSize)
|
||||
return () => {
|
||||
window.removeEventListener('resize', updateSize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <div className="absolute left-0 right-0 mx-auto bg-gray-700 rounded-xl flex flex-col items-center border-gray-500 border-2 overflow-hidden"
|
||||
style={{
|
||||
width: rect,
|
||||
height: 1.1 * rect,
|
||||
top: (window.innerHeight - 1.1 * rect) / 3,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useDispatch, useSelector } from "react-redux"
|
|||
import { Clip } from './clip'
|
||||
import { Modal } from './modal'
|
||||
|
||||
import { MdZoomIn, MdSave, MdFolder, MdInsertDriveFile, MdHelpOutline } from 'react-icons/md'
|
||||
import { MdZoomIn, MdSave, MdFolder, MdInsertDriveFile, MdCancel } from 'react-icons/md'
|
||||
import { FaRegPlayCircle, FaEdit, FaCubes } from 'react-icons/fa'
|
||||
|
||||
import * as Icon from "./icons";
|
||||
|
@ -50,7 +50,7 @@ const clipArr = [
|
|||
['basic-workflow.mp4', 'Basic model creation workflow'],
|
||||
['load-file-and-edit.mp4', 'Loading and editing models'],
|
||||
['export-to-3dprint.mp4', 'Exporting model for 3D printing'],
|
||||
['headphones-stand.json.gz', 'Headphones Stand Model'],
|
||||
['headphone-stand.json.gz', 'Headphone Stand Model'],
|
||||
]
|
||||
|
||||
const utf8decoder = new TextDecoder();
|
||||
|
@ -59,27 +59,39 @@ export const QuickStart = ({setModal}) => {
|
|||
const dispatch = useDispatch()
|
||||
|
||||
const [clip, setClip] = useState(null)
|
||||
const [rect, setRect] = useState(Math.min(Math.min(window.innerHeight * 0.8, window.innerWidth * 0.7), 800))
|
||||
|
||||
return <div className='bg-transparent w-full h-full flex justify-center'>
|
||||
<div className="bg-transparent w-full h-full
|
||||
text-sm lg:text-base xl:text-lg
|
||||
flex flex-col items-center overflow-y-auto overflow-x-hidden text-gray-50">
|
||||
<div className='text-center w-full text-lg lg:text-xl xl:text-2xl my-2 font-bold'>
|
||||
Quick Start
|
||||
</div>
|
||||
const updateSize = () => {
|
||||
setRect(Math.min(Math.min(window.innerHeight * 0.8, window.innerWidth * 0.7), 800))
|
||||
}
|
||||
useEffect(() => {
|
||||
window.addEventListener('resize', updateSize)
|
||||
return () => {
|
||||
window.removeEventListener('resize', updateSize)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return <div className="absolute left-0 right-0 mx-auto bg-gray-700 flex flex-col items-center
|
||||
text-sm lg:text-base xl:text-lg text-gray-50"
|
||||
style={{
|
||||
width: rect,
|
||||
height: 1.1 * rect,
|
||||
top: (window.innerHeight - 1.1 * rect) / 2,
|
||||
}}
|
||||
>
|
||||
<div className='w-full h-full bg-transparent overflow-y-auto overflow-x-hidden flex flex-col items-center'>
|
||||
|
||||
<div className='text-center text-base lg:text-lg xl:text-xl mb-2'>
|
||||
<div className='text-center text-base lg:text-lg xl:text-xl mb-2 font-bold'>
|
||||
Demos
|
||||
</div>
|
||||
|
||||
|
||||
<div className='mb-4 cursor-pointer'>
|
||||
<div className='mb-4 cursor-pointer w-min'>
|
||||
{
|
||||
clipArr.map((ele, idx) => {
|
||||
const isGz = ele[0].match(/\.[0-9a-z]+$/i)[0] == '.gz'
|
||||
|
||||
return <div className="flex h-12 mx-2 rounded-lg items-center hover:text-green-500"
|
||||
return <div className="flex h-12 mx-2 items-center hover:text-green-500 whitespace-nowrap"
|
||||
onClick={async () => {
|
||||
if (isGz) {
|
||||
const state = sce.loadState(
|
||||
|
@ -97,7 +109,7 @@ export const QuickStart = ({setModal}) => {
|
|||
)
|
||||
|
||||
setModal(false)
|
||||
dispatch({ type: 'restore-state', state, fileName: ele[0] })
|
||||
dispatch({ type: 'restore-state', state, fileName: ele[0].replace(/\.[^/.]+$/, "") })
|
||||
sce.render()
|
||||
|
||||
} else {
|
||||
|
@ -109,9 +121,9 @@ export const QuickStart = ({setModal}) => {
|
|||
key={idx}
|
||||
>
|
||||
{isGz ?
|
||||
<FaCubes size={'2.5em'} style={{ padding: '0.625em' }} />
|
||||
<FaCubes size={'2.5em'} className='flex-shrink-0' style={{ padding: '0.625em' }} />
|
||||
:
|
||||
<FaRegPlayCircle size={'2.5em'} style={{ padding: '0.625em' }} />
|
||||
<FaRegPlayCircle size={'2.5em'} className='flex-shrink-0' style={{ padding: '0.625em' }} />
|
||||
}
|
||||
{ele[1]}
|
||||
</div>
|
||||
|
@ -130,7 +142,7 @@ export const QuickStart = ({setModal}) => {
|
|||
{
|
||||
navArr.map((row, i) => (
|
||||
typeof row === 'string' ?
|
||||
<div className='col-span-2 flex justify-center text-base lg:text-lg xl:text-xl mb-2' key={i}>
|
||||
<div className='col-span-2 flex justify-center text-base lg:text-lg xl:text-xl mb-2 font-bold' key={i}>
|
||||
{row}
|
||||
</div>
|
||||
:
|
||||
|
@ -161,6 +173,17 @@ export const QuickStart = ({setModal}) => {
|
|||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='absolute -top-7 w-full text-xl flex justify-center items-center bg-green-800'>
|
||||
<div className='text-gray-50'>
|
||||
Quick Start
|
||||
</div>
|
||||
<MdCancel className="absolute cursor-pointer text-gray-50 hover:text-gray-400 right-2"
|
||||
onClick={() => setModal(null)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -169,10 +192,8 @@ export const QuickStart = ({setModal}) => {
|
|||
<Clip {...{ setClip, clip }} />
|
||||
</Modal>
|
||||
}
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue