Public
Edited
Dec 15, 2022
1 fork
8 stars
Insert cell
Insert cell
Insert cell
{
const svg = d3.create('svg')
.attr('viewBox', [0, -10, w, h])
svg.append('g')
// .attr('transform', `translate(${0}, ${0})`)
.selectAll('.hexagon')
.data(hexbin(colours))
.enter().append('path')
.attr('class', 'hexagon')
.attr('transform', d => `translate(${d.x}, ${d.y})`)
.attr('d', hexbin.hexagon())
.attr('stroke', '#000')
.attr('stroke-opacity', '0.5')
.attr('stroke-width', '1px')
.style('fill', d => d[0].rgb) // take the colour from the canvas mapping > colours = rgbData(img)
return svg.node()
}
Insert cell
Insert cell
canvas = DOM.canvas(w, h);
Insert cell
image = {
const canvas = DOM.context2d(w, h);

// render the image on the canvas.
context.drawImage(img, 0, 0, w, h)

// return canvas not context.canvas which will produce
// the wrong imageData scaled up by the devicePixelRatio
return canvas
}
Insert cell
hexbin = hexbinObj.hexbin()
.x(d => d.x)
.y(d => d.y)
.radius(size)
.extent([[0, 0], [w, h]]);
Insert cell
context = canvas.getContext('2d')
Insert cell
w = img.naturalWidth
Insert cell
h = img.naturalHeight
Insert cell
colours = rgbData(img)
Insert cell
rgbData = async function(img) {

const data = rgbValues({
image: img,
size: size,
context: context
})

return data
}
Insert cell
function rgbValues (props) {
props = {
image: null,
size: 10,
context: null,
...props
}
const {image, size, context} = props
// number of squares left-to-right and top-to-bottom.
const xSquares = image.naturalWidth / size
const ySquares = image.naturalHeight / size
let data = []
for (let x = 0; x < xSquares; x++) {
for (let y = 0; y < ySquares; y++) {
const rgba = context.getImageData(x * size, y * size, size, size).data
const len = rgba.length
const num = len / 4
let r = 0
let g = 0
let b = 0
// Sum the color values.
for (let i = 0; i < len; i += 4) {
r += rgba[i]
g += rgba[i + 1]
b += rgba[i + 2]
}
// save the position and average color value.
data.push({
x: x * size,
y: y * size,
rgb: 'rgb(' + [
Math.round(r / num),
Math.round(g / num),
Math.round(b / num)
].join(',') + ')'
})
}
}
return data
}
Insert cell
Insert cell
img = FileAttachment("The_Great_Wave_off_Kanagawa.jpg").image()
Insert cell
hexbinObj = require("d3-hexbin@0.2")
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