【问题标题】:createSVGPoint not a function in NextjscreateSVGPoint 不是 Nextjs 中的函数
【发布时间】:2021-01-02 20:50:13
【问题描述】:

我正在使用 Nextjs、React hooks 和 svg 制作一个非常基本的游戏引擎。

我想检测两个 svg 之间的冲突,但我不知道该怎么做。

尝试此语法后

circle.isPointInFill(new DOMPoint(10, 10))

在看到 so-question 后,我转而使用 createSVGPoint

我想使用 React 的 useRef 来获取对 svg 的引用(我真的不想使用 JQuery),但我似乎无法让 createSVGPoint 函数工作,所以我可以使用 isPointInFill 检查点是否为在 svg 中。

我在这里similar problem in Angular 看到了类似的问题,但我不知道如何使用 useRef 来做类似的事情?

document.createElementNS('http://www.w3.org/2000/svg', 'svg');

这是我的 index.js

import Head from 'next/head'
import { useState, useEffect, useRef } from 'react'
import {useKeyPress} from '../hooks/useKeyPress'
import Circle from '../components/svgs/circle'
import Room from '../components/svgs/room'
import utilStyles from '../styles/utils.module.css'

export default function Home() {
  const [ currentXPos, setCurrentXPos ] = useState(500)
  const [ currentYPos, setCurrentYPos ] = useState(500)
  const [ colourIndex, setColourIndex ] = useState(0)

  const circle = useRef()

  const circleColours = [
    "green",
    "orange",
    "red",
    "blue"
  ]

  const upPress = useKeyPress('w');
  const rightPress = useKeyPress('d');
  const leftPress = useKeyPress('a');
  const downPress = useKeyPress('s');

  const setNewXPos = (circle, changeXPos) => {
    let point = circle.createSVGPoint();
    point.x = 40;
    point.y = 32;
    let _newColourIndex = (colourIndex + 1) % 4

    let _newXPos = currentXPos + changeXPos
    if (_newXPos < 50) {
      _newXPos = currentXPos
    } else if (_newXPos > 950) {
      _newXPos = currentXPos
    }

    if (_newXPos % 150 === 0) {
      setColourIndex(_newColourIndex)
    }

    console.log("CHECK IF POINT IN CIRCLE REF", circle.isPointInFill(point))

    setCurrentXPos(_newXPos)
  }

  const setNewYPos = (changeYPos) => {
    let _newColourIndex = (colourIndex + 1) % 4
    let _newYPos = currentYPos + changeYPos
    if (_newYPos < 50) {
      _newYPos = currentYPos
    } else if (_newYPos > 800) {
      _newYPos = currentYPos
    }

    if (_newYPos % 150 === 0) {
      setColourIndex(_newColourIndex)
    }
    
    setCurrentYPos(_newYPos)
  }

  useEffect(() => {
    console.log("CIRCLE", circle.current)
    if (upPress) {
      console.log("UP!")
      setNewYPos(-1)
    }
    if (rightPress) {
      console.log("RIGHT!")
      setNewXPos(circle, 1)
    }
    if (leftPress) {
      console.log("LEFT!")
      setNewXPos(circle, -1)
    }
    if (downPress) {
      console.log("DOWN!")
      setNewYPos(1)
    }
  }, [ 
    currentXPos,
    currentYPos,
    circleColours,
    circle,
    upPress, 
    rightPress, 
    leftPress, 
    downPress
  ])

  return (
    <div className="container">
      <Head>
        <title>Game Engine Thing</title>
      </Head>

      <main>
        <h1 className="title">
         Very Basic React Game Engine {currentXPos} {currentYPos}
        </h1>    

        <Room />

        {currentXPos && <section className={`${utilStyles.gameEnv}`}>
        <svg ref={circle} width="1000" height="1000">
          <Circle
            xPos={currentXPos}
            yPos={currentYPos}
            fill={circleColours[colourIndex]}
          />
        </svg>
        </section>}

      </main>
    </div>
  )
}

完整代码在complete code

【问题讨论】:

  • createSVGPoint 是 元素上的函数,而不是 元素上的函数。

标签: svg next.js collision-detection


【解决方案1】:

所以问题是我用函数引用了哪些对象,为了使某些东西工作得很好,我必须更改我的 SVG 并更改我放置引用的位置。下面是新的 index.js,它现在允许圆圈围绕 svg 路径的边缘移动,就好像路径是房间的墙壁一样。

import Head from 'next/head'
import { useState, useEffect, useRef } from 'react'
import {useKeyPress} from '../hooks/useKeyPress'
import utilStyles from '../styles/utils.module.css'

export default function Home() {
  const [ currentXPos, setCurrentXPos ] = useState(100)
  const [ currentYPos, setCurrentYPos ] = useState(100)
  const [ colourIndex, setColourIndex ] = useState(0)

  const circle = useRef()
  const path = useRef()

  const circleColours = [
    "green",
    "orange",
    "red",
    "blue"
  ]

  const upPress = useKeyPress('w');
  const rightPress = useKeyPress('d');
  const leftPress = useKeyPress('a');
  const downPress = useKeyPress('s');

  const setNewXPos = (changeXPos) => {
    
    let _newColourIndex = (colourIndex + 1) % 4

    let _newXPos = currentXPos + changeXPos

    if (_newXPos % 150 === 0) {
      setColourIndex(_newColourIndex)
    } 

    let point = circle.current.createSVGPoint();
    point.x = _newXPos;
    point.y = currentYPos;

    console.log("CHECK IF POINT IN PATH REF", point, path.current.isPointInFill(point))

    if (path.current.isPointInFill(point)) {
      console.log("GOT HERE!!!!!!")
      setCurrentXPos(_newXPos)
    } else {
      _newXPos = currentXPos
    }
  }

  const setNewYPos = (changeYPos) => {
    let _newColourIndex = (colourIndex + 1) % 4
    let _newYPos = currentYPos + changeYPos


    if (_newYPos % 150 === 0) {
      setColourIndex(_newColourIndex)
    }
    
    let point = circle.current.createSVGPoint();
    point.x = currentXPos;
    point.y = _newYPos;

    console.log("CHECK IF POINT IN PATH REF", point, path.current.isPointInFill(point))

    if (path.current.isPointInFill(point)) {
      setCurrentYPos(_newYPos)
    } else {
      _newYPos = currentYPos
    }

  }

  useEffect(() => {
    console.log("CIRCLE", circle.current)
    if (upPress) {
      console.log("UP!")
      setNewYPos(-1)
    }
    if (rightPress) {
      console.log("RIGHT!")
      setNewXPos(1)
    }
    if (leftPress) {
      console.log("LEFT!")
      setNewXPos(-1)
    }
    if (downPress) {
      console.log("DOWN!")
      setNewYPos(1)
    }
  }, [ 
    currentXPos,
    currentYPos,
    circleColours,
    circle,
    upPress, 
    rightPress, 
    leftPress, 
    downPress
  ])

  return (
    <div className="container">
      <Head>
        <title>Game Engine Thing</title>
      </Head>

      <main>
        <div className={`${utilStyles.mainContainer}`}>
          {currentXPos && <section className={`${utilStyles.gameEnv}`}>
            <svg ref={circle} width="1000" height="800" viewBox="0 0 1000 750" fill="none" xmlns="http://www.w3.org/2000/svg">
              <rect width="1000" height="750" fill="white"/>
              <path ref={path}  fill-rule="evenodd" clip-rule="evenodd" d="M49 51H449V165.239H884V430.332H949V713H214V611.942H172V343.92H49V51Z" fill="#C4C4C4"/>
              <circle  cx={currentXPos} cy={currentYPos} r="40" stroke="green" strokeWidth="4" fill={circleColours[colourIndex]} />
            </svg>
          </section>}
        </div>
        

      </main>
    </div>
  )
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-07-20
    • 2020-11-05
    • 2023-01-14
    • 2021-05-30
    • 2021-08-04
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多