Mapping an image onto a 3D surface in Javascript

Hi everyone!

I am trying to map an image onto a surface in Javascript using Plotly. I have found a previous post asking for a solution in R and an example of how to do it in Python.

I have attempted to implement the Python solution in Javascript but it hasn’t worked for me. Does anyone know how to do this in Javascript or if it is possible?

Specifically, I am first creating a 3D scatter plot and then trying to project an image onto an xy-plane with a z-value of 0.

Here is my attempt.

``````<html>
<script src="https://cdn.plot.ly/plotly-2.2.0.min.js"></script>

<body>
<div id="myDiv"></div>
<script>
//Create a 3d scatter plot
let x_values = [90,80,50,100]
let y_values = [100,200,40,80]
let z_values = [11,8,15,3]

let scatterplot = [{
x: x_values,
y: y_values,
z: z_values,
type: 'scatter3d',
mode: 'markers'
}]

Plotly.newPlot('myDiv', scatterplot)

// Create a blank 2d canvas
let canvas = document.createElement('canvas')
let context = canvas.getContext('2d')
context.rect(0, 0, 400, 400)
context.fill()

// A promise that the image will be loaded
let promise = new Promise(function(resolve, reject) {
// Create an image
let img = document.createElement("img")
img.crossOrigin = "Anonymous"

if (img.complete) {
resolve(img)
}
else {
}
}
})

// After the promise is fulfilled, get the pixel data
promise.then(
function(img){
// Draw the image onto the canvas
context.drawImage(img, 0, 0)

// Get the pixel data for the 400x400 square of pixels in the top left
let imageData = context.getImageData(0, 0, 400, 400).data

}
)

// Create an xy-plane @ z = 0
let width = 400
let height = 400
let x_values = []
let y_values = []
let z_values = new Array(width).fill(0)

for (let i = 0; i < width; i++) {
// Fill with values 0 -> width
x_values[i] = i
// Fill with all zeros (width x height dimensions)
z_values[i] = new Array(height).fill(0)
}
for (let j = 0; j < height; j++){
// Fill with values 0 -> height
y_values[j] = j
}

let surface = {
x: x_values,
y: y_values,
z: z_values,
type: 'surface',
surfacecolor: imageData, // Surfacecolor is RGBA pixel data of image
colorscale: [
[0.0, 'rgb(0, 0, 0)'],
[0.2, 'rgb(64, 64, 64)'],
[0.4, 'rgb(122, 122, 122)'],
[0.6, 'rgb(181, 181, 181)'],
[0.8, 'rgb(226, 226, 226)'],
[1.0, 'rgb(255, 255, 255)']
] // Simple grayscale color scale
}

// Add the surface to the scatterplot