{
let data = adlb.filter(d => d.USUBJID === patient)
.filter(d => d.LBNRIND !== "NORMAL")
const xAccessor = d => d.ADY
const radiusAccessor = d => d.AVAL
const svg = d3.create("svg")
.attr("width", dimensions.width)
.attr("height", dimensions.height)
const bounds = svg.append("g")
.style("transform", `translate(${
dimensions.margin.left
}px, ${
dimensions.margin.top
}px)`
)
const colorScale = d3.scaleOrdinal()
.domain(["LOW", "NORMAL", "HIGH"])
.range(['#fdd26e', '#86cac5', '#ff8041'])
const dots = bounds.selectAll("circle")
.data(beeswarmForce(data, 'ADY', 'AVAL', 'LBNRIND', xScale))
.join("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", d => d.r)
.attr("fill", d => colorScale(d.fill))
.on('mousemove', nodeMouseOver)
.on('mouseout', nodeMouseOut );
// extras
const xAxisGenerator = d3.axisBottom()
.scale(xScale)
const xAxis = bounds.append("g")
.call(xAxisGenerator)
.style("transform", `translateY(${dimensions.boundedHeight}px)`)
.style("stroke", "#004f5b")
// tooltip
// const listenerRect = bounds.append('rect')
// .attr('class', 'listener-rect')
// .attr('width', dimensions.boundedWidth)
// .attr('height', dimensions.boundedHeight)
// .on("mousemove", onMouseMo)
// .on("mouseleave", onMouseLeave)
// const tooltip = bounds.append("div")
const tooltip = d3.select("body").append('div')
// const tooltip = wrapper.append('div')
.attr('class', 'tooltip')
.html(
`<span class='tooltip-param'></span>
<span class='tooltip-aval'></span>
<span class='tooltip-range'></span>
<span class='tooltip-day'></span>`
)
// .append('span')
// .attr('class', 'tooltip-param')
// .apppend('span')
// .attr('class', 'tooltip-aval')
// .append('span')
// .attr('class', 'tooltip-range')
function onMouseEnter(event, d) {
const mousePosition = d3.pointer(event)
const xPosition = mousePosition[0]
const yPosition = mousePosition[1]
// console.log(mousePosition)
tooltip.select('.tooltip-param')
.text(`PARAM: ${d.PARAM}`)
// .style('left', `${dimensions.boundedWidth - xPosition - 20}px`)
// .style('top', `${dimensions.boundedHeight + yPosition + 20}px`)
// .style('left', '79px')
// .style('right', '260px')
// tooltip.style('transform', `translate(calc(-50% + ${xPosition}px), calc(-100% + ${yPosition}px))`)
// .style('opacity', 1)
tooltip
.style('width', '100px')
.style('height', '100px')
.style('left', xPosition + 'px')
.style('top', yPosition + 'px')
// .style('transform', `translate(${xPosition}px, ${yPosition}px)`)
.style('opacity', 1)
.style('background', 'red')
// console.log(dimensions.boundedWidth - xPosition - 20)
// console.log(dimensions.boundedHeight + yPosition + 20)
// const hoveredDay = xScale.invert(mousePosition[0])
// // need to find closet point in our data
// const getDistanceFromHoveredDay = d => {
// return Math.abs(xAccessor(d) - hoveredDay)
// }
// const closestIndex = d3.leastIndex(
// data,
// (a, b) => { // kind of like native JS sort
// return getDistanceFromHoveredDay(a) - getDistanceFromHoveredDay(b)
// }
// )
// const closestDataPoint = data[closestIndex]
// console.log(closestDataPoint)
// // at this point, we're at the 'd' we usually work with
// const formatDate = d3.timeFormat("%B %A %-d, %Y")
// tooltip.select("#date")
// .text(formatDate(xAccessor(closestDataPoint)))
// const formatTemperature = d => `${d3.format(".1f")(d)}°F`
// tooltip.select("#temperature")
// .text(formatTemperature(yAccessor(closestDataPoint)))
// // ended up not using this but it's nice to know there's an inverse
// //const hoveredTemp = yScale.invert(mousePosition[1])
// // move tooltip to correct position
// const x = xScale(xAccessor(closestDataPoint)) + dimensions.margin.left
// const y = yScale(yAccessor(closestDataPoint)) + dimensions.margin.top
// tooltip.style('transform', `translate(calc(-50% + ${x}px), calc(-100% + ${y}px))`)
// tooltip.style('opacity', 1)
}
function onMouseLeave(event, d) {
tooltip.style('opacity', 0)
}
return svg.node()
}