New file |
| | |
| | | import React, { useEffect } from 'react'; |
| | | import { useForm, Controller } from 'react-hook-form'; |
| | | import { |
| | | Box, |
| | | Grid, |
| | | Typography, |
| | | TextField, |
| | | Slider, |
| | | Button, |
| | | Select, |
| | | MenuItem, |
| | | InputLabel, |
| | | FormControl, |
| | | FormHelperText, |
| | | Checkbox, |
| | | FormControlLabel, |
| | | Stack, |
| | | } from '@mui/material'; |
| | | import { useTranslate } from 'react-admin'; |
| | | |
| | | const MapSettings = (props) => { |
| | | const { sprite, onSubmit } = props; |
| | | const translate = useTranslate(); |
| | | |
| | | const { control, handleSubmit, reset, watch, setValue } = useForm({ |
| | | defaultValues: { |
| | | x: sprite?.position.x || 0, |
| | | y: sprite?.position.y || 0, |
| | | scaleX: sprite?.scale.x || 1, |
| | | scaleY: sprite?.scale.y || 1, |
| | | rotation: (sprite?.rotation * 180) / Math.PI || 0, |
| | | copyDirection: 'right', |
| | | copyCount: 1, |
| | | // 其他默认值... |
| | | }, |
| | | }); |
| | | |
| | | // 监听表单值的变化 |
| | | const watchAllFields = watch(); |
| | | |
| | | useEffect(() => { |
| | | if (sprite) { |
| | | reset({ |
| | | x: sprite.position.x, |
| | | y: sprite.position.y, |
| | | scaleX: sprite.scale.x, |
| | | scaleY: sprite.scale.y, |
| | | rotation: (sprite.rotation * 180) / Math.PI, |
| | | // 设置其他字段的初始值 |
| | | }); |
| | | } |
| | | }, [sprite, reset]); |
| | | |
| | | // 更新精灵属性的函数 |
| | | const updateSprite = (data) => { |
| | | if (sprite) { |
| | | sprite.position.x = data.x; |
| | | sprite.position.y = data.y; |
| | | sprite.scale.x = data.scaleX; |
| | | sprite.scale.y = data.scaleY; |
| | | sprite.rotation = (data.rotation * Math.PI) / 180; |
| | | // 更新其他属性... |
| | | } |
| | | }; |
| | | |
| | | // 处理表单提交 |
| | | const onFormSubmit = (data) => { |
| | | updateSprite(data); |
| | | if (onSubmit) { |
| | | onSubmit(data); |
| | | } |
| | | }; |
| | | |
| | | return ( |
| | | <Box component="form" onSubmit={handleSubmit(onFormSubmit)} noValidate sx={{ mt: 2 }}> |
| | | <Grid container spacing={2}> |
| | | {/* 位置 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.position')}</Typography> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Controller |
| | | name="x" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="X" |
| | | type="number" |
| | | fullWidth |
| | | onChange={(e) => { |
| | | field.onChange(e); |
| | | updateSprite({ ...watchAllFields, x: parseFloat(e.target.value) }); |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Controller |
| | | name="y" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="Y" |
| | | type="number" |
| | | fullWidth |
| | | onChange={(e) => { |
| | | field.onChange(e); |
| | | updateSprite({ ...watchAllFields, y: parseFloat(e.target.value) }); |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | |
| | | {/* 缩放 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.scale')}</Typography> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Controller |
| | | name="scaleX" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="Scale X" |
| | | type="number" |
| | | fullWidth |
| | | inputProps={{ step: 0.1, min: 0.1, max: 10 }} |
| | | onChange={(e) => { |
| | | field.onChange(e); |
| | | updateSprite({ ...watchAllFields, scaleX: parseFloat(e.target.value) }); |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Controller |
| | | name="scaleY" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label="Scale Y" |
| | | type="number" |
| | | fullWidth |
| | | inputProps={{ step: 0.1, min: 0.1, max: 10 }} |
| | | onChange={(e) => { |
| | | field.onChange(e); |
| | | updateSprite({ ...watchAllFields, scaleY: parseFloat(e.target.value) }); |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | |
| | | {/* 旋转 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.rotation')}</Typography> |
| | | </Grid> |
| | | <Grid item xs={12}> |
| | | <Controller |
| | | name="rotation" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <Slider |
| | | {...field} |
| | | min={0} |
| | | max={360} |
| | | step={1} |
| | | valueLabelDisplay="auto" |
| | | onChange={(e, value) => { |
| | | field.onChange(value); |
| | | updateSprite({ ...watchAllFields, rotation: value }); |
| | | }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | |
| | | {/* 复制 */} |
| | | <Grid item xs={12}> |
| | | <Typography variant="h6">{translate('map.settings.copy')}</Typography> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Controller |
| | | name="copyDirection" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <FormControl fullWidth> |
| | | <InputLabel>{translate('map.settings.copyDirection')}</InputLabel> |
| | | <Select {...field} label={translate('map.settings.copyDirection')}> |
| | | <MenuItem value="left">{translate('map.settings.left')}</MenuItem> |
| | | <MenuItem value="right">{translate('map.settings.right')}</MenuItem> |
| | | <MenuItem value="up">{translate('map.settings.up')}</MenuItem> |
| | | <MenuItem value="down">{translate('map.settings.down')}</MenuItem> |
| | | </Select> |
| | | </FormControl> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | <Grid item xs={6}> |
| | | <Controller |
| | | name="copyCount" |
| | | control={control} |
| | | render={({ field }) => ( |
| | | <TextField |
| | | {...field} |
| | | label={translate('map.settings.copyCount')} |
| | | type="number" |
| | | fullWidth |
| | | inputProps={{ min: 1 }} |
| | | /> |
| | | )} |
| | | /> |
| | | </Grid> |
| | | |
| | | {/* 提交按钮 */} |
| | | <Grid item xs={12}> |
| | | <Stack direction="row" spacing={2}> |
| | | <Button type="submit" variant="contained" color="primary"> |
| | | {translate('common.submit')} |
| | | </Button> |
| | | <Button variant="outlined" color="secondary" onClick={() => reset()}> |
| | | {translate('common.reset')} |
| | | </Button> |
| | | </Stack> |
| | | </Grid> |
| | | </Grid> |
| | | </Box> |
| | | ); |
| | | }; |
| | | |
| | | export default MapSettings; |