Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 有没有办法在ThreeJs中使用dat.gui.js构建范围滑块?_Javascript_Three.js_Dat.gui - Fatal编程技术网

Javascript 有没有办法在ThreeJs中使用dat.gui.js构建范围滑块?

Javascript 有没有办法在ThreeJs中使用dat.gui.js构建范围滑块?,javascript,three.js,dat.gui,Javascript,Three.js,Dat.gui,我想在我的设计中有一个范围滑块,虽然我有一个数字滑块,但我想有一个我可以选择一个数字范围来传递,如下图所示。 除了在dat.gui.js文件中进行更改并为范围滑块添加功能之外,还有其他选择吗?没有,这是不可能的。控制器的创建仅基于所创建的值类型。您必须破解它,发出拉请求,或者只使用两个滑块(最小/最大)。我在React中实现了一个dat gui范围滑块,看起来很像(使用材质ui)。也许这会帮助一些人尝试创建他们自己的,所以我想我会把它贴在这里 import React,{useffect,us

我想在我的设计中有一个范围滑块,虽然我有一个数字滑块,但我想有一个我可以选择一个数字范围来传递,如下图所示。


除了在dat.gui.js文件中进行更改并为范围滑块添加功能之外,还有其他选择吗?

没有,这是不可能的。控制器的创建仅基于所创建的值类型。您必须破解它,发出拉请求,或者只使用两个滑块(最小/最大)。

我在React中实现了一个dat gui范围滑块,看起来很像(使用材质ui)。也许这会帮助一些人尝试创建他们自己的,所以我想我会把它贴在这里

import React,{useffect,useRef,useCallback}来自“React”;
从“类名称”导入cx;
从“@material ui/core”导入{makeStyles,Theme,createStyles};
从“lodash/clamp”进口夹具;
从“utils/useEventCallback”导入useEventCallback;
功能asc(a:编号,b:编号){
返回a-b;
}
函数findClosest(值:any,currentValue:number){
const{index:closestinex}=values.reduce((acc:{distance:number;}}| null,value:number,index:number)=>{
常数距离=数学绝对值(currentValue-value);
if(acc==null | |距离({left:`${percent}%`}),
闰:(百分比:数字)=>({width:`${percent}%`}),
};
const trackMouse=(event:React.MouseEvent)=>({x:event.clientX,y:event.clientY,});
const useStyles=makeStyles((主题:主题)=>
创建样式({
根目录:{
宽度:“100%”,
框大小:“边框框”,
显示:“内联块”,
光标:“ew resize”,
touchAction:'无',
边框:“3px实心#1a1a1a”,
},
滑块:{
显示:“块”,
位置:'相对',
背景颜色:“#141414”,
背景图片:`线性渐变(90度,${theme.palete.primary.light},${theme.palete.primary.light})`,//#2fa1d6,#2fa1d6)`,
背景重复:“不重复”,
高度:“14px”,
},
})
)
界面道具{
数值:数字[];
min:编号;
最大:数量;
步骤:编号;
类名?:字符串;
颜色?:字符串;
默认值?:数字[];
禁用?:布尔值;
onChange?:(事件:React.MouseEvent,值:any)=>void;
onChangeCommitted?:(事件:React.MouseEvent,值:any)=>void;
onMouseDown?:(事件:React.MouseEvent)=>void;
}
导出默认函数范围滑块({
类名,
颜色='主',
默认值,
禁用=错误,
最大值,
闵,
一旦改变,
一旦承诺,
一下楼,
步
值:valuesProp,
……其他
}:道具){
const classes=useStyles();
常量sliderRef=useRef();
const previousIndex=useRef();
let values=[…valuesProp].sort(asc);
值=值。映射((值:数字)=>钳制(值、最小值、最大值));
const getNewValue=useCallback(
({mouse,move=false,value:values2,source})=>{
const{current:slider}=sliderRef;
const{width,left}=slider.getBoundingClientRect();
常量百分比=(mouse.x-left)/宽度;
让新价值;
newValue=percentToValue(百分比、最小值、最大值);
newValue=roundValueToStep(newValue,step);
新值=夹具(新值、最小值、最大值);
设activeIndex=0;
如果(!移动){
activeIndex=findClosest(值2,新值);
}否则{
activeIndex=previousIndex.current;
}
const previousValue=newValue;
newValue=setValueIndex({
值:值2,
来源:,
新价值,
索引:activeIndex,
}).分类(asc);
activeIndex=newValue.indexOf(以前的值);
previousIndex.current=活动索引;
返回{newValue,activeIndex};
},
[最大、最小、步长]
);
const handleMouseMove=useEventCallback((事件:React.MouseEvent)=>{
const mouse=trackMouse(事件);
常量{newValue}=getNewValue({
老鼠
搬家:没错,
价值观
资料来源:valuesProp,
});
if(onChange){
onChange(事件,newValue);
}
});
康斯塔
import React, { useEffect, useRef, useCallback } from 'react';
import cx from 'classnames';
import { makeStyles, Theme, createStyles } from '@material-ui/core';
import clamp from 'lodash/clamp';
import useEventCallback from 'utils/useEventCallback';

function asc(a: number, b: number) {
    return a - b;
}

function findClosest(values: any, currentValue: number) {
    const { index: closestIndex } = values.reduce((acc: { distance: number; } | null, value: number, index: number) => {
        const distance = Math.abs(currentValue - value);

        if (acc === null || distance < acc.distance || distance === acc.distance) {
            return {
                distance,
                index,
            };
        }

        return acc;
    }, null);
    return closestIndex;
}

function valueToPercent(value: number, min: number, max: number) {
    return ((value - min) * 100) / (max - min);
}

function percentToValue(percent: number, min: number, max: number) {
    return (max - min) * percent + min;
}

function getDecimalPrecision(num: number) {
    // This handles the case when num is very small (0.00000001), js will turn this into 1e-8.
    // When num is bigger than 1 or less than -1 it won't get converted to this notation so it's fine.
    if (Math.abs(num) < 1) {
        const parts = num.toExponential().split('e-');
        const matissaDecimalPart = parts[0].split('.')[1];
        return (
            (matissaDecimalPart ? matissaDecimalPart.length : 0) +
            parseInt(parts[1], 10)
        );
    }

    const decimalPart = num.toString().split('.')[1];
    return decimalPart ? decimalPart.length : 0;
}

function roundValueToStep(value: number, step: number) {
    const nearest = Math.round(value / step) * step;
    return Number(nearest.toFixed(getDecimalPrecision(step)));
}

function setValueIndex({ values, source, newValue, index }: any) {
    // Performance shortcut
    if (values[index] === newValue) {
        return source;
    }

    const output = [...values];
    output[index] = newValue;
    return output;
}

const axisProps = {
    offset: (percent: number) => ({ left: `${percent}%` }),
    leap: (percent: number) => ({ width: `${percent}%` }),
};

const trackMouse = (event: React.MouseEvent) => ({ x: event.clientX, y: event.clientY, });

const useStyles = makeStyles((theme: Theme) =>
    createStyles({
        root: {
            width: '100%',
            boxSizing: 'border-box',
            display: 'inline-block',
            cursor: 'ew-resize',
            touchAction: 'none',
            border: '3px solid #1a1a1a',
        },
        slider: {
            display: 'block',
            position: 'relative',
            backgroundColor: '#141414',
            backgroundImage: `linear-gradient(90deg, ${theme.palette.primary.light}, ${theme.palette.primary.light})`, //#2fa1d6, #2fa1d6)",
            backgroundRepeat: 'no-repeat',
            height: '14px',
        },
    })
)

interface Props {
    values: number[];
    min: number;
    max: number;
    step: number;
    className?: string;
    color?: string;
    defaultValue?: number[];
    disabled?: boolean;
    onChange?: (event: React.MouseEvent, value: any) => void;
    onChangeCommitted?: (event: React.MouseEvent, value: any) => void;
    onMouseDown?: (event: React.MouseEvent) => void;
}
export default function RangeSlider({
    className,
    color = 'primary',
    defaultValue,
    disabled = false,
    max,
    min,
    onChange,
    onChangeCommitted,
    onMouseDown,
    step,
    values: valuesProp,
    ...other
}: Props) {
    const classes = useStyles();
    const sliderRef = useRef<any>();
    const previousIndex = useRef<any>();

    let values = [...valuesProp].sort(asc);
    values = values.map((value: number) => clamp(value, min, max));

    const getNewValue = useCallback(
        ({ mouse, move = false, values: values2, source }) => {

            const { current: slider } = sliderRef;
            const { width, left } = slider.getBoundingClientRect();
            const percent = (mouse.x - left) / width;

            let newValue;
            newValue = percentToValue(percent, min, max);
            newValue = roundValueToStep(newValue, step);
            newValue = clamp(newValue, min, max);
            let activeIndex = 0;

            if (!move) {
                activeIndex = findClosest(values2, newValue);
            } else {
                activeIndex = previousIndex.current;
            }

            const previousValue = newValue;
            newValue = setValueIndex({
                values: values2,
                source,
                newValue,
                index: activeIndex,
            }).sort(asc);
            activeIndex = newValue.indexOf(previousValue);
            previousIndex.current = activeIndex;


            return { newValue, activeIndex };


        },
        [max, min, step]
    );

    const handleMouseMove = useEventCallback((event: React.MouseEvent) => {
        const mouse = trackMouse(event);

        const { newValue } = getNewValue({
            mouse,
            move: true,
            values,
            source: valuesProp,
        });

        if (onChange) {
            onChange(event, newValue);
        }
    });

    const handleMouseEnter = useEventCallback((event: React.MouseEvent) => {
        // If the slider was being interacted with but the mouse went off the window
        // and then re-entered while unclicked then end the interaction.
        if (event.buttons === 0) {
            handleMouseEnd(event);
        }
    });

    const handleMouseEnd = useEventCallback((event: React.MouseEvent) => {
        const mouse = trackMouse(event);

        const { newValue } = getNewValue({
            mouse,
            values,
            source: valuesProp,
        });

        if (onChangeCommitted) {
            onChangeCommitted(event, newValue);
        }

        window.removeEventListener('mousemove', handleMouseMove);
        window.removeEventListener('mouseup', handleMouseEnd);
        window.removeEventListener('mouseenter', handleMouseEnter);
    });

    useEffect(() => {
        return () => {
            window.removeEventListener('mousemove', handleMouseMove);
            window.removeEventListener('mouseup', handleMouseEnd);
            window.removeEventListener('mouseenter', handleMouseEnter);
        };
    }, [disabled, handleMouseEnter, handleMouseEnd, handleMouseMove]);

    const handleMouseDown = useEventCallback((event: React.MouseEvent) => {
        if (onMouseDown) {
            onMouseDown(event);
        }

        if (disabled) {
            return;
        }

        event.preventDefault();
        const mouse = trackMouse(event);
        const { newValue } = getNewValue({
            mouse,
            values,
            source: valuesProp,
        });

        if (onChange) {
            onChange(event, newValue);
        }

        window.addEventListener('mousemove', handleMouseMove);
        window.addEventListener('mouseenter', handleMouseEnter);
        window.addEventListener('mouseup', handleMouseEnd);
    });

    const sliderOffset = valueToPercent(values[0], min, max);
    const sliderLeap = valueToPercent(values[values.length - 1], min, max) - sliderOffset;
    const widthBackground = axisProps.leap(sliderLeap).width;

    const sliderStyle = {
        ...axisProps.offset(sliderOffset),
        ...axisProps.leap(sliderLeap),
        backgroundSize: `${widthBackground}% 100%`,
    };

    return (
        <span
            ref={sliderRef}
            className={cx(classes.root, className)}
            onMouseDown={handleMouseDown}
            {...other}
        >
            <span className={classes.slider} style={sliderStyle} />
            {values.map((value, index) => {
                const percent = valueToPercent(value, min, max);
                const style = axisProps.offset(percent);
                return (
                    <span
                        key={index}
                        role="slider"
                        style={style}
                        data-index={index}
                    />
                );
            })}
        </span>
    );
}

RangeSlider.defaultProps = {
    min: 0,
    max: 100,
    step: 1
}