react fibre接收后台数据,实时更新物体位置


前言

共同效果:前端获取后台位置信息,实现物体移动。

原本的效果(按钮)

(如效果图1)通过按钮实现:点击一次鼠标,物体改变一次位置。

更改效果(无按钮)

(如效果图2)物体实时获取后台信息,自动更换移动位置。

效果1效果图1在这里插入图片描述
效果图2


一、按钮实现物体移动?

1. 代码拆解

思路:通过索引index获取data数据对象,鼠标按钮控制index增加,进而获取下一位物体的位置信息。

2. 完整代码

import React, { Component } from 'react';
import styled from "styled-components";
import { Canvas } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import { Suspense } from "react";
// 3d模型导入
···

const Button = styled.button`
(按钮的css)
  `;

let url = "后台接口url"
let start, goods;
const period = 4 // 数据周期为4

export default class All extends Component {
//react中的三大组件之一:state
    state = {
        index: 0,	//索引
        datas: []	//数据集
    }

	//生命周期function:将后台获取的数据存入state中
    componentDidMount() {

        //fetch默认式get请求,所以请求头设置部分可以省略
        fetch(url)
            .then(res => res.json())// 不是用户需要的数据,通过return返回给浏览器
            .then(data => {// 服务器返回给客户端的数据

                // console.log(data)
                //把数据赋值给 datas 然后渲染在页面上
                this.setState({
                    datas: data
                })
                //console.log(data)
            })

    }
//按钮点击函数
    change = () => {
        //遍历完成后,将state中的index=0重新遍历
        if (goods.length !==0) {//goods获取一个对象数组,当数组为零,就修改state的index重新遍历
            this.setState({
                index: this.state.index + 1
            })
        } else {
            this.setState({
                index: this.state.index=0
            })
        }
        //再次渲染,修改物体位置
        this.render()
    }
    
    render() {
       // console.log("index=", this.state.index)
        let { index, datas } = this.state

        // 获取本次交互物品数据
        start = period * index  //index=0

        goods = datas.slice(start, start + period) // [0, 4) [4, 8)

        console.log(goods)

        return (
            <>

                <div>
                    <Button onClick={this.change}>变换位置</Button>
                </div>


                <Canvas>
                    {/* 3d模型放置 */}
                    <Suspense fallback={null}>

                        <Table position={[0, 0, 0]} />

                        {goods.map((item, index) => {
                          
                            var x=item.x-100;
                            var y=item.y;
                            //角度转弧度
                            var angle = (item.Angle * Math.PI / 180)
                            // console.log(angle)
                            return (

                                <mesh key={index} position={[x, y, 2]} rotation={[angle,0,Math.PI]}>

                                    {this.switchGoods(item.Name)}
                                </mesh>
                            );
                        })}

                        <OrbitControls />
                    </Suspense>
                </Canvas>

            </>
        );


    }

    switchGoods = (type) => {

        switch (type) {
            case 'cup':
                return (<Cup />)
            case 'projector':
                return (<Projector />)
            case 'trash':
                return (<TrashCan />)
            case 'mecanum':
                return (<Mecanum />)
            default:
                break;
        }

    }

}

二、无按钮实现实时移动

1.代码拆解

思路:通过定时执行,替换鼠标点击事件。

重点代码:定时执行(iTimer函数需要在render中调用)

iTimer = (goods) => {
        console.log(goods)
        this.timer = setTimeout(async () => {
            //遍历完成后,将state中的index=0重新遍历
            if (goods.length !==0) {
                this.setState({
                    index: this.state.index + 1
                })
            } else {
                this.setState({
                    index: 0
                })
            }
        }, 100)

    }

2. 完整代码

import React, { Component } from 'react';
import { Canvas } from "@react-three/fiber";
import { OrbitControls } from "@react-three/drei";
import { Suspense } from "react";
// 3d模型导入
、、、



let url = "、、、"
let start, goods;
const period = 1 // 数据周期为1,逐个获取

export default class All extends Component {

    state = {
        index: 0,
        datas: []
    }


    componentDidMount() {//生命周期function

        //fetch默认式get请求,所以请求头设置部分可以省略
        fetch(url)
            .then(res => res.json())// 不是用户需要的数据,通过return返回给浏览器
            .then(data => {// 服务器返回给客户端的数据

                // console.log(data)
                //把数据赋值给 datas 然后渲染在页面上
                this.setState({
                    datas: data
                })
                console.log(data)
            })

    }
//定时执行(关键代码)
    iTimer = (goods) => {
        console.log(goods)
        this.timer = setTimeout(async () => {
            //遍历完成后,将state中的index=0重新遍历
            if (goods.length !==0) {
                this.setState({
                    index: this.state.index + 1
                })
            } else {
                this.setState({
                    index: 0
                })
            }
        }, 100)

    }

    render() {
        //console.log("index=", this.state.index)
        let { index, datas } = this.state

        // 获取本次交互物品数据
        start = period * index  //index=0

        goods = datas.slice(start, start + period) // 每次只取一个物品位置
        //定时执行
        this.iTimer(goods)
        
        return (
            <>

                <Canvas>
                    {/* 3d模型放置 */}
                    <Suspense fallback={null}>

                        <Table position={[0, 0, 0]} />
                     //map循环遍历
                        {goods.map((item, index) => {

                            var x = item.x - 100;
                            var y = item.y;
                            //角度转弧度
                            var angle = (item.Angle * Math.PI / 180)
                            // console.log(angle)
                            return (

                                <mesh key={index} position={[x, y, 2]} rotation={[angle, 0, Math.PI]}>

                                    {this.switchGoods(item.Name)}
                                </mesh>
                            );
                        })}

                        <OrbitControls />
                    </Suspense>
                </Canvas>

            </>
        );


    }
//按照物体名称,渲染3d物体
    switchGoods = (type) => {

        switch (type) {
            case 'cup':
                return (<Cup />)
            case 'projector':
                return (<Projector />)
            case 'trash':
                return (<TrashCan />)
            case 'mecanum':
                return (<Mecanum />)
            default:
                break;
        }

    }

}

3. 遇到的问题集

3.1 setInterval()越来越快的问题

  • setInterval()

setInterval()方法可按照指定的周期来调用函数或者计算表达式(以毫秒为单位)

语法:

setInterval(函数表达式,毫秒数);

setInterval()会不停的调用函数,直到clearInterval()被调用或者窗口被关闭,由
setInterval()返回的ID值可用作clearInterval()方法的参数。

  • setTimeout

setTimeout()方法用于在指定毫秒数后再调用函数或者计算表达式(以毫秒为单位)

语法:

setTimeout(函数表达式,毫秒数);

setTimeout()只执行函数一次,如果需要多次调用可以使用setInterval(),或者在函数体内再次调用setTimeout()

  • 区别
  1. setTimeout()方法只运行一次,也就是说当达到设定的时间后就出发运行指定的代码,运行完后就结束了,如果还想再次执行同样的函数,可以在函数体内再次调用setTimeout(),可以达到循环调用的效果。
  2. setInterval()是循环执行的,即每达到指定的时间间隔就执行相应的函数或者表达式,是真正的定时器。

总结

react是个框架,react fiber是一种协调器。Fiber 协调器的主要目标是增量渲染,更好更平滑地渲染 UI 动画和手势,以及用户互动的响应性。
所以,react又或者是react fiber中遇到的逻辑问题、语法问题等,通通都可以转化为底层JavaScript问题进行思考。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值