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>
<head>
<script src="https://cdn.plot.ly/plotly-2.2.0.min.js"></script>
</head>
<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"
img.src = "https://raw.githubusercontent.com/cldougl/plot_images/add_r_img/vox.png"
img.onload = function(){
if (img.complete) {
resolve(img)
}
else {
reject(Error("Image Not Found."))
}
}
})
// 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
add_surface(imageData)
}
)
add_surface = function(imageData){
// 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
Plotly.addTraces('myDiv', [surface])
}
</script>
</body>
</html>