1.0代码 同步代码仓库 : https://gitee.com/honbingitee/ruyi-lowcode. src/component/BoxShadow/index.tsx
/*
* @Author: hongbin
* @Date: 2022-05-02 21:20:18
* @LastEditors: hongbin
* @LastEditTime: 2022-05-04 08:28:09
* @Description:box-shadow pick
*/
import { FC, ReactElement, useEffect, useRef } from "react";
import styled, { css } from "styled-components";
import { IShadow } from "../ElementProvider/ElementList";
import ProgressBar from "../ProgressBar";
interface IProps {
style?: React.CSSProperties;
shadow: IShadow;
setShadowItem: (key: keyof IShadow, val: number | boolean) => void;
onCancel: () => void;
onCompute: () => void;
}
const BoxShadowPick: FC<IProps> = ({ style = {}, shadow, setShadowItem, onCancel, onCompute }): ReactElement => {
const wrapRef = useRef<HTMLDivElement>(null);
const panelRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (wrapRef.current && panelRef.current) {
const { offsetWidth } = wrapRef.current;
panelRef.current.style["width"] = offsetWidth / 2 + "px";
panelRef.current.style["height"] = offsetWidth / 2 + "px";
}
}, []);
return (
<Container style={{ ...style }} ref={wrapRef}>
<RowFlex>
<Button onClick={() => setShadowItem("inset", false)} selected={!shadow.inset}>
外阴影
</Button>
<Button onClick={() => setShadowItem("inset", true)} selected={shadow.inset}>
内阴影
</Button>
</RowFlex>
<Panel ref={panelRef}>
<Spot
style={{
transform: `translate(${shadow.x}px,${shadow.y}px)`,
}}
onMouseDown={(e) => {
const { pageX: startX, pageY: startY } = e;
const maxDistance = panelRef.current!.offsetWidth / 2;
const { x, y } = shadow;
const move = (e: MouseEvent) => {
const disX = x + (e.pageX - startX);
const disY = y + (e.pageY - startY);
if (maxDistance >= Math.abs(disX)) setShadowItem("x", disX);
if (maxDistance >= Math.abs(disY)) setShadowItem("y", disY);
};
const clear = () => {
document.removeEventListener("mousemove", move);
document.removeEventListener("mouseup", clear);
document.removeEventListener("mouseleave", clear);
};
document.addEventListener("mousemove", move);
document.addEventListener("mouseleave", clear);
document.addEventListener("mouseup", clear);
}}
/>
</Panel>
<RowFlex>
<span>模糊</span>
<ProgressBar
value={shadow.blur / 10}
onChange={(percent) => {
setShadowItem("blur", percent * 10);
}}
style={{ width: "9vw" }}
/>
<span>{shadow.blur.toFixed(1)}</span>
</RowFlex>
<RowFlex>
<span>范围</span>
<ProgressBar
value={shadow.spread / 10}
onChange={(percent) => {
setShadowItem("spread", percent * 10);
}}
style={{ width: "9vw" }}
/>
<span>{shadow.spread.toFixed(1)}</span>
</RowFlex>
<RowFlex>
<Button onClick={onCancel} selected={false}>
取消
</Button>
<Button onClick={onCompute} selected={true}>
确定
</Button>
</RowFlex>
</Container>
);
};
export default BoxShadowPick;
const Spot = styled.div`
position: absolute;
width: 0.75vw;
height: 0.75vw;
border-radius: 1vw;
background-color: var(--deep-color, #1340f4);
cursor: pointer;
z-index: 2;
`;
const Panel = styled.div`
background-color: var(--tint-color, #f7f7f7);
position: relative;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
margin-top: 0.5vh;
::before,
::after {
content: "";
border: 1px dotted var(--deep-color, #1340f4);
border-left: none;
border-top: none;
position: absolute;
}
::before {
height: inherit;
}
::after {
width: inherit;
}
`;
const Button = styled.button<{ selected: boolean }>`
cursor: pointer;
border: none;
outline: none;
border-radius: 0.3vh;
width: 40%;
height: 2.3vh;
background-color: var(--tint-color, #eee);
color: var(--deep-color, #999);
letter-spacing: 1px;
font-size: 0.8vw;
transform: 0.3s linear;
transition-property: background-color, color, font-weight;
${(props) =>
props.selected &&
css`
background-color: var(--deep-color, #1340f4);
color: var(--tint-color, #fffae5);
font-weight: bold;
`};
`;
const RowFlex = styled.div`
display: flex;
align-items: center;
width: inherit;
justify-content: space-evenly;
`;
const Container = styled.div`
width: 15vw;
height: 30vh;
border-radius: 1vh;
background: #fff;
box-shadow: 1px 2px 3px 1px #ccc;
z-index: 1;
display: flex;
justify-content: space-evenly;
align-items: center;
flex-direction: column;
padding: 1vh 0;
`;