Published
Edited
Sep 7, 2020
1 fork
Importers
11 stars
Insert cell
Insert cell
Insert cell
Insert cell
circleLegend(d3.select(chart), [0, 100], [2, 35])
.x(width/4)
.y(2 * height/3)
.values([10, 50, 100])
.circleColor('#333333')
.textColor('#333333')
.suffix(' dBm')
.fontSize(10)
.fontFamily('Arial')
.textPadding(47)
.render()
Insert cell
circleLegend(d3.select(chart), [-10000, 0], [50, 2])
.x(width/2)
.y(2 * height/3)
.values([-500, -5000, -10000])
.circleColor('skyblue')
.textColor('silver')
.suffix(' dBm')
.fontFamily('Times')
.format(d3.format(".3~s"))
.textPadding(65)
.title('Center Frequency Magnitude')
.render()
Insert cell
function circleLegend(selection, domain, range) {

let instance = {}

// set some defaults
const api = {
domain: domain, // the values min and max
range: range, // the circle area/size mapping
values: [8, 34, 89], // values for circles
x: 500,
y: 500,
suffix:'', // ability to pass in a suffix
circleColor: '#888',
textPadding: 80,
textColor: '#454545',
fontSize: 14,
fontFamily: 'Arial',
format: d3.format("~g"),
title: 'Default title'
}
const sqrtScale = d3.scaleSqrt()
.domain(api.domain)
.range(api.range)

instance.render = function () {

const s = selection.append('g')
.attr('class', 'legend-wrap')
// push down to radius of largest circle
.attr('transform', 'translate(0,' + sqrtScale(d3.max(Math.abs(api.values))) + ')')

// append the values for circles
s.append('g')
.attr('class', 'values-wrap')
.selectAll('circle')
.data(api.values)
.enter().append('circle')
.attr('class', d => 'values values-' + d)
.attr('r', d => Math.abs(sqrtScale(d)))
.attr('cx', api.x)
.attr('cy', d => api.y - Math.abs(sqrtScale(d)))
.style('fill', 'none')
.style('stroke', api.circleColor)
.style('opacity', 0.9)

// append some lines based on values
s.append('g')
.attr('class', 'values-line-wrap')
.selectAll('.values-labels')
.data(api.values)
.enter().append('line')
.attr('x1', d => api.x + sqrtScale(d))
.attr('x2', api.x + Math.abs(sqrtScale(Math.max(Math.abs(api.domain[0]),Math.abs(api.domain[1])))) + 14)
.attr('y1', d => api.y - Math.abs(sqrtScale(d)))
.attr('y2', d => api.y - Math.abs(sqrtScale(d)))
.style('stroke', api.textColor)
.style('stroke-dasharray', ('2,2'))

// append some labels from values
s.append('g')
.attr('class', 'values-labels-wrap')
.selectAll('.values-labels')
.data(api.values)
.enter().append('text')
.attr('x', api.x + Math.abs(sqrtScale(Math.max(Math.abs(api.domain[0]),Math.abs(api.domain[1])))) + 14 + api.textPadding)
.attr('y', d => (api.y - Math.abs(sqrtScale(d))) + 4)
.attr('shape-rendering', 'crispEdges')
.style('text-anchor', 'end')
.style('fill', api.textColor)
.attr('font-family', api.fontFamily)
.attr('font-size', api.fontSize)
.text(d => api.format(d) + api.suffix)
s.append('g')
.selectAll('text')
.data(api.values)
.enter().append('text')
//.attr('text', api.title)
.attr('x', api.x )
.attr('y', api.y + 20)
.attr('font-family', api.fontFamily)
.attr('font-size', api.fontSize + 4)
.style('text-anchor', 'middle')
.text(d => api.title)
return instance
}

// convert api fields to setter functions
for (let key in api) {
instance[key] = getSet(key, instance).bind(api)
}
return instance

// https://gist.github.com/gneatgeek/5892586
function getSet(option, component) {
return function (_) {
if (! arguments.length) {
return this[option];
}
this[option] = _;
return component;
}
}
}
Insert cell
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