d3-selection#select JavaScript Examples
The following examples show how to use
d3-selection#select.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: legend.js From t-viSNE with MIT License | 6 votes |
d3_textWrapping = (text, width) => {
text.each(function() {
var text = select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.2, //ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")) || 0,
tspan = text.text(null)
.append("tspan")
.attr("x", 0)
.attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width && line.length > 1) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan")
.attr("x", 0)
.attr("dy", lineHeight + dy + "em").text(word);
}
}
});
}
Example #2
Source File: nodrag.js From gamedesign with GNU General Public License v3.0 | 6 votes |
export function yesdrag(view, noclick) {
var root = view.document.documentElement,
selection = select(view).on("dragstart.drag", null);
if (noclick) {
selection.on("click.drag", noevent, true);
setTimeout(function() { selection.on("click.drag", null); }, 0);
}
if ("onselectstart" in root) {
selection.on("selectstart.drag", null);
} else {
root.style.MozUserSelect = root.__noselect;
delete root.__noselect;
}
}
Example #3
Source File: nodrag.js From gamedesign with GNU General Public License v3.0 | 6 votes |
export default function(view) {
var root = view.document.documentElement,
selection = select(view).on("dragstart.drag", noevent, true);
if ("onselectstart" in root) {
selection.on("selectstart.drag", noevent, true);
} else {
root.__noselect = root.style.MozUserSelect;
root.style.MozUserSelect = "none";
}
}
Example #4
Source File: statusboard.js From covid19japan-data with MIT License | 6 votes |
showPatients = (prefectureId) => {
let patients = responses[prefectureId]
if (!patients) {
console.error(`No response cached for ${prefectureId}`)
}
document.querySelector('#console').value = JSON.stringify(patients)
let patientList = select('#patients')
selectAll('.patient-item').remove()
let row = DATA_START_ROW
for (let patient of patients) {
createPatientItemCells(prefectureId, patientList, patient, row)
row++
}
}
Example #5
Source File: zoomable-canvas.js From ThreatMapper with Apache License 2.0 | 6 votes |
componentDidMount() {
this.svg = select('.zoomable-canvas svg');
this.drag = drag()
.on('start', this.handlePanStart)
.on('end', this.handlePanEnd)
.on('drag', this.handlePan);
this.svg.call(this.drag);
this.zoomRestored = false;
this.updateZoomLimits(this.props);
this.restoreZoomState(this.props);
document
.getElementById('canvas')
.addEventListener('wheel', this.handleZoom, { passive: false });
}
Example #6
Source File: statusboard.js From covid19japan-data with MIT License | 6 votes |
createPrefecturePatientCountCell = (placeId, patients) => {
let patientCount = 0
if (patients) {
patientCount = patients.length
}
select(`#statusboard`)
.append('div')
.attr('class', _.join(['item', 'dash-confirmed', placeId], ' '))
.attr('data-prefecture-id', placeId)
.style('grid-row', rowByPrefecture[placeId])
.style('grid-column', 'dash-confirmed')
.append('a')
.attr('href', `/statusboard/patients.html#${placeId}`)
.attr('target', '_blank')
.text(patientCount)
.on('click', e => {
event(this).preventDefault()
showPatients(placeId)
})
}
Example #7
Source File: statusboard.js From covid19japan-data with MIT License | 6 votes |
createPrefectureSiteCountCell = (prefectureId, summary) => {
select('#statusboard')
.append('div')
.attr('class', 'item')
.attr('data-prefecture-id', prefectureId)
.style('grid-row', rowByPrefecture[prefectureId])
.style('grid-column', 'site-confirmed')
.text(summary.confirmed)
select('#statusboard')
.append('div')
.attr('class', 'item')
.attr('data-prefecture-id', prefectureId)
.style('grid-row', rowByPrefecture[prefectureId])
.style('grid-column', 'site-recovered')
.text(summary.recovered)
}
Example #8
Source File: statusboard.js From covid19japan-data with MIT License | 6 votes |
createPrefectureNHKCountCell = (prefectureId, count) => {
select('#statusboard')
.append('div')
.attr('class', 'item nhk-value')
.attr('data-prefecture-id', prefectureId)
.style('grid-row', rowByPrefecture[prefectureId])
.style('grid-column', 'nhk-confirmed')
.text(count)
}
Example #9
Source File: MapLegend.js From covid19india-react with MIT License | 6 votes |
function ramp(color, n = 256) {
const canvas = select('.color-scale').node();
const context = ((canvas.width = n), (canvas.height = 1), canvas).getContext(
'2d'
);
for (let i = 0; i < n; ++i) {
context.fillStyle = color(i / (n - 1));
context.fillRect(i, 0, 1, 1);
}
return canvas;
}
Example #10
Source File: statusboard.js From covid19japan-data with MIT License | 6 votes |
createCell = (rowId, column, text, title, city) => {
let cityClass = city ? 'city' : ''
select('#statusboard')
.append('div')
.attr('class', _.join(['item', column, rowId, cityClass], ' '))
.attr('data-prefecture-id', rowId)
.attr('title', title)
.style('grid-row', rowByPrefecture[rowId])
.style('grid-column', column)
.text(text)
}
Example #11
Source File: statusboard.js From covid19japan-data with MIT License | 6 votes |
createLinkCell = (rowId, column, text, title, url, city) => {
let cityClass = city ? 'city' : ''
select('#statusboard')
.append('div')
.attr('class', _.join(['item', column, rowId, cityClass], ' '))
.attr('data-prefecture-id', rowId)
.attr('title', title)
.style('grid-row', rowByPrefecture[rowId])
.style('grid-column', column)
.append('a')
.attr('href', url)
.attr('target', '_blank')
.text(text)
}
Example #12
Source File: indexRollupNext.js From t-viSNE with MIT License | 6 votes |
d3_textWrapping = function d3_textWrapping(text, width) {
text.each(function () {
var text = select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.2,
//ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")) || 0,
tspan = text.text(null).append("tspan").attr("x", 0).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width && line.length > 1) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("dy", lineHeight + dy + "em").text(word);
}
}
});
}
Example #13
Source File: nodrag.js From cs-wiki with GNU General Public License v3.0 | 6 votes |
export default function(view) {
var root = view.document.documentElement,
selection = select(view).on("dragstart.drag", noevent, nonpassivecapture);
if ("onselectstart" in root) {
selection.on("selectstart.drag", noevent, nonpassivecapture);
} else {
root.__noselect = root.style.MozUserSelect;
root.style.MozUserSelect = "none";
}
}
Example #14
Source File: nodrag.js From cs-wiki with GNU General Public License v3.0 | 6 votes |
export function yesdrag(view, noclick) {
var root = view.document.documentElement,
selection = select(view).on("dragstart.drag", null);
if (noclick) {
selection.on("click.drag", noevent, nonpassivecapture);
setTimeout(function() { selection.on("click.drag", null); }, 0);
}
if ("onselectstart" in root) {
selection.on("selectstart.drag", null);
} else {
root.style.MozUserSelect = root.__noselect;
delete root.__noselect;
}
}
Example #15
Source File: nodrag.js From cs-wiki with GNU General Public License v3.0 | 6 votes |
export function yesdrag(view, noclick) {
var root = view.document.documentElement,
selection = select(view).on("dragstart.drag", null);
if (noclick) {
selection.on("click.drag", noevent, true);
setTimeout(function() { selection.on("click.drag", null); }, 0);
}
if ("onselectstart" in root) {
selection.on("selectstart.drag", null);
} else {
root.style.MozUserSelect = root.__noselect;
delete root.__noselect;
}
}
Example #16
Source File: nodrag.js From cs-wiki with GNU General Public License v3.0 | 6 votes |
export default function(view) {
var root = view.document.documentElement,
selection = select(view).on("dragstart.drag", noevent, true);
if ("onselectstart" in root) {
selection.on("selectstart.drag", noevent, true);
} else {
root.__noselect = root.style.MozUserSelect;
root.style.MozUserSelect = "none";
}
}
Example #17
Source File: index.js From dmarman.github.io with MIT License | 5 votes |
ChartJSdragDataPlugin = {
id: 'dragdata',
afterInit: function (chartInstance) {
if (chartInstance.options.dragData) {
select(chartInstance.chart.canvas).call(
drag().container(chartInstance.chart.canvas)
.on('start', getElement(chartInstance, chartInstance.options.onDragStart))
.on('drag', updateData(chartInstance, chartInstance.options.onDrag))
.on('end', dragEndCallback(chartInstance, chartInstance.options.onDragEnd))
)
}
},
beforeRender: function (chart) {
const dragOptions = chart.config.options.dragOptions
if (dragOptions && dragOptions.showTooltip) {
// create an array of tooltips
// we can't use the chart tooltip because there is only one tooltip per chart
chart.pluginTooltips = []
chart.config.data.datasets.forEach(function (dataset, i) {
chart.getDatasetMeta(i).data.forEach(function (sector, j) {
if (curDatasetIndex === i && curIndex === j) {
chart.pluginTooltips.push(new Chart.Tooltip({
_chart: chart.chart,
_chartInstance: chart,
_data: chart.data,
_options: chart.options.tooltips,
_active: [sector]
}, chart))
}
})
})
// turn off normal tooltips
// chart.options.tooltips.enabled = false;
}
},
afterDraw: function (chart, easing) {
const dragOptions = chart.config.options.dragOptions
if (dragOptions && dragOptions.showTooltip) {
// we don't want the permanent tooltips to animate, so don't do anything till the animation runs atleast once
if (!chart.allTooltipsOnce) {
if (easing !== 1)
return
chart.allTooltipsOnce = true
}
// turn on tooltips
chart.options.tooltips.enabled = true
Chart.helpers.each(chart.pluginTooltips, function (tooltip) {
// This line checks if the item is visible to display the tooltip
if(!tooltip._active[0].hidden){
tooltip.initialize()
tooltip.update()
// we don't actually need this since we are not animating tooltips
tooltip.pivot()
tooltip.transition(easing).draw()
}
})
chart.options.tooltips.enabled = true
}
}
}
Example #18
Source File: diagram.js From the-eye-knows-the-garbage with MIT License | 5 votes |
// sometimes text doesn't fit inside the circle, if thats the case lets wrap
// the text here such that it fits
// todo: looks like this might be merged into d3 (
// https://github.com/mbostock/d3/issues/1642),
// also worth checking out is
// http://engineering.findthebest.com/wrapping-axis-labels-in-d3-js/
// this seems to be one of those things that should be easy but isn't
export function wrapText(circles, labeller) {
return function() {
var text = select(this),
data = text.datum(),
width = circles[data.sets[0]].radius || 50,
label = labeller(data) || '';
var words = label.split(/\s+/).reverse(),
maxLines = 3,
minChars = (label.length + words.length) / maxLines,
word = words.pop(),
line = [word],
joined,
lineNumber = 0,
lineHeight = 1.1, // ems
tspan = text.text(null).append("tspan").text(word);
while (true) {
word = words.pop();
if (!word) break;
line.push(word);
joined = line.join(" ");
tspan.text(joined);
if (joined.length > minChars && tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").text(word);
lineNumber++;
}
}
var initial = 0.35 - lineNumber * lineHeight / 2,
x = text.attr("x"),
y = text.attr("y");
text.selectAll("tspan")
.attr("x", x)
.attr("y", y)
.attr("dy", function(d, i) {
return (initial + i * lineHeight) + "em";
});
};
}
Example #19
Source File: wrapText.js From react-orgchart with MIT License | 5 votes |
// One way of achieving text-wrapping capability in SVG
// Text is broken down to words, each word is added to a line and then the lines width is checked
// If the line width is less than the max we move to the next word, if more we add new line etc
// until the max number of lines is reached.
export function wrapText(text, maxLineWidth, maxNumberOfLines = 3, maxWordLength = 17) {
if (!text._groups || !text._groups[0] || !text._groups[0].length) {
return '';
}
let editedClass = '';
text._groups[0].forEach(textNode => {
const text = select(textNode);
const x = text.attr('x');
const y = text.attr('y');
const dy = parseFloat(text.attr('dy'));
const lineHeight = 1.1;
const words = text.text().split(/\s+/).reverse();
let lineNumber = 0;
let curLineWidth;
let word;
let line = [];
let tspan = text
.text(null)
.append('tspan')
.style('text-anchor', 'middle')
.attr('x', x)
.attr('y', y)
.attr('dy', `${dy}em`);
while (lineNumber < maxNumberOfLines && words.length) {
word = words.pop();
line.push(word);
tspan.text(line.join(' '));
curLineWidth = tspan.node().getComputedTextLength();
if (curLineWidth > maxLineWidth) {
if (lineNumber + 1 === maxNumberOfLines) {
tspan.text(getTruncatedText(line.join(' '), maxWordLength));
break;
} else {
line.pop();
tspan.text(line.join(' '));
line = [word];
tspan = text
.append('tspan')
.style('text-anchor', 'middle')
.attr('x', x)
.attr('y', y)
.attr('dy', ++lineNumber * lineHeight + dy + 'em')
.text(getTruncatedText(word, maxWordLength));
}
if (word.length > maxWordLength) {
break;
}
}
}
if (!editedClass) {
editedClass = text.attr('class').replace(' unedited', '');
}
text.attr('class', editedClass);
});
}
Example #20
Source File: statusboard.js From covid19japan-data with MIT License | 5 votes |
createPrefecturePatientTodayCell = (prefectureId, patients) => {
let patientsToday = 0
let patientsYesterday = 0
let latestPatientDate = ''
let today = moment().format('YYYY-MM-DD')
let yesterday = moment().subtract(1, 'days').format('YYYY-MM-DD')
if (patients) {
for (let patient of patients) {
if (patient.dateAnnounced == today) {
patientsToday++;
}
if (patient.dateAnnounced == yesterday) {
patientsYesterday++;
}
}
}
if (patients.length) {
latestPatientDate = _.last(patients).dateAnnounced
}
select('#statusboard')
.append('div')
.attr('class', 'item')
.attr('data-prefecture-id', prefectureId)
.style('grid-row', rowByPrefecture[prefectureId])
.style('grid-column', 'dash-latest')
.text(latestPatientDate)
select('#statusboard')
.append('div')
.attr('class', 'item')
.attr('data-prefecture-id', prefectureId)
.style('grid-row', rowByPrefecture[prefectureId])
.style('grid-column', 'dash-today')
.text(patientsToday)
select('#statusboard')
.append('div')
.attr('class', 'item')
.attr('data-prefecture-id', prefectureId)
.style('grid-row', rowByPrefecture[prefectureId])
.style('grid-column', 'dash-yesterday')
.text(patientsYesterday)
}
Example #21
Source File: brush.js From cs-wiki with GNU General Public License v3.0 | 4 votes |
function brush(dim) {
var extent = defaultExtent,
filter = defaultFilter,
touchable = defaultTouchable,
keys = true,
listeners = dispatch("start", "brush", "end"),
handleSize = 6,
touchending;
function brush(group) {
var overlay = group
.property("__brush", initialize)
.selectAll(".overlay")
.data([type("overlay")]);
overlay.enter().append("rect")
.attr("class", "overlay")
.attr("pointer-events", "all")
.attr("cursor", cursors.overlay)
.merge(overlay)
.each(function() {
var extent = local(this).extent;
select(this)
.attr("x", extent[0][0])
.attr("y", extent[0][1])
.attr("width", extent[1][0] - extent[0][0])
.attr("height", extent[1][1] - extent[0][1]);
});
group.selectAll(".selection")
.data([type("selection")])
.enter().append("rect")
.attr("class", "selection")
.attr("cursor", cursors.selection)
.attr("fill", "#777")
.attr("fill-opacity", 0.3)
.attr("stroke", "#fff")
.attr("shape-rendering", "crispEdges");
var handle = group.selectAll(".handle")
.data(dim.handles, function(d) { return d.type; });
handle.exit().remove();
handle.enter().append("rect")
.attr("class", function(d) { return "handle handle--" + d.type; })
.attr("cursor", function(d) { return cursors[d.type]; });
group
.each(redraw)
.attr("fill", "none")
.attr("pointer-events", "all")
.on("mousedown.brush", started)
.filter(touchable)
.on("touchstart.brush", started)
.on("touchmove.brush", touchmoved)
.on("touchend.brush touchcancel.brush", touchended)
.style("touch-action", "none")
.style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
}
brush.move = function(group, selection, event) {
if (group.tween) {
group
.on("start.brush", function(event) { emitter(this, arguments).beforestart().start(event); })
.on("interrupt.brush end.brush", function(event) { emitter(this, arguments).end(event); })
.tween("brush", function() {
var that = this,
state = that.__brush,
emit = emitter(that, arguments),
selection0 = state.selection,
selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent),
i = interpolate(selection0, selection1);
function tween(t) {
state.selection = t === 1 && selection1 === null ? null : i(t);
redraw.call(that);
emit.brush();
}
return selection0 !== null && selection1 !== null ? tween : tween(1);
});
} else {
group
.each(function() {
var that = this,
args = arguments,
state = that.__brush,
selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent),
emit = emitter(that, args).beforestart();
interrupt(that);
state.selection = selection1 === null ? null : selection1;
redraw.call(that);
emit.start(event).brush(event).end(event);
});
}
};
brush.clear = function(group, event) {
brush.move(group, null, event);
};
function redraw() {
var group = select(this),
selection = local(this).selection;
if (selection) {
group.selectAll(".selection")
.style("display", null)
.attr("x", selection[0][0])
.attr("y", selection[0][1])
.attr("width", selection[1][0] - selection[0][0])
.attr("height", selection[1][1] - selection[0][1]);
group.selectAll(".handle")
.style("display", null)
.attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; })
.attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; })
.attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; })
.attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; });
}
else {
group.selectAll(".selection,.handle")
.style("display", "none")
.attr("x", null)
.attr("y", null)
.attr("width", null)
.attr("height", null);
}
}
function emitter(that, args, clean) {
var emit = that.__brush.emitter;
return emit && (!clean || !emit.clean) ? emit : new Emitter(that, args, clean);
}
function Emitter(that, args, clean) {
this.that = that;
this.args = args;
this.state = that.__brush;
this.active = 0;
this.clean = clean;
}
Emitter.prototype = {
beforestart: function() {
if (++this.active === 1) this.state.emitter = this, this.starting = true;
return this;
},
start: function(event, mode) {
if (this.starting) this.starting = false, this.emit("start", event, mode);
else this.emit("brush", event);
return this;
},
brush: function(event, mode) {
this.emit("brush", event, mode);
return this;
},
end: function(event, mode) {
if (--this.active === 0) delete this.state.emitter, this.emit("end", event, mode);
return this;
},
emit: function(type, event, mode) {
var d = select(this.that).datum();
listeners.call(
type,
this.that,
new BrushEvent(type, {
sourceEvent: event,
target: brush,
selection: dim.output(this.state.selection),
mode,
dispatch: listeners
}),
d
);
}
};
function started(event) {
if (touchending && !event.touches) return;
if (!filter.apply(this, arguments)) return;
var that = this,
type = event.target.__data__.type,
mode = (keys && event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (keys && event.altKey ? MODE_CENTER : MODE_HANDLE),
signX = dim === Y ? null : signsX[type],
signY = dim === X ? null : signsY[type],
state = local(that),
extent = state.extent,
selection = state.selection,
W = extent[0][0], w0, w1,
N = extent[0][1], n0, n1,
E = extent[1][0], e0, e1,
S = extent[1][1], s0, s1,
dx = 0,
dy = 0,
moving,
shifting = signX && signY && keys && event.shiftKey,
lockX,
lockY,
points = Array.from(event.touches || [event], t => {
const i = t.identifier;
t = pointer(t, that);
t.point0 = t.slice();
t.identifier = i;
return t;
});
interrupt(that);
var emit = emitter(that, arguments, true).beforestart();
if (type === "overlay") {
if (selection) moving = true;
const pts = [points[0], points[1] || points[0]];
state.selection = selection = [[
w0 = dim === Y ? W : min(pts[0][0], pts[1][0]),
n0 = dim === X ? N : min(pts[0][1], pts[1][1])
], [
e0 = dim === Y ? E : max(pts[0][0], pts[1][0]),
s0 = dim === X ? S : max(pts[0][1], pts[1][1])
]];
if (points.length > 1) move(event);
} else {
w0 = selection[0][0];
n0 = selection[0][1];
e0 = selection[1][0];
s0 = selection[1][1];
}
w1 = w0;
n1 = n0;
e1 = e0;
s1 = s0;
var group = select(that)
.attr("pointer-events", "none");
var overlay = group.selectAll(".overlay")
.attr("cursor", cursors[type]);
if (event.touches) {
emit.moved = moved;
emit.ended = ended;
} else {
var view = select(event.view)
.on("mousemove.brush", moved, true)
.on("mouseup.brush", ended, true);
if (keys) view
.on("keydown.brush", keydowned, true)
.on("keyup.brush", keyupped, true)
dragDisable(event.view);
}
redraw.call(that);
emit.start(event, mode.name);
function moved(event) {
for (const p of event.changedTouches || [event]) {
for (const d of points)
if (d.identifier === p.identifier) d.cur = pointer(p, that);
}
if (shifting && !lockX && !lockY && points.length === 1) {
const point = points[0];
if (abs(point.cur[0] - point[0]) > abs(point.cur[1] - point[1]))
lockY = true;
else
lockX = true;
}
for (const point of points)
if (point.cur) point[0] = point.cur[0], point[1] = point.cur[1];
moving = true;
noevent(event);
move(event);
}
function move(event) {
const point = points[0], point0 = point.point0;
var t;
dx = point[0] - point0[0];
dy = point[1] - point0[1];
switch (mode) {
case MODE_SPACE:
case MODE_DRAG: {
if (signX) dx = max(W - w0, min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
if (signY) dy = max(N - n0, min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
break;
}
case MODE_HANDLE: {
if (points[1]) {
if (signX) w1 = max(W, min(E, points[0][0])), e1 = max(W, min(E, points[1][0])), signX = 1;
if (signY) n1 = max(N, min(S, points[0][1])), s1 = max(N, min(S, points[1][1])), signY = 1;
} else {
if (signX < 0) dx = max(W - w0, min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
else if (signX > 0) dx = max(W - e0, min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
if (signY < 0) dy = max(N - n0, min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
else if (signY > 0) dy = max(N - s0, min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
}
break;
}
case MODE_CENTER: {
if (signX) w1 = max(W, min(E, w0 - dx * signX)), e1 = max(W, min(E, e0 + dx * signX));
if (signY) n1 = max(N, min(S, n0 - dy * signY)), s1 = max(N, min(S, s0 + dy * signY));
break;
}
}
if (e1 < w1) {
signX *= -1;
t = w0, w0 = e0, e0 = t;
t = w1, w1 = e1, e1 = t;
if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
}
if (s1 < n1) {
signY *= -1;
t = n0, n0 = s0, s0 = t;
t = n1, n1 = s1, s1 = t;
if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
}
if (state.selection) selection = state.selection; // May be set by brush.move!
if (lockX) w1 = selection[0][0], e1 = selection[1][0];
if (lockY) n1 = selection[0][1], s1 = selection[1][1];
if (selection[0][0] !== w1
|| selection[0][1] !== n1
|| selection[1][0] !== e1
|| selection[1][1] !== s1) {
state.selection = [[w1, n1], [e1, s1]];
redraw.call(that);
emit.brush(event, mode.name);
}
}
function ended(event) {
nopropagation(event);
if (event.touches) {
if (event.touches.length) return;
if (touchending) clearTimeout(touchending);
touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
} else {
dragEnable(event.view, moving);
view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
}
group.attr("pointer-events", "all");
overlay.attr("cursor", cursors.overlay);
if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
if (empty(selection)) state.selection = null, redraw.call(that);
emit.end(event, mode.name);
}
function keydowned(event) {
switch (event.keyCode) {
case 16: { // SHIFT
shifting = signX && signY;
break;
}
case 18: { // ALT
if (mode === MODE_HANDLE) {
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
mode = MODE_CENTER;
move(event);
}
break;
}
case 32: { // SPACE; takes priority over ALT
if (mode === MODE_HANDLE || mode === MODE_CENTER) {
if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
mode = MODE_SPACE;
overlay.attr("cursor", cursors.selection);
move(event);
}
break;
}
default: return;
}
noevent(event);
}
function keyupped(event) {
switch (event.keyCode) {
case 16: { // SHIFT
if (shifting) {
lockX = lockY = shifting = false;
move(event);
}
break;
}
case 18: { // ALT
if (mode === MODE_CENTER) {
if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
mode = MODE_HANDLE;
move(event);
}
break;
}
case 32: { // SPACE
if (mode === MODE_SPACE) {
if (event.altKey) {
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
mode = MODE_CENTER;
} else {
if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
mode = MODE_HANDLE;
}
overlay.attr("cursor", cursors[type]);
move(event);
}
break;
}
default: return;
}
noevent(event);
}
}
function touchmoved(event) {
emitter(this, arguments).moved(event);
}
function touchended(event) {
emitter(this, arguments).ended(event);
}
function initialize() {
var state = this.__brush || {selection: null};
state.extent = number2(extent.apply(this, arguments));
state.dim = dim;
return state;
}
brush.extent = function(_) {
return arguments.length ? (extent = typeof _ === "function" ? _ : constant(number2(_)), brush) : extent;
};
brush.filter = function(_) {
return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), brush) : filter;
};
brush.touchable = function(_) {
return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), brush) : touchable;
};
brush.handleSize = function(_) {
return arguments.length ? (handleSize = +_, brush) : handleSize;
};
brush.keyModifiers = function(_) {
return arguments.length ? (keys = !!_, brush) : keys;
};
brush.on = function() {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? brush : value;
};
return brush;
}
Example #22
Source File: LogLikPlot.js From likelihood with MIT License | 4 votes |
logLikCart = props => {
const vizRef = useRef(null);
const dispatch = useContext(VizDispatch);
// Stuff
const margin = { top: 60, right: 20, bottom: 40, left: 50 };
const durationTime = 200;
const w = props.width - margin.left - margin.right;
const h = props.width * 0.4 - margin.top - margin.bottom;
const sample = props.sample;
const sigmaTheta = Math.sqrt(props.sigma2Theta);
const deriv = props.deriv;
const data1 = props.data;
// Axes min and max
var xMax, xMin, llTheta;
if (props.thetaLab == "mu") {
xMax = props.muTheta + sigmaTheta * 5;
xMin = props.muTheta - sigmaTheta * 5;
llTheta = useMemo(() => logLikSum(sample, props.mu, props.sigma2), [
props.mu,
props.sigma2,
props.sample
]);
} else if (props.thetaLab == "sigma") {
const sigma2MLE = props.sigma2Theta;
xMax = sigma2MLE + sigma2MLE * 2;
xMin = sigma2MLE - sigma2MLE * 5;
xMin = xMin < 0 ? 0.1 : xMin;
llTheta = useMemo(() =>
logLikSum(sample, props.mu, props.sigma2, [
props.mu,
props.sigma2,
props.sample
])
);
}
const x_range = range(xMin, xMax, Math.abs(xMax - xMin) / 50);
const newtonParabola = x_range.map(x1 => {
return [
x1,
quadraticApprox(x1 - props.mu, 1, llTheta, deriv, -10 / props.sigma2)
];
});
const yMin = -100;
const yMax = -20;
const [spring, set] = useSpring(() => ({
xy: [props.mu, props.sigma2],
immediate: false,
config: { duration: 500 }
}));
set({ xy: [props.mu, props.sigma2], immediate: !props.animating });
const bind = useDrag(({ movement: [mx, my], first, memo }) => {
const muStart = first ? props.mu : memo[0];
const sigma2Start = first ? props.sigma2 : memo[1];
const mu = xScale.invert(xScale(muStart) + mx);
const sigma2 = yScale.invert(yScale(sigma2Start) + my);
dispatch({
name: "contourDrag",
value: { mu: mu, sigma2: props.sigma2 }
});
return [muStart, sigma2Start];
});
//const yMax = 0.05;
// Create scales
const yScale = scaleLinear()
.domain([yMin, yMax])
.range([h, 0]);
const xScale = scaleLinear()
.domain([xMin, xMax])
.range([0, w]);
// Scales and Axis
const xAxis = axisBottom(xScale);
const yAxis = axisLeft(yScale).ticks(4);
// Line function
const linex = line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]));
// Update
useEffect(() => {
createChart(durationTime);
}, [props.mu, props.sigma2, w, props.sample]);
const gradientNext = gradientStep(props);
const gradientNextLL = logLikSum(
sample,
gradientNext.points.mu,
props.sigma2
);
// Tooltip
const Tooltip = ({ theta, thetaLab, ll, deriv }) => {
const x = 0;
const y = 0;
const width = 100;
const path = topTooltipPath(width, 40, 10, 10);
const thetaSymb = thetaLab == "mu" ? "mu" : "sigma^2";
const eqLogLik = katex.renderToString(
`\\frac{\\partial}{\\partial \\${thetaSymb}}\\ell = `,
{
displayMode: false,
throwOnError: false
}
);
return (
<g>
<path
d={path}
className="polygonTip"
transform={`translate(${x + margin.left}, ${y + margin.top - 5})`}
/>
<foreignObject
x={x - width / 2 + margin.left}
y={y}
width={width}
height={50}
>
<div className="vizTooltip">
<p>
<span dangerouslySetInnerHTML={{ __html: eqLogLik }} />
{format(".2f")(deriv)}
</p>
</div>
</foreignObject>
</g>
);
};
const createChart = () => {
const node = vizRef.current;
select(node)
.selectAll("g.viz")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x Axis
select(node)
.selectAll("g.xAxis")
.data([0])
.enter()
.append("g")
.attr("class", "xAxis");
select(node)
.select("g.xAxis")
.attr(
"transform",
"translate(" + margin.left + "," + (h + margin.top) + ")"
)
.call(xAxis);
// y Axis
select(node)
.selectAll("g.yAxis")
.data([0])
.enter()
.append("g")
.attr("class", "yAxis");
select(node)
.select("g.yAxis")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
const gViz = select(node)
.selectAll("g.viz")
.data([0])
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x label
gViz
.selectAll(".x-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("class", "x-label MuiTypography-body1");
select(node)
.selectAll(".x-label")
.attr(
"transform",
"translate(" + w / 2 + " ," + (h + margin.bottom - 5) + ")"
)
.text(props.thetaLab == "mu" ? "μ" : "σ²");
// y label
gViz
.selectAll(".y-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("class", "y-label MuiTypography-body2");
select(node)
.selectAll(".y-label")
.attr("transform", "rotate(-90)")
.attr("text-anchor", "middle")
.attr("x", -(h / 2))
.attr("y", -40)
.text(`ℓ(μ, σ² = ${format(".2f")(props.sigma2)})`);
};
const delta = xMax - xMin;
return (
<svg width={props.width} height={props.width * 0.4}>
<g ref={vizRef}>
<g className="viz">
<g clipPath="url(#clipMu)">
<AnimatedPath
data={data1.data}
x={100}
sigma2={props.sigma2}
xScale={xScale}
yScale={yScale}
linex={linex}
mu={props.mu}
sample={sample}
animating={props.animating}
className="LogLikMu"
/>
{props.algo == "newtonRaphson" && (
<AnimatedPath
data={newtonParabola}
x={100}
sigma2={props.sigma2}
xScale={xScale}
yScale={yScale}
linex={linex}
mu={props.mu}
sample={sample}
animating={props.animating}
className="LogLikNewton"
/>
)}
{props.algo == "gradientAscent" && (
<>
<circle
cx={xScale(gradientNext.points.mu)}
cy={yScale(gradientNextLL)}
r="5"
className="logLikNewtonX--approx"
/>
<line
className="LogLikNewton--maxima"
y1={yScale(yMin)}
y2={yScale(gradientNextLL)}
x1={xScale(gradientNext.points.mu)}
x2={xScale(gradientNext.points.mu)}
/>
</>
)}
</g>
</g>
</g>
<g clipPath="url(#clipMu2)">
<animated.g
{...bind()}
transform={spring.xy.interpolate(
(x, y) =>
`translate(${xScale(x)}, ${yScale(logLikSum(sample, x, y))})`
)}
className="draggable"
>
<circle
cx={margin.left}
cy={margin.top}
r="5"
className="logLikX"
/>
<animated.line
className="deriv"
y1={spring.xy.interpolate(
(x, y) =>
margin.top + yScale(yMax - delta * dMu(10, x, props.muHat, y))
)}
y2={spring.xy.interpolate(
(x, y) =>
margin.top + yScale(yMax + delta * dMu(10, x, props.muHat, y))
)}
x1={margin.left + xScale(xMin - delta)}
x2={margin.left + xScale(xMin + delta)}
/>
<Tooltip
theta={props.theta}
thetaLab={props.thetaLab}
ll={llTheta}
deriv={deriv}
/>
</animated.g>
</g>
<defs>
<clipPath id="clipMu">
<rect id="clip-rectMu" x="0" y="-10" width={w} height={h + 10} />
</clipPath>
<clipPath id="clipMu2">
<rect
id="clip-rectMu"
x={margin.left}
y={-margin.bottom}
width={w}
height={h + 100}
/>
</clipPath>
</defs>
</svg>
);
}
Example #23
Source File: zoom.js From gamedesign with GNU General Public License v3.0 | 4 votes |
export default function() {
var filter = defaultFilter,
extent = defaultExtent,
constrain = defaultConstrain,
wheelDelta = defaultWheelDelta,
touchable = defaultTouchable,
scaleExtent = [0, Infinity],
translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]],
duration = 250,
interpolate = interpolateZoom,
gestures = [],
listeners = dispatch("start", "zoom", "end"),
touchstarting,
touchending,
touchDelay = 500,
wheelDelay = 150,
clickDistance2 = 0;
function zoom(selection) {
selection
.property("__zoom", defaultTransform)
.on("wheel.zoom", wheeled)
.on("mousedown.zoom", mousedowned)
.on("dblclick.zoom", dblclicked)
.filter(touchable)
.on("touchstart.zoom", touchstarted)
.on("touchmove.zoom", touchmoved)
.on("touchend.zoom touchcancel.zoom", touchended)
.style("touch-action", "none")
.style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
}
zoom.transform = function(collection, transform) {
var selection = collection.selection ? collection.selection() : collection;
selection.property("__zoom", defaultTransform);
if (collection !== selection) {
schedule(collection, transform);
} else {
selection.interrupt().each(function() {
gesture(this, arguments)
.start()
.zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
.end();
});
}
};
zoom.scaleBy = function(selection, k) {
zoom.scaleTo(selection, function() {
var k0 = this.__zoom.k,
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return k0 * k1;
});
};
zoom.scaleTo = function(selection, k) {
zoom.transform(selection, function() {
var e = extent.apply(this, arguments),
t0 = this.__zoom,
p0 = centroid(e),
p1 = t0.invert(p0),
k1 = typeof k === "function" ? k.apply(this, arguments) : k;
return constrain(translate(scale(t0, k1), p0, p1), e, translateExtent);
});
};
zoom.translateBy = function(selection, x, y) {
zoom.transform(selection, function() {
return constrain(this.__zoom.translate(
typeof x === "function" ? x.apply(this, arguments) : x,
typeof y === "function" ? y.apply(this, arguments) : y
), extent.apply(this, arguments), translateExtent);
});
};
zoom.translateTo = function(selection, x, y) {
zoom.transform(selection, function() {
var e = extent.apply(this, arguments),
t = this.__zoom,
p = centroid(e);
return constrain(identity.translate(p[0], p[1]).scale(t.k).translate(
typeof x === "function" ? -x.apply(this, arguments) : -x,
typeof y === "function" ? -y.apply(this, arguments) : -y
), e, translateExtent);
});
};
function scale(transform, k) {
k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k));
return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
}
function translate(transform, p0, p1) {
var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
}
function centroid(extent) {
return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
}
function schedule(transition, transform, center) {
transition
.on("start.zoom", function() { gesture(this, arguments).start(); })
.on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
.tween("zoom", function() {
var that = this,
args = arguments,
g = gesture(that, args),
e = extent.apply(that, args),
p = center || centroid(e),
w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
a = that.__zoom,
b = typeof transform === "function" ? transform.apply(that, args) : transform,
i = interpolate(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
return function(t) {
if (t === 1) t = b; // Avoid rounding error on end.
else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
g.zoom(null, t);
};
});
}
function gesture(that, args) {
for (var i = 0, n = gestures.length, g; i < n; ++i) {
if ((g = gestures[i]).that === that) {
return g;
}
}
return new Gesture(that, args);
}
function Gesture(that, args) {
this.that = that;
this.args = args;
this.index = -1;
this.active = 0;
this.extent = extent.apply(that, args);
}
Gesture.prototype = {
start: function() {
if (++this.active === 1) {
this.index = gestures.push(this) - 1;
this.emit("start");
}
return this;
},
zoom: function(key, transform) {
if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
this.that.__zoom = transform;
this.emit("zoom");
return this;
},
end: function() {
if (--this.active === 0) {
gestures.splice(this.index, 1);
this.index = -1;
this.emit("end");
}
return this;
},
emit: function(type) {
customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
}
};
function wheeled() {
if (!filter.apply(this, arguments)) return;
var g = gesture(this, arguments),
t = this.__zoom,
k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))),
p = mouse(this);
// If the mouse is in the same location as before, reuse it.
// If there were recent wheel events, reset the wheel idle timeout.
if (g.wheel) {
if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
g.mouse[1] = t.invert(g.mouse[0] = p);
}
clearTimeout(g.wheel);
}
// If this wheel event won’t trigger a transform change, ignore it.
else if (t.k === k) return;
// Otherwise, capture the mouse point and location at the start.
else {
g.mouse = [p, t.invert(p)];
interrupt(this);
g.start();
}
noevent();
g.wheel = setTimeout(wheelidled, wheelDelay);
g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent, translateExtent));
function wheelidled() {
g.wheel = null;
g.end();
}
}
function mousedowned() {
if (touchending || !filter.apply(this, arguments)) return;
var g = gesture(this, arguments),
v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
p = mouse(this),
x0 = event.clientX,
y0 = event.clientY;
dragDisable(event.view);
nopropagation();
g.mouse = [p, this.__zoom.invert(p)];
interrupt(this);
g.start();
function mousemoved() {
noevent();
if (!g.moved) {
var dx = event.clientX - x0, dy = event.clientY - y0;
g.moved = dx * dx + dy * dy > clickDistance2;
}
g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent, translateExtent));
}
function mouseupped() {
v.on("mousemove.zoom mouseup.zoom", null);
dragEnable(event.view, g.moved);
noevent();
g.end();
}
}
function dblclicked() {
if (!filter.apply(this, arguments)) return;
var t0 = this.__zoom,
p0 = mouse(this),
p1 = t0.invert(p0),
k1 = t0.k * (event.shiftKey ? 0.5 : 2),
t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments), translateExtent);
noevent();
if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
else select(this).call(zoom.transform, t1);
}
function touchstarted() {
if (!filter.apply(this, arguments)) return;
var g = gesture(this, arguments),
touches = event.changedTouches,
started,
n = touches.length, i, t, p;
nopropagation();
for (i = 0; i < n; ++i) {
t = touches[i], p = touch(this, touches, t.identifier);
p = [p, this.__zoom.invert(p), t.identifier];
if (!g.touch0) g.touch0 = p, started = true;
else if (!g.touch1) g.touch1 = p;
}
// If this is a dbltap, reroute to the (optional) dblclick.zoom handler.
if (touchstarting) {
touchstarting = clearTimeout(touchstarting);
if (!g.touch1) {
g.end();
p = select(this).on("dblclick.zoom");
if (p) p.apply(this, arguments);
return;
}
}
if (started) {
touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
interrupt(this);
g.start();
}
}
function touchmoved() {
var g = gesture(this, arguments),
touches = event.changedTouches,
n = touches.length, i, t, p, l;
noevent();
if (touchstarting) touchstarting = clearTimeout(touchstarting);
for (i = 0; i < n; ++i) {
t = touches[i], p = touch(this, touches, t.identifier);
if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
}
t = g.that.__zoom;
if (g.touch1) {
var p0 = g.touch0[0], l0 = g.touch0[1],
p1 = g.touch1[0], l1 = g.touch1[1],
dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
t = scale(t, Math.sqrt(dp / dl));
p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
}
else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
else return;
g.zoom("touch", constrain(translate(t, p, l), g.extent, translateExtent));
}
function touchended() {
var g = gesture(this, arguments),
touches = event.changedTouches,
n = touches.length, i, t;
nopropagation();
if (touchending) clearTimeout(touchending);
touchending = setTimeout(function() { touchending = null; }, touchDelay);
for (i = 0; i < n; ++i) {
t = touches[i];
if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
}
if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);
else g.end();
}
zoom.wheelDelta = function(_) {
return arguments.length ? (wheelDelta = typeof _ === "function" ? _ : constant(+_), zoom) : wheelDelta;
};
zoom.filter = function(_) {
return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), zoom) : filter;
};
zoom.touchable = function(_) {
return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), zoom) : touchable;
};
zoom.extent = function(_) {
return arguments.length ? (extent = typeof _ === "function" ? _ : constant([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
};
zoom.scaleExtent = function(_) {
return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom) : [scaleExtent[0], scaleExtent[1]];
};
zoom.translateExtent = function(_) {
return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];
};
zoom.constrain = function(_) {
return arguments.length ? (constrain = _, zoom) : constrain;
};
zoom.duration = function(_) {
return arguments.length ? (duration = +_, zoom) : duration;
};
zoom.interpolate = function(_) {
return arguments.length ? (interpolate = _, zoom) : interpolate;
};
zoom.on = function() {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? zoom : value;
};
zoom.clickDistance = function(_) {
return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom) : Math.sqrt(clickDistance2);
};
return zoom;
}
Example #24
Source File: diagram.js From the-eye-knows-the-garbage with MIT License | 4 votes |
/*global console:true*/
export function VennDiagram() {
var width = 600,
height = 350,
padding = 15,
duration = 1000,
orientation = Math.PI / 2,
normalize = true,
wrap = true,
styled = true,
fontSize = null,
orientationOrder = null,
// mimic the behaviour of d3.scale.category10 from the previous
// version of d3
colourMap = {},
// so this is the same as d3.schemeCategory10, which is only defined in d3 4.0
// since we can support older versions of d3 as long as we don't force this,
// I'm hackily redefining below. TODO: remove this and change to d3.schemeCategory10
colourScheme = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd", "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"],
colourIndex = 0,
colours = function(key) {
if (key in colourMap) {
return colourMap[key];
}
var ret = colourMap[key] = colourScheme[colourIndex];
colourIndex += 1;
if (colourIndex >= colourScheme.length) {
colourIndex = 0;
}
return ret;
},
layoutFunction = venn,
loss = lossFunction;
function chart(selection) {
var data = selection.datum();
// handle 0-sized sets by removing from input
var toremove = {};
data.forEach(function(datum) {
if ((datum.size == 0) && datum.sets.length == 1) {
toremove[datum.sets[0]] = 1;
}
});
data = data.filter(function(datum) {
return !datum.sets.some(function(set) { return set in toremove; });
});
var circles = {};
var textCentres = {};
if (data.length > 0) {
var solution = layoutFunction(data, {lossFunction: loss});
if (normalize) {
solution = normalizeSolution(solution,
orientation,
orientationOrder);
}
circles = scaleSolution(solution, width, height, padding);
textCentres = computeTextCentres(circles, data);
}
// Figure out the current label for each set. These can change
// and D3 won't necessarily update (fixes https://github.com/benfred/venn.js/issues/103)
var labels = {};
data.forEach(function(datum) {
if (datum.label) {
labels[datum.sets] = datum.label;
}
});
function label(d) {
if (d.sets in labels) {
return labels[d.sets];
}
if (d.sets.length == 1) {
return '' + d.sets[0];
}
}
// create svg if not already existing
selection.selectAll("svg").data([circles]).enter().append("svg");
var svg = selection.select("svg")
.attr("width", width)
.attr("height", height);
// to properly transition intersection areas, we need the
// previous circles locations. load from elements
var previous = {}, hasPrevious = false;
svg.selectAll(".venn-area path").each(function (d) {
var path = select(this).attr("d");
if ((d.sets.length == 1) && path) {
hasPrevious = true;
previous[d.sets[0]] = circleFromPath(path);
}
});
// interpolate intersection area paths between previous and
// current paths
var pathTween = function(d) {
return function(t) {
var c = d.sets.map(function(set) {
var start = previous[set], end = circles[set];
if (!start) {
start = {x : width/2, y : height/2, radius : 1};
}
if (!end) {
end = {x : width/2, y : height/2, radius : 1};
}
return {'x' : start.x * (1 - t) + end.x * t,
'y' : start.y * (1 - t) + end.y * t,
'radius' : start.radius * (1 - t) + end.radius * t};
});
return intersectionAreaPath(c);
};
};
// update data, joining on the set ids
var nodes = svg.selectAll(".venn-area")
.data(data, function(d) { return d.sets; });
// create new nodes
var enter = nodes.enter()
.append('g')
.attr("class", function(d) {
return "venn-area venn-" +
(d.sets.length == 1 ? "circle" : "intersection");
})
.attr("data-venn-sets", function(d) {
return d.sets.join("_");
});
var enterPath = enter.append("path"),
enterText = enter.append("text")
.attr("class", "label")
.text(function (d) { return label(d); } )
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.attr("x", width/2)
.attr("y", height/2);
// apply minimal style if wanted
if (styled) {
enterPath.style("fill-opacity", "0")
.filter(function (d) { return d.sets.length == 1; } )
.style("fill", function(d) { return colours(d.sets); })
.style("fill-opacity", ".25");
enterText
.style("fill", function(d) { return d.sets.length == 1 ? colours(d.sets) : "#444"; });
}
// update existing, using pathTween if necessary
var update = selection;
if (hasPrevious) {
update = selection.transition("venn").duration(duration);
update.selectAll("path")
.attrTween("d", pathTween);
} else {
update.selectAll("path")
.attr("d", function(d) {
return intersectionAreaPath(d.sets.map(function (set) { return circles[set]; }));
});
}
var updateText = update.selectAll("text")
.filter(function (d) { return d.sets in textCentres; })
.text(function (d) { return label(d); } )
.attr("x", function(d) { return Math.floor(textCentres[d.sets].x);})
.attr("y", function(d) { return Math.floor(textCentres[d.sets].y);});
if (wrap) {
if (hasPrevious) {
// d3 4.0 uses 'on' for events on transitions,
// but d3 3.0 used 'each' instead. switch appropiately
if ('on' in updateText) {
updateText.on("end", wrapText(circles, label));
} else {
updateText.each("end", wrapText(circles, label));
}
} else {
updateText.each(wrapText(circles, label));
}
}
// remove old
var exit = nodes.exit().transition('venn').duration(duration).remove();
exit.selectAll("path")
.attrTween("d", pathTween);
var exitText = exit.selectAll("text")
.attr("x", width/2)
.attr("y", height/2);
// if we've been passed a fontSize explicitly, use it to
// transition
if (fontSize !== null) {
enterText.style("font-size", "0px");
updateText.style("font-size", fontSize);
exitText.style("font-size", "0px");
}
return {'circles': circles,
'textCentres': textCentres,
'nodes': nodes,
'enter': enter,
'update': update,
'exit': exit};
}
chart.wrap = function(_) {
if (!arguments.length) return wrap;
wrap = _;
return chart;
};
chart.width = function(_) {
if (!arguments.length) return width;
width = _;
return chart;
};
chart.height = function(_) {
if (!arguments.length) return height;
height = _;
return chart;
};
chart.padding = function(_) {
if (!arguments.length) return padding;
padding = _;
return chart;
};
chart.colours = function(_) {
if (!arguments.length) return colours;
colours = _;
return chart;
};
chart.fontSize = function(_) {
if (!arguments.length) return fontSize;
fontSize = _;
return chart;
};
chart.duration = function(_) {
if (!arguments.length) return duration;
duration = _;
return chart;
};
chart.layoutFunction = function(_) {
if (!arguments.length) return layoutFunction;
layoutFunction = _;
return chart;
};
chart.normalize = function(_) {
if (!arguments.length) return normalize;
normalize = _;
return chart;
};
chart.styled = function(_) {
if (!arguments.length) return styled;
styled = _;
return chart;
};
chart.orientation = function(_) {
if (!arguments.length) return orientation;
orientation = _;
return chart;
};
chart.orientationOrder = function(_) {
if (!arguments.length) return orientationOrder;
orientationOrder = _;
return chart;
};
chart.lossFunction = function(_) {
if (!arguments.length) return loss;
loss = _;
return chart;
};
return chart;
}
Example #25
Source File: index.js From react-orgchart with MIT License | 4 votes |
export function init(options) {
// Merge options with the default config
const config = {
...options,
treeData: options.data,
};
if (!config.id) {
throw new Error('missing id for svg root');
}
const {
elem,
treeData,
nodeWidth,
nodeHeight,
nodeSpacing,
shouldResize,
disableCanvasMouseWheelZoom,
disableCanvasMouseMove,
} = config;
// Calculate how many pixel nodes to be spaced based on the
// type of line that needs to be rendered
config.lineDepthY = nodeHeight + 40;
if (!elem) {
throw new Error('No root elem');
}
// Reset in case there's any existing DOM
elem.innerHTML = '';
const elemWidth = elem.offsetWidth;
const elemHeight = elem.offsetHeight;
// Setup the d3 tree layout
config.tree = hierarchy(treeData, function (d) {
return d.children;
});
config.treeMap = tree(config.tree).nodeSize([nodeWidth + nodeSpacing, nodeHeight + nodeSpacing]);
// Collapse tree on load
config.treeMap(config.tree).descendants().slice(1).forEach(collapse);
// Calculate width of a node with expanded children
// const childrenWidth = parseInt((treeData.children.length * nodeWidth) / 2)
// <svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" xml:space="preserve" viewBox="0 0 193 260" enable-background=" new 0 0 193 260" height="260" width="193"
// Add svg root for d3
const svgroot = select(elem)
.append('svg')
.attr('id', 'svg')
.attr('xmlns', 'http://www.w3.org/2000/svg')
.attr('xmlns:xlink', 'http://www.w3.org/1999/xlink')
.attr('x', '0px')
.attr('y', '0px')
.attr('xml:space', 'preserve')
.attr('viewBox', `0 0 ${elemWidth} ${elemHeight}`)
.attr('enable-background', ` new 0 0 ${elemWidth} ${elemHeight}`)
.attr('width', elemWidth)
.attr('height', elemHeight);
// Graph center point
const centerPoint = elemWidth / 2 - nodeWidth / 2 + 15;
// Add our base svg group to transform when a user zooms/pans
const svg = svgroot.append('g');
// Connect core variables to config so that they can be
// used in internal rendering functions
config.svg = svg;
config.svgroot = svgroot;
config.elemWidth = elemWidth;
config.elemHeight = elemHeight;
config.render = render;
// Defined zoom behavior
const zoom = zoomer()
.scaleExtent([0.1, 1.5])
.duration(50)
.on('zoom', zoomEvent => {
svg.attr('transform', () => {
return zoomEvent.transform;
});
});
svgroot.call(zoom.transform, zoomIdentity.translate(centerPoint, 48).scale(0.8));
const zoomedRoot = svgroot.call(zoom);
// Disable the Mouse Wheel Zooming
if (disableCanvasMouseWheelZoom) {
zoomedRoot.on('wheel.zoom', null);
}
// Disable the Mouse Wheel Canvas Content Moving
if (disableCanvasMouseMove) {
zoomedRoot
.on('mousedown.zoom', null)
.on('touchstart.zoom', null)
.on('touchmove.zoom', null)
.on('touchend.zoom', null);
}
// Add avatar clip path
const defs = svgroot.append('svg:defs');
defs
.append('clipPath')
.attr('id', 'avatarClip')
.append('circle')
.attr('cx', 70)
.attr('cy', 32)
.attr('r', 24);
// Add boxshadow
const filter = svgroot
.append('svg:defs')
.append('svg:filter')
.attr('id', 'boxShadow')
.attr('height', '150%')
.attr('width', '150%');
filter
.append('svg:feGaussianBlur')
.attr('in', 'SourceAlpha')
.attr('stdDeviation', 1) // blur amount
.attr('result', 'blurOut');
filter
.append('svg:feOffset')
.attr('in', 'blurOut')
.attr('dx', 0)
.attr('dy', 2)
.attr('result', 'offsetOut');
const feMerge = filter.append('feMerge');
feMerge.append('feMergeNode').attr('in', 'offsetOut');
feMerge.append('feMergeNode').attr('in', 'SourceGraphic');
// Add listener for when the browser or parent node resizes
const resize = () => {
if (!elem) {
window.removeEventListener('resize', resize);
return;
}
svgroot.attr('width', elem.offsetWidth).attr('height', elem.offsetHeight);
};
if (shouldResize) {
window.addEventListener('resize', resize);
}
// Start initial render
render(config);
// return OnDestroy fn
return () => {
svgroot.remove();
if (shouldResize) {
window.removeEventListener('resize', resize);
}
};
}
Example #26
Source File: SamplePlot.js From likelihood with MIT License | 4 votes |
SampleChart = props => {
const vizRef = useRef(null);
// Stuff
const margin = { top: 60, right: 20, bottom: 30, left: 50 };
const durationTime = 200;
const w = props.width - margin.left - margin.right;
const h = props.width * aspect - margin.top - margin.bottom;
const sample = props.sample;
const sigma = Math.sqrt(props.sigma2)
const sigmaTheta = Math.sqrt(props.sigma2Theta)
// x.values
const x_start = props.muTheta - 10 * sigmaTheta;
const x_end = props.muTheta + 10 * sigmaTheta;
const x_start2 = props.mu - 3 * sigma;
const x_end2 = props.mu + 3 * sigma;
const x = range( props.mu - 3 * sigma,
props.mu + 3 * sigma, Math.abs(x_start2 - x_end2) / 50);
x.push(x_end)
x.unshift(x_start)
// Data sets
const data1 = genData(props.mu, sigma, x);
// Axes min and max
const x_max = props.muTheta + sigmaTheta * 5;
const x_min = props.muTheta - sigmaTheta * 5;
//const y_max = max(data1.y);
const y_max = 0.04;
// Create scales
const yScale = scaleLinear()
.domain([0, y_max])
.range([h, 0]);
const xScale = scaleLinear()
.domain([x_min, x_max])
.range([0, w]);
// Scales and Axis
const xAxis = axisBottom(xScale);
const yAxis = axisLeft(yScale);
// Update
useEffect(() => {
createSampleChart(durationTime);
}, [props.mu, props.sigma2, props.highlight, props.sample, w]);
// Tooltip
const Tooltip = ({ d, i }) => {
const x = xScale(d);
const L = normal.pdf(d, props.mu, sigma);
const y = yScale(L);
const path = topTooltipPath(150, 50, 10, 10);
const width = 150;
const eqLogLik = katex.renderToString(`\\ell_{${i + 1}} = `, {
displayMode: false,
throwOnError: false
});
return (
<g>
<path
d={path}
className="polygonTip1"
transform={`translate(${x + margin.left}, ${y + margin.top })`}
/>
<foreignObject
x={x - width / 2 + margin.left}
y={y }
width={width}
height={50}
>
<div className="vizTooltip">
<p>
<span dangerouslySetInnerHTML={{ __html: eqLogLik }} />
log({format(".2n")(L)})
</p>
</div>
</foreignObject>
</g>
);
};
const createSampleChart = () => {
const node = vizRef.current;
// Line function
const linex = line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]));
select(node)
.selectAll("g.viz")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x Axis
select(node)
.selectAll("g.xAxis")
.data([0])
.enter()
.append("g")
.attr("class", "xAxis");
select(node)
.select("g.xAxis")
.attr(
"transform",
"translate(" + margin.left + "," + (h + margin.top) + ")"
)
.call(xAxis);
// y Axis
select(node)
.selectAll("g.yAxis")
.data([0])
.enter()
.append("g")
.attr("class", "yAxis");
select(node)
.select("g.yAxis")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(yAxis);
const gViz = select(node)
.selectAll("g.viz")
.data([0])
.enter()
.append("g")
.attr("class", "viz")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// x label
gViz
.selectAll(".x-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("class", "x-label");
select(node)
.selectAll(".x-label")
.attr(
"transform",
"translate(" + w / 2 + " ," + (h + margin.bottom) + ")"
)
.text(props.xLabel);
// y label
gViz
.selectAll("#y-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("id", "y-label");
select(node)
.selectAll("#y-label")
.attr("transform", "rotate(-90)")
.attr("text-anchor", "middle")
.attr("x", -(h / 2))
.attr("y", -40)
.text("Density");
// Append dists
// DIST1
gViz
.selectAll("#dist1")
.data([data1.data])
.enter()
.append("svg:path")
.attr("d", linex)
.attr("id", "dist1");
select(node)
.selectAll("#dist1")
.data([data1.data])
.attr("d", linex);
// mu vertical lines
const sampleLines = (mu, id) => {
gViz
.selectAll("#" + id)
.data([0])
.enter()
.append("line")
.attr("class", "logLikLines")
.attr("id", id);
select(node)
.selectAll("#" + id)
.data([0])
.attr("x1", xScale(mu))
.attr("x2", xScale(mu))
.attr("y1", yScale(normal.pdf(mu, props.mu, sigma)))
.attr("y2", yScale(0));
};
//muLines(props.mu0, "mu0");
sample.map((x, i) => sampleLines(x, `sample${i}`));
// Points
gViz
.selectAll("circle")
.data(sample)
.enter()
.append("svg:circle")
.attr("cy", d => yScale(normal.pdf(d, props.mu, sigma)))
.attr("cx", d => xScale(d));
select(node)
.selectAll("circle")
.data(sample)
.attr("cy", d => yScale(normal.pdf(d, props.mu, sigma)))
.attr("cx", d => xScale(d))
.attr("class", "sampleCircles")
.on("mouseover", function(d, i) {
props.setHighlight(i);
select(this).attr("r", 10)
})
.on("mouseout", function() {
props.setHighlight();
select(this).attr("r", 5)
})
.attr("r", (d, i) => {
const r = props.highlight == i ? 10 : 5;
return r;
});
};
return (
<svg width={props.width} height={props.width * aspect}>
<g ref={vizRef} />
{props.highlight >= 0 && (
<Tooltip d={sample[props.highlight]} i={props.highlight} />
)}
</svg>
);
}
Example #27
Source File: statusboard.js From covid19japan-data with MIT License | 4 votes |
createPrefectureRow = (placeName, prefectureSource, rowNumber, prefectureCity) => {
let name = placeName
if (prefectureCity) {
name = ` ↳ ${placeName}`
}
let placeId = placeName.toLowerCase()
let htmlClass = 'item'
if (prefectureCity) {
htmlClass = 'item city'
}
select('#statusboard')
.append('div')
.attr('class', htmlClass + ' place')
.style('grid-row', rowNumber)
.style('grid-column', 'place')
.append('a')
.attr('href', '#')
.html(name)
.on('click', () => {
event.preventDefault()
fetchPrefectureData(prefectureSource, placeId)
fetchPrefectureSummary(prefectureSource, placeId)
fetchPrefectureLatest(prefectureSource, placeId)
})
if (prefectureSource) {
if (prefectureSource.dashboard) {
select('#statusboard')
.append('div')
.attr('class', 'item')
.style('grid-row', rowNumber)
.style('grid-column', 'dash-link')
.append('a')
.attr('href', prefectureSource.dashboard)
.attr('target', '_blank')
.text('dash')
}
if (prefectureSource.gov) {
if (prefectureSource.gov.patients) {
select('#statusboard')
.append('div')
.attr('class', htmlClass)
.style('grid-row', rowNumber)
.style('grid-column', 'gov-link-patients')
.append('a')
.attr('href', prefectureSource.gov.patients)
.attr('target', '_blank')
.text('reports')
}
if (prefectureSource.gov.summary) {
select('#statusboard')
.append('div')
.attr('class', htmlClass)
.style('grid-row', rowNumber)
.style('grid-column', 'gov-link-summary')
.append('a')
.attr('href', prefectureSource.gov.summary)
.attr('target', '_blank')
.text('sum')
}
if (prefectureSource.gov.deaths) {
select('#statusboard')
.append('div')
.attr('class', htmlClass)
.style('grid-row', rowNumber)
.style('grid-column', 'gov-link-deaths')
.append('a')
.attr('href', prefectureSource.gov.deaths)
.attr('target', '_blank')
.text('deaths')
}
if (prefectureSource.gov.patientList) {
select('#statusboard')
.append('div')
.attr('class', htmlClass)
.style('grid-row', rowNumber)
.style('grid-column', 'gov-link-list')
.append('a')
.attr('href', prefectureSource.gov.patientList)
.attr('target', '_blank')
.text('list')
}
}
}
}
Example #28
Source File: brush.js From akaunting with GNU General Public License v3.0 | 4 votes |
function brush(dim) {
var extent = defaultExtent,
filter = defaultFilter,
touchable = defaultTouchable,
keys = true,
listeners = dispatch("start", "brush", "end"),
handleSize = 6,
touchending;
function brush(group) {
var overlay = group
.property("__brush", initialize)
.selectAll(".overlay")
.data([type("overlay")]);
overlay.enter().append("rect")
.attr("class", "overlay")
.attr("pointer-events", "all")
.attr("cursor", cursors.overlay)
.merge(overlay)
.each(function() {
var extent = local(this).extent;
select(this)
.attr("x", extent[0][0])
.attr("y", extent[0][1])
.attr("width", extent[1][0] - extent[0][0])
.attr("height", extent[1][1] - extent[0][1]);
});
group.selectAll(".selection")
.data([type("selection")])
.enter().append("rect")
.attr("class", "selection")
.attr("cursor", cursors.selection)
.attr("fill", "#777")
.attr("fill-opacity", 0.3)
.attr("stroke", "#fff")
.attr("shape-rendering", "crispEdges");
var handle = group.selectAll(".handle")
.data(dim.handles, function(d) { return d.type; });
handle.exit().remove();
handle.enter().append("rect")
.attr("class", function(d) { return "handle handle--" + d.type; })
.attr("cursor", function(d) { return cursors[d.type]; });
group
.each(redraw)
.attr("fill", "none")
.attr("pointer-events", "all")
.on("mousedown.brush", started)
.filter(touchable)
.on("touchstart.brush", started)
.on("touchmove.brush", touchmoved)
.on("touchend.brush touchcancel.brush", touchended)
.style("touch-action", "none")
.style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
}
brush.move = function(group, selection) {
if (group.selection) {
group
.on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
.on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
.tween("brush", function() {
var that = this,
state = that.__brush,
emit = emitter(that, arguments),
selection0 = state.selection,
selection1 = dim.input(typeof selection === "function" ? selection.apply(this, arguments) : selection, state.extent),
i = interpolate(selection0, selection1);
function tween(t) {
state.selection = t === 1 && selection1 === null ? null : i(t);
redraw.call(that);
emit.brush();
}
return selection0 !== null && selection1 !== null ? tween : tween(1);
});
} else {
group
.each(function() {
var that = this,
args = arguments,
state = that.__brush,
selection1 = dim.input(typeof selection === "function" ? selection.apply(that, args) : selection, state.extent),
emit = emitter(that, args).beforestart();
interrupt(that);
state.selection = selection1 === null ? null : selection1;
redraw.call(that);
emit.start().brush().end();
});
}
};
brush.clear = function(group) {
brush.move(group, null);
};
function redraw() {
var group = select(this),
selection = local(this).selection;
if (selection) {
group.selectAll(".selection")
.style("display", null)
.attr("x", selection[0][0])
.attr("y", selection[0][1])
.attr("width", selection[1][0] - selection[0][0])
.attr("height", selection[1][1] - selection[0][1]);
group.selectAll(".handle")
.style("display", null)
.attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection[1][0] - handleSize / 2 : selection[0][0] - handleSize / 2; })
.attr("y", function(d) { return d.type[0] === "s" ? selection[1][1] - handleSize / 2 : selection[0][1] - handleSize / 2; })
.attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection[1][0] - selection[0][0] + handleSize : handleSize; })
.attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection[1][1] - selection[0][1] + handleSize : handleSize; });
}
else {
group.selectAll(".selection,.handle")
.style("display", "none")
.attr("x", null)
.attr("y", null)
.attr("width", null)
.attr("height", null);
}
}
function emitter(that, args, clean) {
return (!clean && that.__brush.emitter) || new Emitter(that, args);
}
function Emitter(that, args) {
this.that = that;
this.args = args;
this.state = that.__brush;
this.active = 0;
}
Emitter.prototype = {
beforestart: function() {
if (++this.active === 1) this.state.emitter = this, this.starting = true;
return this;
},
start: function() {
if (this.starting) this.starting = false, this.emit("start");
else this.emit("brush");
return this;
},
brush: function() {
this.emit("brush");
return this;
},
end: function() {
if (--this.active === 0) delete this.state.emitter, this.emit("end");
return this;
},
emit: function(type) {
customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
}
};
function started() {
if (touchending && !event.touches) return;
if (!filter.apply(this, arguments)) return;
var that = this,
type = event.target.__data__.type,
mode = (keys && event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (keys && event.altKey ? MODE_CENTER : MODE_HANDLE),
signX = dim === Y ? null : signsX[type],
signY = dim === X ? null : signsY[type],
state = local(that),
extent = state.extent,
selection = state.selection,
W = extent[0][0], w0, w1,
N = extent[0][1], n0, n1,
E = extent[1][0], e0, e1,
S = extent[1][1], s0, s1,
dx = 0,
dy = 0,
moving,
shifting = signX && signY && keys && event.shiftKey,
lockX,
lockY,
pointer = event.touches ? toucher(event.changedTouches[0].identifier) : mouse,
point0 = pointer(that),
point = point0,
emit = emitter(that, arguments, true).beforestart();
if (type === "overlay") {
if (selection) moving = true;
state.selection = selection = [
[w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
[e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
];
} else {
w0 = selection[0][0];
n0 = selection[0][1];
e0 = selection[1][0];
s0 = selection[1][1];
}
w1 = w0;
n1 = n0;
e1 = e0;
s1 = s0;
var group = select(that)
.attr("pointer-events", "none");
var overlay = group.selectAll(".overlay")
.attr("cursor", cursors[type]);
if (event.touches) {
emit.moved = moved;
emit.ended = ended;
} else {
var view = select(event.view)
.on("mousemove.brush", moved, true)
.on("mouseup.brush", ended, true);
if (keys) view
.on("keydown.brush", keydowned, true)
.on("keyup.brush", keyupped, true)
dragDisable(event.view);
}
nopropagation();
interrupt(that);
redraw.call(that);
emit.start();
function moved() {
var point1 = pointer(that);
if (shifting && !lockX && !lockY) {
if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
else lockX = true;
}
point = point1;
moving = true;
noevent();
move();
}
function move() {
var t;
dx = point[0] - point0[0];
dy = point[1] - point0[1];
switch (mode) {
case MODE_SPACE:
case MODE_DRAG: {
if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
break;
}
case MODE_HANDLE: {
if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
break;
}
case MODE_CENTER: {
if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
break;
}
}
if (e1 < w1) {
signX *= -1;
t = w0, w0 = e0, e0 = t;
t = w1, w1 = e1, e1 = t;
if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
}
if (s1 < n1) {
signY *= -1;
t = n0, n0 = s0, s0 = t;
t = n1, n1 = s1, s1 = t;
if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
}
if (state.selection) selection = state.selection; // May be set by brush.move!
if (lockX) w1 = selection[0][0], e1 = selection[1][0];
if (lockY) n1 = selection[0][1], s1 = selection[1][1];
if (selection[0][0] !== w1
|| selection[0][1] !== n1
|| selection[1][0] !== e1
|| selection[1][1] !== s1) {
state.selection = [[w1, n1], [e1, s1]];
redraw.call(that);
emit.brush();
}
}
function ended() {
nopropagation();
if (event.touches) {
if (event.touches.length) return;
if (touchending) clearTimeout(touchending);
touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
} else {
dragEnable(event.view, moving);
view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
}
group.attr("pointer-events", "all");
overlay.attr("cursor", cursors.overlay);
if (state.selection) selection = state.selection; // May be set by brush.move (on start)!
if (empty(selection)) state.selection = null, redraw.call(that);
emit.end();
}
function keydowned() {
switch (event.keyCode) {
case 16: { // SHIFT
shifting = signX && signY;
break;
}
case 18: { // ALT
if (mode === MODE_HANDLE) {
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
mode = MODE_CENTER;
move();
}
break;
}
case 32: { // SPACE; takes priority over ALT
if (mode === MODE_HANDLE || mode === MODE_CENTER) {
if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
mode = MODE_SPACE;
overlay.attr("cursor", cursors.selection);
move();
}
break;
}
default: return;
}
noevent();
}
function keyupped() {
switch (event.keyCode) {
case 16: { // SHIFT
if (shifting) {
lockX = lockY = shifting = false;
move();
}
break;
}
case 18: { // ALT
if (mode === MODE_CENTER) {
if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
mode = MODE_HANDLE;
move();
}
break;
}
case 32: { // SPACE
if (mode === MODE_SPACE) {
if (event.altKey) {
if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
mode = MODE_CENTER;
} else {
if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
mode = MODE_HANDLE;
}
overlay.attr("cursor", cursors[type]);
move();
}
break;
}
default: return;
}
noevent();
}
}
function touchmoved() {
emitter(this, arguments).moved();
}
function touchended() {
emitter(this, arguments).ended();
}
function initialize() {
var state = this.__brush || {selection: null};
state.extent = number2(extent.apply(this, arguments));
state.dim = dim;
return state;
}
brush.extent = function(_) {
return arguments.length ? (extent = typeof _ === "function" ? _ : constant(number2(_)), brush) : extent;
};
brush.filter = function(_) {
return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), brush) : filter;
};
brush.touchable = function(_) {
return arguments.length ? (touchable = typeof _ === "function" ? _ : constant(!!_), brush) : touchable;
};
brush.handleSize = function(_) {
return arguments.length ? (handleSize = +_, brush) : handleSize;
};
brush.keyModifiers = function(_) {
return arguments.length ? (keys = !!_, brush) : keys;
};
brush.on = function() {
var value = listeners.on.apply(listeners, arguments);
return value === listeners ? brush : value;
};
return brush;
}
Example #29
Source File: CurvaturePlot.js From likelihood with MIT License | 4 votes |
CurvatureChart = props => {
const vizRef = useRef(null);
// Stuff
const margin = { top: 20, right: 20, bottom: 30, left: 50 };
const durationTime = 200;
const w = props.width - margin.left - margin.right;
const h = props.width * 0.5 - margin.top - margin.bottom;
const deriv = props.deriv;
const llThetaMLE = props.llThetaMLE;
const llThetaNull = props.llThetaNull;
const test = props.test;
const n = props.n;
const muNull = props.muNull;
// Axes min and max
var xMax, xMin, llTheta;
const sigmaTheta = Math.sqrt(props.sigma2Theta);
xMax = props.muTheta + sigmaTheta * 5;
xMin = props.muTheta - sigmaTheta * 5;
llTheta = 0;
const data1 = useMemo(
() =>
genEstLogLikCurve(
10,
props.muHat,
props.sigma2Hat,
props.muTheta,
props.sigma2Theta
),
[props.width, props.sigma2Hat, props.muHat]
);
const data2 = useMemo(
() =>
genEstLogLikCurve(
n,
props.muHat,
props.sigma2Hat,
props.muTheta,
props.sigma2Theta
),
[n, props.width, props.sigma2Hat, props.muHat]
);
const yMin = min(data1.y.filter(y => isFinite(y)));
const yMax = max(data1.y);
//const yMax = 0.05;
// Create scales
const yScale = scaleLinear()
.domain([yMin, yMax])
.range([h, 0]);
const xScale = scaleLinear()
.domain([xMin, xMax])
.range([0, w]);
// Scales and Axis
const xAxis = axisBottom(xScale);
// Line function
const linex = line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]));
// Update
useEffect(() => {
createChart(durationTime);
}, [n, props.width]);
const createChart = () => {
const node = vizRef.current;
const gOuter = select(node).attr(
"transform",
"translate(" + margin.left + "," + margin.top + ")"
);
// x Axis
gOuter
.selectAll("g.xAxis")
.data([0])
.enter()
.append("g")
.attr("class", "xAxis");
select(node)
.select("g.xAxis")
.attr("transform", "translate(" + 0 + "," + h + ")")
.call(xAxis);
// x label
gOuter
.selectAll("#x-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("class", "x-label");
select(node)
.selectAll(".x-label")
.attr(
"transform",
"translate(" + w / 2 + " ," + (h + margin.bottom) + ")"
)
.text("μ");
// y label
gOuter
.selectAll("#y-label")
.data([0])
.enter()
.append("text")
.style("text-anchor", "middle")
.attr("id", "y-label");
select(node)
.selectAll("#y-label")
.attr("transform", "rotate(-90)")
.attr("text-anchor", "middle")
.attr("x", -(h / 2))
.attr("y", -40)
.text("Log-Likelihood");
};
const delta = xMax - xMin;
return (
<svg width={props.width} height={props.width * 0.5}>
<g id="outer" ref={vizRef}>
<g className="viz" clipPath="url(#clip)">
<path d={linex(data1.data)} id="logLikReferenceCurve" />
<path d={linex(data2.data)} id="logLikNCurve" />
<line
className={clsx("LRT", test == "LRT" && "highlight")}
x1={xScale(xMin)}
x2={xScale(xMax)}
y1={yScale(llThetaMLE)}
y2={yScale(llThetaMLE)}
/>
<line
className={clsx("LRT", test == "LRT" && "highlight")}
x1={xScale(xMin)}
x2={xScale(xMax)}
y1={yScale(llThetaNull)}
y2={yScale(llThetaNull)}
/>
<line
className={clsx("wald", test == "wald" && "highlight")}
x1={xScale(props.muHat)}
x2={xScale(props.muHat)}
y1={yScale(yMin)}
y2={yScale(yMax)}
/>
<circle
cx={xScale(muNull)}
cy={yScale(llThetaNull)}
r="5"
fill="red"
className="testPointMuNull"
/>
<circle
cx={xScale(props.muHat)}
cy={yScale(llTheta)}
r="5"
className="testPointMu"
/>
</g>
<line
className={clsx("wald", test == "wald" && "highlight")}
x1={xScale(props.muNull)}
x2={xScale(props.muNull)}
y1={yScale(yMin)}
y2={yScale(yMax)}
/>
<line
className={clsx("score", test == "score" && "highlight")}
x1={xScale(props.muNull - delta)}
x2={xScale(props.muNull + delta)}
y1={yScale(llThetaNull - delta * deriv)}
y2={yScale(llThetaNull + delta * deriv)}
/>
</g>
<defs>
<clipPath id="clip">
<rect id="clip-rect" x="0" y="-10" width={w} height={h + 10} />
</clipPath>
</defs>
</svg>
);
}