Published
Edited
Mar 14, 2021
Fork of 2D to 3D
Insert cell
Insert cell
{
const scene = new THREE.Scene()
//scene.fog = new THREE.FogExp2(0xffffff, 0.0012)
const canvasHeight = 600
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(width, canvasHeight)
renderer.setPixelRatio(devicePixelRatio)
renderer.setClearColor(0xffffff)

const camera = new THREE.PerspectiveCamera(60, width/canvasHeight, 0.1, height * 2)
camera.position.x = 228//50
camera.position.y = 240//50
camera.position.z = 150//30
camera.lookAt(new THREE.Vector3(width/2, 0, height/2))
const controls = new THREE.OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
// controls.maxDistance = 15
invalidation.then(() => (controls.dispose(), renderer.dispose()))
controls.addEventListener("change", () => {
mutable debug = camera.position
renderer.render(scene, camera)
})

const light = new THREE.AmbientLight(0xcccccc)
scene.add(light)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5)
directionalLight.position.set(1, 1, 1)
scene.add(directionalLight)

const group = new THREE.Group()
scene.add(group)
group.translateX(-width * .5)
group.translateZ(-height * .5)

const shape = new THREE.Shape()
for(let i = 0; i <= 6; i ++) {
const angle = Math.PI / 3 * i + Math.PI / 2
const x = Math.cos(angle) * 14
const y = Math.sin(angle) * 14

if(i===0) shape.moveTo(x, y)
else shape.lineTo(x, y)
}
bins.forEach(bin => {
// Physically Based Rendering
const material = new THREE.MeshStandardMaterial({
color: ycolor(bin.length)
})

//const geometry = new THREE.BoxGeometry(10, 1, 10)
const geometry = new THREE.ExtrudeGeometry(shape, { depth: 1, bevelEnabled: false, metalness: 1 })
const mesh = new THREE.Mesh(geometry, material)
// we are mapping our data's Y dimension to Three's Z dimension
mesh.geometry.scale(1, 1, y(bin.length))
mesh.position.set(bin.x, y(bin.length), bin.y)
mesh.rotation.x = Math.PI/2
group.add(mesh)
})

const shape2 = new THREE.Shape()
for(let i = 0; i <= 6; i ++) {
const angle = Math.PI / 3 * i + Math.PI / 2
const x = Math.cos(angle) * 7
const y = Math.sin(angle) * 7

if(i===0) shape2.moveTo(x, y)
else shape2.lineTo(x, y)
}
bins2.forEach(bin => {
// Physically Based Rendering
const material = new THREE.MeshStandardMaterial({
color: ycolor(bin.length)
})

//const geometry = new THREE.BoxGeometry(10, 1, 10)
const geometry = new THREE.ExtrudeGeometry(shape2, { depth: 1, bevelEnabled: false })
const mesh = new THREE.Mesh(geometry, material)
// we are mapping our data's Y dimension to Three's Z dimension
mesh.geometry.scale(1, 1, y(bin.length))
mesh.position.set(bin.x, y(bin.length), bin.y-0.1)
mesh.rotation.x = Math.PI/2
group.add(mesh)
})
while(true) {
controls.update()
mutable debug = camera.position
renderer.render(scene, camera)
yield renderer.domElement
}
}
Insert cell
chart = {
let svg = d3.select(DOM.svg(width, height))

svg.selectAll("circle.big")
.data(bins)
.enter()
.append("circle").classed("big", true)
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", radius*.8)
.attr("fill", d => color(d.length))
// .attr("stroke-width", d => z(d.length))
// .attr("stroke", "#111")
// .attr("stroke-opacity", 0.2)

svg.selectAll("circle.small")
.data(bins2)
.enter()
.append("circle").classed("small", true)
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", radius2 * 0.6)
// .attr("fill", d => color(d.length))
.attr("fill", "none")
.attr("stroke", "#111")

return svg.node()
}
Insert cell
import { data, bins, x, y as z, height } with { radius as radius } from "@d3/hexbin"
Insert cell
radius = 24
Insert cell
radius2 = 12
Insert cell
import { bins as bins2 } with { radius2 as radius } from "@d3/hexbin"
Insert cell
bins
Insert cell
bins2
Insert cell
bins[0]
Insert cell
data
Insert cell
d3 = require("d3@6")
Insert cell
xextent = d3.extent(bins, d => d.x)
Insert cell
zextent = d3.extent(bins, d => d.y)
Insert cell
yextent = d3.extent(bins, d => d.length)
Insert cell
color = d3.scaleSequential(d3.interpolateBuPu)
.domain([0, d3.max(bins, d => d.length) / 2])
Insert cell
ramp(d3.interpolateBuPu)
Insert cell
Insert cell
THREE = {
const THREE = window.THREE = await require("three/build/three.min.js");
await require("three/examples/js/controls/OrbitControls.js").catch(() => {});
return THREE;
}
Insert cell
mutable debug = {}
Insert cell
/*
const length = 12, width = 8;

const shape = new THREE.Shape();
shape.moveTo( 0,0 );
shape.lineTo( 0, width );
shape.lineTo( length, width );
shape.lineTo( length, 0 );
shape.lineTo( 0, 0 );

const extrudeSettings = {
steps: 2,
depth: 16,
bevelEnabled: true,
bevelThickness: 1,
bevelSize: 1,
bevelOffset: 0,
bevelSegments: 1
};

const geometry = new THREE.ExtrudeGeometry( shape, extrudeSettings );
const material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
const mesh = new THREE.Mesh( geometry, material ) ;
scene.add( mesh );
*/
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(bins, d => d.length) / 2])
.range([0, 100])
Insert cell
ycolor = d3.scaleSequential(d3.interpolateBuPu)
.domain([d3.max(bins, d => d.length) / 1, 0])
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more