react webgl_使用React-3光纤将具有可重用WebGL组件的SVG分开

本文介绍了如何结合React和Three.js在3D环境中解析SVG,利用react-three-fiber将场景图分解为可重用组件。通过示例展示了如何设置场景、转换SVG为形状并添加动画效果,实现SVG元素的动态过渡。
摘要由CSDN通过智能技术生成
react webgl

react webgl

PullingApartSVGs_featured

We will be looking at how to pull apart SVGs in 3D space with Three.js and React, using abstractions that allow us to break the scene graph into reusable components.

我们将研究如何使用Three.js和React在3D空间中拆分SVG,并使用抽象方法将场景图分解为可重用的组件。

React和Three.js,有什么问题? (React and Three.js, what’s the problem?)

My background in the past had more to do with front-end work than design, and React has been my preferred tool for a couple of years now. I like it because it pretty much maps the way i think. The ideas in my head are puzzle-pieces, which in React turn to composable components. It makes prototyping faster, and from a visual/design standpoint, it’s even fun, because it allows you to play around without repercussions. If everything is a self-contained lego-brick, you can rip it out, place it here, or there, and observe the result from different angles and perspectives. Especially for visual coding this can make a difference.

我过去的背景与前端工作多于设计,而React则是我几年来的首选工具。 我喜欢它,因为它几乎可以映射我的思维方式。 我脑海中的想法是拼图,在React中,拼图变成了可组合的组件。 它使原型制作变得更快,并且从视觉/设计的角度来看,它甚至很有趣,因为它使您可以随意玩耍。 如果一切都是独立的乐高积木,则可以将其撕裂,放在此处或那里,然后从不同的角度和角度观察结果。 特别是对于视觉编码,这可以有所作为。

The problems that arise when handling programming tasks in an imperative way are always the same. Once we have created a sufficiently complex dependency-graph then things tend to be cobbled together, which causes the whole to be less flexible. Adding, updating or deleting items in sync with state and other operations can get complex. Orchestrating animations makes it even worse, because now you need to await animations to conclude before you continue with other operations and so on. Without a clear component-model it can be a reasonable challenge to keep it all together.

以命令方式处理编程任务时出现的问题始终是相同的。 一旦我们创建了足够复杂的依赖关系图,那么事物就会趋于齐整,这将导致整体的灵活性降低。 与状态和其他操作同步添加,更新或删除项目会变得很复杂。 编排动画会使情况变得更糟,因为现在您需要等待动画结束后再继续其他操作,依此类推。 如果没有清晰的组件模型,将它们保持在一起可能是一个合理的挑战。

We run into this when working with user interfaces, as well as when creating scenes with Three.js, which can lend to especially unwieldy structures as it forces us to create a ton of objects that we have to track, mutate and manage. But React can solve that, too.

在使用用户界面以及使用Three.js创建场景时,我们会遇到这种情况,这可能会导致特别笨拙的结构,因为它迫使我们创建大量必须跟踪,诱变和管理的对象。 但是React也可以解决这个问题。

Think of React as a standard that defines what a component is and how it functions. React needs a so called “reconciler” to tell it what to do with these components and how to render them into a host. The browsers dom is a host, hence the react-dom package, which instructs React about the dom. React-native is another one you may be familiar with, but really there are dozens, reaching into all kinds of platforms, from AR, VR, console shells to, you guessed it, Three.js. The reconciler we will be using in this tutorial is called react-three-fiber, it renders components into a Three.js scene graph. Think of it as a portal into Three.js.

将React视为定义组件是什么以及如何工作的标准。 React需要一个所谓的“协调器”来告诉它如何使用这些组件以及如何将它们渲染到主机中。 浏览器dom是主机,因此是react-dom软件包,用于指示React有关dom的信息。 React-native是您可能熟悉的另一种,但实际上有数十种,涉及到从AR,VR,控制台shell到您猜到的Three.js的各种平台。 我们在本教程中将使用的协调器称为react-three-fiber ,它将组件渲染成Three.js场景图。 可以将其视为Three.js的门户。

Let’s build!

让我们开始吧!

设置场景 (Setting up the scene)

Our portal into Three.js will be react-three-fiber’s “Canvas” component. Everything that goes in there will be cast into Three.js-native objects. The following will create a responsive canvas with some lights in it.

我们进入Three.js的门户将是react-three-fiber的“ Canvas”组件。 其中的所有内容都将转换为Three.js本机对象。 下面将创建一个响应式画布,其中包含一些灯光。

function App() {
  return (
    <Canvas>
      <ambientLight intensity={0.5} />
      <spotLight intensity={0.5} position={[300, 300, 4000]} />
    </Canvas>
  )
}

将SVG转换为形状 (Converting SVGs into shapes)

Our goal is to extract SVG paths, once we have that we can display them in all sorts of interesting ways. We will be using fairly simple sketches for that, they won’t create many layers and the effect will be less pronounced.

我们的目标是提取SVG路径,一旦有了我们就可以用各种有趣的方式显示它们。 为此,我们将使用相当简单的草图,它们不会创建很多层,效果不会那么明显。

example

In order to transform SVGs into shape geometries we use Three.js’s SVGLoader. The following will give us a nested array of objects that contains the shapes and colors. We collect the index, too, which we will be using to offset the z-vector.

为了将SVG转换为形状几何,我们使用Three.js的SVGLoader 。 下面将为我们提供一个嵌套的对象数组,其中包含形状和颜色。 我们也收集索引,我们将使用该索引来偏移z矢量。

const svgResource = new Promise(resolve =>
  new loader().load(url, shapes =>
    resolve(
      flatten(
        shapes.map((group, index) =>
          group.toShapes(true).map(shape => ({ shape, color: group.color, index }))
        )
      )
    )
  )
)

Next we define a “Shape” component which renders a single shape. Each shape is offset 50 units by its own index.

接下来,我们定义一个“形状”组件,该组件呈现单个形状。 每个形状通过其自己的索引偏移50个单位。

function Shape({ shape, position, color, opacity, index }) {
  return (
    <mesh position={[0, 0, index * 50]}>
      <meshPhongMaterial attach="material" color={color} />
      <shapeBufferGeometry attach="geometry" args={[shape]} />
    </mesh>
  )
}

All we are missing now is a component that maps through the shapes we have created. Since the resource we have created is a promise we have to await its resolved state. Once it has loaded, we wrote it into the local component state and forward each shape to the “Shape” component we have just created.

我们现在所缺少的只是一个可以映射我们创建的形状的组件。 由于我们创建的资源是一个承诺,因此我们必须等待其解决状态。 加载后,我们将其写入本地组件状态,并将每个形状转发到我们刚创建的“ Shape”组件。

function Scene() {
  const [shapes, set] = useState([])
  useEffect(() => void svgResource.then(set), [])
  return (
    <group>
      {shapes.map(item => <Shape key={item.shape.uuid} {...item} />)}
    </group>
  )
}

This is it, our canvas shows an offset SVG.

就是这样,我们的画布显示了偏移SVG。

演示地址

添加动画(Adding animations)

If you wanted to animate Three.js you would most likely do it manually and use tools like GSAP. And since we want to animate elements that go in and out you need to have some system in place that orchestrates it, which is not an easy task to pull off.

如果要对Three.js进行动画处理,则很可能会手动进行,并使用GSAP之类的工具。 而且,由于我们要对进出的元素进行动画处理,因此您需要有一些适当的系统来对其进行编排,而这并非易事。

Here comes the nice part, we are rendering React components and that opens up a lot of possibilities. We can use pretty much everything that exists in the eco system, including animation and transition tools. In this case we use react-spring.

好的部分来了,我们正在渲染React组件,这带来了很多可能性。 我们可以使用生态系统中几乎所有的东西,包括动画和过渡工具。 在这种情况下,我们使用react-spring

Really all we need to do is convert out shapes into a transition-group. A transition group is something that watches state for changes and helps to retain and transition old state until it can be safely removed. In react-springs case it is called “useTransition”. It takes the original data, shapes in this case, keys in order to identify changes in the data-set, and a couple of lifecycles in which we can define what happens when state is added, removed or changed.

实际上,我们所需要做的就是将形状转换为过渡组。 过渡组可以监视状态的变化,并有助于保留和过渡旧状态,直到可以安全地将其删除为止。 在react-springs情况下,它称为“ useTransition”。 它使用原始数据,这种情况下的形状,用于识别数据集中更改的键以及几个生命周期,在这些生命周期中,我们可以定义在添加,删除或更改状态时发生的情况。

The following takes care of everything. If shapes are added, they will transition into the scene in a trailed motion. If shapes are removed, they will transition out.

以下内容将解决所有问题。 如果添加了形状,它们将以尾随动作过渡到场景中。 如果删除形状,它们将过渡出来。

const transitions = useTransition(shapes, item => item.shape.uuid, {
  from: { position: [0, 50, -200], opacity: 0 },
  enter: { position: [0, 0, 0], opacity: 1 },
  leave: { position: [0, -50, 10], opacity: 0 },
})

return (
  <group>
    {transitions.map(({ item, key, props }) => <Shape key={key} {...item} {...props} />)}
  </group>
)

useTransition creates an array of objects which contain generated keys, the data items (our shapes) and animated properties. We spread everything over the Shape component. Now we just need to prepare that component to receive animated values and we are done.

useTransition创建一个对象数组,其中包含生成的键,数据项(我们的形状)和动画属性。 我们将所有内容散布在Shape组件上。 现在,我们只需要准备该组件以接收动画值就可以了。

react-spring exports a little helper called “animated”, as well as a shortcut called “a”. If you extend any element with it, it will be able to handle these properties. Basically, if you had a div, it would become a.div, if you had a mesh, it now becomes a.mesh.

react-spring会输出一个称为“动画”的小助手,以及一个称为“ a”的快捷方式。 如果使用它扩展任何元素,它将能够处理这些属性。 基本上,如果您有一个div,它将变为a.div;如果您有一个网格,则现在变为a.mesh。

演示地址

I hope you had fun! You will find detailed explanations for everything in the respective docs for react-three-fiber and react-spring. The full code for the original demo can be found here.

希望你玩得开心! 您可以在相应的文档中找到有关React三纤维和React弹簧的详细说明。 原始演示的完整代码可以在这里找到。

翻译自: https://tympanus.net/codrops/2019/04/12/pulling-apart-svgs-with-reusable-webgl-components-using-react-three-fiber/

react webgl

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值