consolidate carousel
parent
525a13171c
commit
bdcc41176f
|
@ -14,6 +14,8 @@ combine multiple solids to form the part you desire
|
||||||
|
|
||||||
uplaod your design to a 3d printer
|
uplaod your design to a 3d printer
|
||||||
|
|
||||||
|
navigation tips
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
General Workflow for part creation
|
General Workflow for part creation
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
|
import React, { useCallback, useEffect, useReducer, useRef } from 'react';
|
||||||
|
|
||||||
|
import { MdArrowBack, MdArrowForward } from 'react-icons/md'
|
||||||
|
|
||||||
export function throttle(callback, limit) {
|
export function throttle(callback, limit) {
|
||||||
let handler = null; // Initially, we're not waiting
|
let handler = null; // Initially, we're not waiting
|
||||||
|
@ -26,101 +27,97 @@ const transTime = 200
|
||||||
|
|
||||||
const elastic = `transform ${transTime}ms cubic-bezier(0.4, 0.0, 0.2, 1)`;
|
const elastic = `transform ${transTime}ms cubic-bezier(0.4, 0.0, 0.2, 1)`;
|
||||||
|
|
||||||
|
function reducer(state, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'set-rect':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
rect: action.rect
|
||||||
|
};
|
||||||
|
case 'resize':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
rect: action.rect,
|
||||||
|
dragLeft: state.pg * action.rect.width,
|
||||||
|
dragging: true
|
||||||
|
};
|
||||||
|
case 'move':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pg: state.pg + action.del,
|
||||||
|
dragging: false
|
||||||
|
};
|
||||||
|
case 'drag-start':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dragLeft: state.pg * state.rect.width,
|
||||||
|
dragging: true
|
||||||
|
};
|
||||||
|
case 'drag':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dragLeft: state.dragLeft - action.move
|
||||||
|
};
|
||||||
|
case 'drag-end':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pg: Math.round(state.dragLeft / state.rect.width),
|
||||||
|
dragging: false
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
console.log('wtf')
|
||||||
|
console.error(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const Carousel = () => {
|
export const Carousel = () => {
|
||||||
const arr = [1, 2, 3]
|
const arr = [1, 2, 3]
|
||||||
|
|
||||||
|
|
||||||
const ref = useRef(null)
|
const ref = useRef(null)
|
||||||
const [dragging, setDragging] = useState(false)
|
const [state, dispatch] = useReducer(reducer, { rect: {}, pg: 0, dragLeft: 0, dragging: false })
|
||||||
|
|
||||||
// const dragging = useRef(false)
|
|
||||||
const [rect, setRect] = useState({})
|
|
||||||
const [pg, setPg] = useState(0)
|
|
||||||
const [dragLeft, setDragLeft] = useState(0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setRect(ref.current.getBoundingClientRect())
|
dispatch({ type: 'set-rect', rect: ref.current.getBoundingClientRect() })
|
||||||
}, [ref])
|
}, [ref])
|
||||||
|
|
||||||
|
|
||||||
const updateSize = useCallback(
|
const updateSize = useCallback(
|
||||||
debounce(
|
debounce(
|
||||||
// throttle(
|
|
||||||
() => {
|
() => {
|
||||||
setRect(ref.current.getBoundingClientRect())
|
dispatch({ type: 'resize', rect: ref.current.getBoundingClientRect() })
|
||||||
}
|
}
|
||||||
, 200
|
, 200
|
||||||
)
|
)
|
||||||
, []
|
, []
|
||||||
)
|
)
|
||||||
|
|
||||||
// const updateSize = () => setRect(ref.current.getBoundingClientRect())
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// dragging.current = false
|
|
||||||
// console.log(dragging)
|
|
||||||
// setDragLeft(pg * rect.width)
|
|
||||||
// setDragging(false)
|
|
||||||
}, [rect])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('resize', updateSize)
|
window.addEventListener('resize', updateSize)
|
||||||
return () => window.removeEventListener('resize', updateSize)
|
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<div
|
|
||||||
className='select-none'
|
|
||||||
onClick={
|
<div className='bg-transparent h-full w-full'
|
||||||
() => setPg(pg + 1)
|
|
||||||
}>1</div>
|
|
||||||
<div
|
|
||||||
className='select-none'
|
|
||||||
onClick={
|
|
||||||
() => setPg(pg - 1)
|
|
||||||
}
|
|
||||||
>2</div>
|
|
||||||
<div
|
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className='relative overflow-visible bg-gray-200 h-full w-full'
|
|
||||||
>
|
>
|
||||||
{rect.width &&
|
{state.rect.width &&
|
||||||
<div
|
<div className='absolute top-0 overflow-visible bg-green-400 h-full'
|
||||||
className='absolute overflow-visible bg-green-400'
|
|
||||||
|
|
||||||
onMouseDown={() => {
|
onMouseDown={() => dispatch({ type: 'drag-start' })}
|
||||||
setDragging(true)
|
onMouseMove={(e) => e.buttons == 1 && dispatch({ type: 'drag', move: e.movementX })}
|
||||||
// dragging.current = true
|
onMouseUp={() => dispatch({ type: 'drag-end' })}
|
||||||
setDragLeft(pg * rect.width)
|
|
||||||
}}
|
|
||||||
|
|
||||||
onMouseMove={(e) => {
|
|
||||||
if (e.buttons != 1) return
|
|
||||||
setDragLeft(state => state + e.movementX)
|
|
||||||
}}
|
|
||||||
|
|
||||||
onMouseUp={(e) => {
|
|
||||||
// dragging.current = false
|
|
||||||
setPg(Math.round(dragLeft / rect.width))
|
|
||||||
setDragging(false)
|
|
||||||
}}
|
|
||||||
|
|
||||||
style={{
|
style={{
|
||||||
height: '80%',
|
width: 1 * state.rect.width,
|
||||||
width: 1 * rect.width,
|
transform: `translateX(${state.dragging ? -state.dragLeft : -state.pg * state.rect.width}px)`,
|
||||||
top: 0,
|
transition: state.dragging ? null : elastic
|
||||||
// left: dragging ? dragLeft : pg * rect.width,
|
}}
|
||||||
left: 0,
|
>
|
||||||
transform: `translateX(${dragging ? dragLeft : pg * rect.width}px)`,
|
|
||||||
transition: dragging ? null : elastic
|
|
||||||
}}>
|
|
||||||
{
|
{
|
||||||
arr.map((e, idx) => {
|
arr.map((e, idx) => {
|
||||||
|
|
||||||
|
@ -132,6 +129,24 @@ export const Carousel = () => {
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className='select-none absolute w-12 h-12 top-0 bottom-0 my-auto -left-24 fill-current bg-gray-100 rounded-full'
|
||||||
|
onClick={() => dispatch({ type: "move", del: -1 })}
|
||||||
|
>
|
||||||
|
<MdArrowBack className="w-full h-full text-gray-700 p-3" />
|
||||||
|
</div>
|
||||||
|
<div className='select-none absolute w-12 h-12 top-0 bottom-0 my-auto -right-24 fill-current bg-gray-100 rounded-full'
|
||||||
|
onClick={() => dispatch({ type: "move", del: 1 })}
|
||||||
|
>
|
||||||
|
<MdArrowForward className="w-full h-full text-gray-700 p-3" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex w-full -bottom-8 absolute flex justify-center items-center">
|
||||||
|
{arr.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>
|
||||||
|
|
||||||
</>
|
</>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
|
||||||
|
import React, { useCallback, useEffect, useReducer, useRef } from 'react';
|
||||||
|
|
||||||
import { useDispatch, useSelector } from 'react-redux'
|
import { useDispatch, useSelector } from 'react-redux'
|
||||||
|
|
||||||
import { MdCancel, MdClose, MdHelpOutline } from 'react-icons/md'
|
import { MdCancel, MdArrowBack, MdArrowForward } from 'react-icons/md'
|
||||||
|
|
||||||
import { Carousel } from './carousel'
|
import { Carousel } from './carousel'
|
||||||
|
|
||||||
|
@ -34,54 +35,162 @@ const exportTS = [
|
||||||
10, 'result',
|
10, 'result',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
function debounce(callback, delay) {
|
||||||
|
let handler = null;
|
||||||
|
return (...args) => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
handler = setTimeout(() => callback(...args), delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reducer(state, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
case 'resize':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
rect: window.innerHeight * 0.6,
|
||||||
|
dragLeft: state.pg * window.innerHeight * 0.6,
|
||||||
|
dragging: true
|
||||||
|
};
|
||||||
|
case 'move':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pg: state.pg + action.del,
|
||||||
|
dragging: false
|
||||||
|
};
|
||||||
|
case 'drag-start':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dragLeft: state.pg * state.rect,
|
||||||
|
dragging: true
|
||||||
|
};
|
||||||
|
case 'drag':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dragLeft: state.dragLeft - action.move
|
||||||
|
};
|
||||||
|
case 'drag-end':
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
pg: Math.round(state.dragLeft / state.rect),
|
||||||
|
dragging: false
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
console.error(action)
|
||||||
|
// throw new Error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const transTime = 200
|
||||||
|
|
||||||
|
const elastic = `transform ${transTime}ms cubic-bezier(0.4, 0.0, 0.2, 1)`;
|
||||||
|
|
||||||
export const Help = () => {
|
export const Help = () => {
|
||||||
|
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
const status = useSelector(state => state.ui.help)
|
||||||
|
|
||||||
const handleClick = (e) => {
|
const handleClick = (e) => {
|
||||||
/*
|
if (!e.composedPath().includes(ref.current)
|
||||||
this handles inside click as well due to bubbling,
|
) {
|
||||||
sets the open/close state of drop down
|
e.stopPropagation() // prevents mouse from immediately clicking nav button if over it
|
||||||
*/
|
dispatch({ type: 'set-help', status: false })
|
||||||
!e.composedPath().includes(ref.current) && dispatch({ type: 'set-help', status: false })
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const handleTimeUpdate = (e) => {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const ref = useRef()
|
|
||||||
const vidRef = useRef()
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!status) return
|
||||||
|
|
||||||
document.addEventListener( // handles click outside buttona & dropdown
|
document.addEventListener( // handles click outside buttona & dropdown
|
||||||
'pointerdown',
|
'click',
|
||||||
handleClick
|
handleClick
|
||||||
,
|
,
|
||||||
{ capture: true } // capture phase to allow for stopPropogation on others
|
{ capture: true } // capture phase to allow for stopPropogation on others
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => document.removeEventListener('pointerdown', handleClick)
|
return () => {
|
||||||
|
document.removeEventListener('click', handleClick, { capture: true }) // important to include options if it was specified
|
||||||
|
}
|
||||||
|
|
||||||
|
}, [status])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const arr = [1, 2, 3]
|
||||||
|
|
||||||
|
const ref = useRef(null)
|
||||||
|
const [state, carouselDispatch] = useReducer(reducer, { rect: window.innerHeight * 0.6, pg: 0, dragLeft: 0, dragging: false })
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const updateSize = useCallback(
|
||||||
|
debounce(
|
||||||
|
() => {
|
||||||
|
carouselDispatch({ type: 'resize' })
|
||||||
|
}
|
||||||
|
, 200
|
||||||
|
)
|
||||||
|
, []
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
window.addEventListener('resize', updateSize)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const dispatch = useDispatch()
|
|
||||||
const [open, setOpen] = useState(false)
|
|
||||||
|
|
||||||
const status = useSelector(state => state.ui.help)
|
|
||||||
|
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
return <div className="absolute w-1/5 h-1/5 left-0 top-0 right-0 bottom-0 m-auto bg-green-200
|
return <div className="absolute h-3/5 left-0 top-0 right-0 bottom-0 m-auto bg-transparent
|
||||||
flex flex-col items-center
|
flex flex-col items-center
|
||||||
"
|
"
|
||||||
// return <div className="absolute w-full h-full bg-green-200"
|
style={{
|
||||||
// onClick={handleInsideClick}
|
width: 1 * state.rect,
|
||||||
|
}}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
>
|
>
|
||||||
<MdCancel className="btn-green absolute h-7 w-auto right-4 top-4"/>
|
<div className='absolute top-0 overflow-visible bg-green-400 h-full'
|
||||||
<Carousel />
|
|
||||||
|
onMouseDown={() => carouselDispatch({ type: 'drag-start' })}
|
||||||
|
onMouseMove={(e) => e.buttons == 1 && carouselDispatch({ type: 'drag', move: e.movementX })}
|
||||||
|
onMouseUp={() => carouselDispatch({ type: 'drag-end' })}
|
||||||
|
|
||||||
|
style={{
|
||||||
|
width: 1 * state.rect,
|
||||||
|
transform: `translateX(${state.dragging ? -state.dragLeft : -state.pg * state.rect}px)`,
|
||||||
|
transition: state.dragging ? null : elastic
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
arr.map((e, idx) => {
|
||||||
|
|
||||||
|
return <div key={idx} style={{}}>
|
||||||
|
hi {e}
|
||||||
|
</div>
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='select-none absolute w-12 h-12 top-0 bottom-0 my-auto -left-24 fill-current bg-gray-100 rounded-full'
|
||||||
|
onClick={() => carouselDispatch({ type: "move", del: -1 })}
|
||||||
|
>
|
||||||
|
<MdArrowBack className="w-full h-full text-gray-700 p-3" />
|
||||||
|
</div>
|
||||||
|
<div className='select-none absolute w-12 h-12 top-0 bottom-0 my-auto -right-24 fill-current bg-gray-100 rounded-full'
|
||||||
|
onClick={() => carouselDispatch({ type: "move", del: 1 })}
|
||||||
|
>
|
||||||
|
<MdArrowForward className="w-full h-full text-gray-700 p-3" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex w-full -bottom-8 absolute flex justify-center items-center">
|
||||||
|
{arr.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>
|
||||||
|
<MdCancel className="btn-green absolute h-7 w-auto right-4 top-4"
|
||||||
|
onClick={() => dispatch({ type: 'set-help', status: false })}
|
||||||
|
/>
|
||||||
</div >
|
</div >
|
||||||
} else {
|
} else {
|
||||||
return null
|
return null
|
||||||
|
|
|
@ -31,6 +31,7 @@ export const NavBar = () => {
|
||||||
const modified = useSelector(state => state.ui.modified)
|
const modified = useSelector(state => state.ui.modified)
|
||||||
const fileName = useSelector(state => state.ui.fileName)
|
const fileName = useSelector(state => state.ui.fileName)
|
||||||
const mode = useSelector(state => state.ui.mode)
|
const mode = useSelector(state => state.ui.mode)
|
||||||
|
const help = useSelector(state => state.ui.help)
|
||||||
|
|
||||||
const boolOp = (code) => {
|
const boolOp = (code) => {
|
||||||
if (sce.selected.length != 2 || !sce.selected.every(e => e.userData.type == 'mesh')) {
|
if (sce.selected.length != 2 || !sce.selected.every(e => e.userData.type == 'mesh')) {
|
||||||
|
@ -194,7 +195,10 @@ export const NavBar = () => {
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className='w-auto h-full flex-1 items-center justify-end flex-shrink-1 hidden md:flex'>
|
<div className='w-auto h-full flex-1 items-center justify-end flex-shrink-1 hidden md:flex'>
|
||||||
<MdHelpOutline className="btn-green w-auto h-full p-3" onClick={()=>dispatch({type:'set-help', status:true})}/>
|
<MdHelpOutline className="btn-green w-auto h-full p-3" onClick={() => {
|
||||||
|
dispatch({ type: 'set-help', status: true })
|
||||||
|
}
|
||||||
|
} />
|
||||||
<a href='https://github.com/twpride/three.cad' className='h-full w=auto'>
|
<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>
|
<FaGithub className="btn-green w-auto h-full p-3.5"></FaGithub>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -199,6 +199,10 @@ export function ui(state = defaultUIState, action) {
|
||||||
return update(state, {
|
return update(state, {
|
||||||
help: { $set: action.status }
|
help: { $set: action.status }
|
||||||
})
|
})
|
||||||
|
case 'toggle-help':
|
||||||
|
return update(state, {
|
||||||
|
help: { $set: !state.help }
|
||||||
|
})
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
|
|
Loading…
Reference in New Issue