Overlay Material Color
Goal
The colormass configurator can be used to render custom fabric designs, which are provided as color images. Internally, the configuator embeds those images into a scanned, high-quality base material. This material contributes to the overall appearance and makes your design look like wool, cotton or linen.
Examples
The following images were created using this sample code and these two images as input:





Setting the scene
For this example, we set up a test scene on the colormass platform. It consists of a chair and uses a wool-like base material. The Overlay Material Color node takes care of replacing the color information of this material and scales your pattern to the desired width and height.

While the base material is fixed, the overlay image as well as the width and height are transferred to the configurator via the corresponding input node (image input and number input).



Adding the markup
Once the scene has been prepared, the configurator component can be added to the page.
<cm-configurator-main template-uuid="60ec3a3a-9e92-4d2a-a6e5-16595d34686e"></cm-configurator-main>
To change the color pattern used programmatically, we add three simple input elements.
<input id="widthInput" type="number" value="10" onchange="updateWidth(this.value)"/>
<input id="heightInput" type="number" value="10" onchange="updateHeight(this.value)"/>
<input type="file" id="overlayImageInput" accept="image/jpeg, image/png" onchange="updateOverlayImage(this.files)" />
Adding the scripts
We use the ‘setParameters’ API, which is provided by the configurator component, to transfer the input data to the renderer. You can find a detailed explanation in our guide on setting parameters.
// wait for the configurator component to be available
customElements.whenDefined("cm-configurator-main").then(() => {
cmConfigurator = document.querySelector("cm-configurator-main")
})
// pass the width input to the configurator
async function updateWidth(width) {
cmConfigurator.setParameter("width", "number", Number(width))
}
// pass the height input to the configurator
async function updateHeight(height) {
cmConfigurator.setParameter("height", "number", Number(height))
}
// pass the image input to the configurator as an object URL
// note: the image parameter supports passing an image via
// - URL
// - data URL (inlined base64)
// - raw data (Uint8Array)
async function updateOverlayImage(files) {
const file = files[0]
const image = await fetch(file)
const imageBlob = await image.blob()
const imageUrl = URL.createObjectURL(imageBlob)
await cmConfigurator.setParameter("overlayImage", "image", imageUrl)
}
Putting it all together
The complete example code can also be found in our sample repository.
<!DOCTYPE html>
<html style="height: 100%">
<head>
<link rel="preconnect" href="https://configurator.colormass.com" />
<!-- Load the colormass configurator styles -->
<link href="https://configurator.colormass.com/styles.css" rel="stylesheet" />
<!-- Load the colormass configurator web components -->
<script src="https://configurator.colormass.com/cm-configurator.js" type="module"></script>
<title>Overlay Material Color | Example</title>
<meta charset="UTF-8" />
<style>
body {
width: 100%;
height: 100%;
margin: 0;
}
:root {
--cm-menu-max-num-cols: 8;
--cm-menu-icon-size: 40px;
--cm-menu-background-color: rgba(255, 255, 255, 0);
font-family: "Roboto";
}
.container {
display: flex;
height: 100%;
overflow: hidden;
}
.menu {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 10px;
padding: 20px;
width: 300px;
background-color: #f4f4f4;
overflow: hidden;
}
.menu-item {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 10px;
width: 100%;
}
#overlayImageInput {
display: none;
}
.configurator-container {
flex-grow: 1;
box-sizing: border-box;
}
img {
width: 100%;
height: auto;
}
</style>
<script>
let cmConfigurator,
overlayImageInput,
widthInput,
heightInput,
overlayImagePreview,
snapshotImagePreview;
customElements.whenDefined("cm-configurator-main").then(() => {
cmConfigurator = document.querySelector("cm-configurator-main")
// Initialize UI elements
overlayImageInput = document.getElementById("overlayImageInput")
widthInput = document.getElementById("widthInput")
heightInput = document.getElementById("heightInput")
overlayImagePreview = document.getElementById("overlay-image-preview")
snapshotImagePreview = document.getElementById("snapshot-image-preview")
// Reset inputs
overlayImageInput.value = ""
widthInput.value = 10
heightInput.value = 10
})
function inMemorySnapshot() {
cmConfigurator
.captureSnapshotInMemory()
.then((snapshot) => {
snapshotImagePreview.src = snapshot
})
.catch((error) => {
console.log("Could not capture snapshot in memory.", error)
})
}
async function updateWidth(width) {
await cmConfigurator.setParameter("width", "number", Number(width))
}
async function updateHeight(height) {
await cmConfigurator.setParameter("height", "number", Number(height))
}
async function updateOverlayImage(files) {
const file = files[0]
const image = await fetch(file)
const imageBlob = await image.blob()
const imageUrl = URL.createObjectURL(imageBlob)
// update image parameter
await cmConfigurator.setParameter("overlayImage", "image", imageUrl)
// set image preview
overlayImagePreview.src = imageUrl
// Alternative implementation using data URL
// const dataUrlReader = new FileReader()
// dataUrlReader.onload = async function (e) {
// overlayImagePreview.src = e.target.result
// await cmConfigurator.setParameter("overlayImage", "image", e.target.result)
// }
// dataUrlReader.readAsDataURL(files[0])
// Alternative implementation using array buffer
// const byteLoader = new FileReader()
// byteLoader.onload = async function (e) {
// const buffer = new Uint8Array(e.target.result)
// const imageParamData = {
// contentType: file.type,
// data: buffer,
// }
// await cmConfigurator.setParameter("overlayImage", "image", imageParamData)
// }
// byteLoader.readAsArrayBuffer(files[0])
}
</script>
</head>
<body>
<div class="container">
<div class="menu">
<!-- Pattern width -->
<div class="menu-item">
<label for="widthInput">Width: </label>
<input id="widthInput" type="number" value="10" onchange="updateWidth(this.value)"/>
</div>
<!-- Pattern height -->
<div class="menu-item">
<label for="heightInput">Height: </label>
<input id="heightInput" type="number" value="10" onchange="updateHeight(this.value)"/>
</div>
<!-- Overlay image -->
<div class="menu-item">
<label for="overlayImageInput">Overlay image</label>
<button onclick="overlayImageInput.click()">Select Image</button>
<input type="file" id="overlayImageInput" accept="image/jpeg, image/png" onchange="updateOverlayImage(this.files)" />
</div>
<img id="overlay-image-preview" />
<!-- Take in memory snapshot -->
<div class="menu-item">
<button onclick="inMemorySnapshot()">Take a snapshot</button>
</div>
<img id="snapshot-image-preview" />
</div>
<div class="configurator-container">
<cm-configurator-main ui-style="default" template-uuid="60ec3a3a-9e92-4d2a-a6e5-16595d34686e"></cm-configurator-main>
</div>
</div>
</body>
</html>
Last updated