Part 3: Scandi Frontend
Display 3D models on the product page
Last updated
Was this helpful?
Display 3D models on the product page
Last updated
Was this helpful?
Before you start with this section, you need to have a and .
We already have a backend module for our extension, but we need a separate Scandi extension Javascript module, responsible for implementing the frontend functionality. An extension is a reusable package that can be installed on any Scandi theme.
To create an extension, navigate to the root of your CSA application in the terminal. You can using the scandipwa
script:
This script will initialize a new extension named packages/product-3d-scandi
and configure your theme to install it. It will also enable it by setting scandipwa.extensions["product-3d-scandi"]
to true
in package.json
.
We have an API available to get the 3D models for each product. However, due to the design of GraphQL, this data won't be fetched unless the query specifically requests it (this helps save bandwidth on unused fields). Hence, the first step is to update the query so that 3D models are requested as well.
Unlike many other applications, Scandi builds queries at runtime, using its . This means that updating the query for the purposes of an extension is as easy as .
The ProductList
query creator is responsible for making product queries. In particular, we are interested in the _getProductInterfaceFields
method, which is responsible for specifying the product fields we want to query.
The current implementation of _getProductInterfaceFields
already returns multiple fields, represented as an array of strings:
We want to wrap around this method, get the "original" array, and return an array with a new field, "model_3d_urls"
, in addition to the original ones:
If you restart your app and open the Product Detail Page, you can verify in your browser's network tab that the model_3d_urls
are indeed returned in the product request.
We want to be able to display a carousel of 3D models on the product page, but we don't have any components with this functionality β so we need to create a new one. Again, we can use the CLI tool instead of creating the boilerplate manually
Expected output:
Now that we have a placeholder component, let's render it on the product page β we want it to appear in one of the tabs below the product image:
We can do this with a plugin, but first we need to find the function we need to plug in to. To do this, we can inspect the source code for the ProductPage
component.
After looking through the source code, it becomes clear that we need to focus on the tabMap
property:
This -map pattern is fairly common in Scandi. It works by defining an object of similar, but distinct renderable elements. Then, a render function takes this data and renders it in the appropriate place.
This extra step of defining an object might seem counter-intuitive, but it will actually be quite helpful for our purposes. Now, to add a tab, all we have to do is add an entry to this tabMap
field. This is easy to do with a member property plugin:
It also integrates seamlessly with React β all we have to do to use it is to render a <model-viewer>
element (this is not technically a React component, but we can still treat it like any other element).
First, we need to load the library. For some reason, installing it via npm
and importing it as a module did not work β most likely, there is some conflict between the Webpack configuration in Scandi and model-viewer's module format. To work around this, we can load the module with a CDN:
Now we can render a 3D model in our Product3DViewer component:
The only functionality left to implement is pagination between different models β as the admin might have uploaded more than one, but currently only the first one is shown. To implement this pagination, we need to store the currently active model index in the state:
Now, we can use modelUrls[activeModelIndex]
to get the current model. By updating the state, we can change which model is active: setState({ activeModelIndex: activeModelIndex + 1 })
, so let's implement a switcher enabling the user to navigate between different models:
Whenever the user clicks a button that updates the state, the active model index is changed, and the component is re-rendered with the new model. When we put this all together, we get a component that can display a carousel of 3D models:
Congratulations, now you have learned how to implement completely new functionality in Scandi, from the Magento backend all the way to the Scandi React frontend. We can't wait to see what you'll create with this knowledge!
We get the original fields returned by the function by calling the original function with the provided arguments (line 3). If this still seems confusing, feel free to refer to the .
Now we need to implement the main functionality β 3D model rendering. Since this is quite a complex feature, we will make use of a library to do all the heavy lifting for us. I considered implementing the viewer in , which has bindings for use in React. However, I found that there is a library that makes things even easier. The library not only displays a 3D model, but also provides mouse interaction functionality and automatic rotation out-of-the-box.
If you are new to React, this might seem a bit overwhelming. The are a great place to learn the basics of React.
3D Models used in the example above: "" by and "" by
By the way, you can find the .
Written by Reinis Mazeiks. Feel free to ask questions and share feedback in the . Thanks for reading!