mirror of
https://github.com/FoggedLens/iD.git
synced 2026-02-13 17:23:02 +00:00
146 lines
4.3 KiB
JavaScript
146 lines
4.3 KiB
JavaScript
import * as d3 from 'd3';
|
|
import { geoRoundCoords } from '../geo/index';
|
|
import { uiTooltipHtml } from './tooltipHtml';
|
|
|
|
|
|
export function uiRadialMenu(context, operations) {
|
|
var menu,
|
|
center = [0, 0],
|
|
tooltip;
|
|
|
|
|
|
var radialMenu = function(selection) {
|
|
if (!operations.length) return;
|
|
|
|
selection.node().parentNode.focus();
|
|
|
|
function click(operation) {
|
|
d3.event.stopPropagation();
|
|
if (operation.disabled()) return;
|
|
operation();
|
|
radialMenu.close();
|
|
}
|
|
|
|
menu = selection
|
|
.append('g')
|
|
.attr('class', 'radial-menu')
|
|
.attr('transform', 'translate(' + center + ')')
|
|
.attr('opacity', 0);
|
|
|
|
menu
|
|
.transition()
|
|
.attr('opacity', 1);
|
|
|
|
var r = 50,
|
|
a = Math.PI / 4,
|
|
a0 = -Math.PI / 4,
|
|
a1 = a0 + (operations.length - 1) * a;
|
|
|
|
menu
|
|
.append('path')
|
|
.attr('class', 'radial-menu-background')
|
|
.attr('d', 'M' + r * Math.sin(a0) + ',' +
|
|
r * Math.cos(a0) +
|
|
' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
|
|
(r * Math.sin(a1) + 1e-3) + ',' +
|
|
(r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
|
|
.attr('stroke-width', 50)
|
|
.attr('stroke-linecap', 'round');
|
|
|
|
var button = menu.selectAll()
|
|
.data(operations)
|
|
.enter()
|
|
.append('g')
|
|
.attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
|
|
.classed('disabled', function(d) { return d.disabled(); })
|
|
.attr('transform', function(d, i) {
|
|
return 'translate(' + geoRoundCoords([
|
|
r * Math.sin(a0 + i * a),
|
|
r * Math.cos(a0 + i * a)]).join(',') + ')';
|
|
});
|
|
|
|
button
|
|
.append('circle')
|
|
.attr('r', 15)
|
|
.on('click', click)
|
|
.on('mousedown', mousedown)
|
|
.on('mouseover', mouseover)
|
|
.on('mouseout', mouseout);
|
|
|
|
button
|
|
.append('use')
|
|
.attr('transform', 'translate(-10,-10)')
|
|
.attr('width', '20')
|
|
.attr('height', '20')
|
|
.attr('xlink:href', function(d) { return '#operation-' + d.id; });
|
|
|
|
tooltip = d3.select(document.body)
|
|
.append('div')
|
|
.attr('class', 'tooltip-inner radial-menu-tooltip');
|
|
|
|
function mousedown() {
|
|
d3.event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
|
|
}
|
|
|
|
function mouseover(d, i) {
|
|
var rect = context.surfaceRect(),
|
|
angle = a0 + i * a,
|
|
top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
|
|
left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
|
|
bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
|
|
right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
|
|
|
|
tooltip
|
|
.style('top', null)
|
|
.style('left', null)
|
|
.style('bottom', null)
|
|
.style('right', null)
|
|
.style('display', 'block')
|
|
.html(uiTooltipHtml(d.tooltip(), d.keys[0]));
|
|
|
|
if (i === 0) {
|
|
tooltip
|
|
.style('right', right)
|
|
.style('top', top);
|
|
} else if (i >= 4) {
|
|
tooltip
|
|
.style('left', left)
|
|
.style('bottom', bottom);
|
|
} else {
|
|
tooltip
|
|
.style('left', left)
|
|
.style('top', top);
|
|
}
|
|
}
|
|
|
|
function mouseout() {
|
|
tooltip.style('display', 'none');
|
|
}
|
|
};
|
|
|
|
|
|
radialMenu.close = function() {
|
|
if (menu) {
|
|
menu
|
|
.style('pointer-events', 'none')
|
|
.transition()
|
|
.attr('opacity', 0)
|
|
.remove();
|
|
}
|
|
|
|
if (tooltip) {
|
|
tooltip.remove();
|
|
}
|
|
};
|
|
|
|
|
|
radialMenu.center = function(_) {
|
|
if (!arguments.length) return center;
|
|
center = _;
|
|
return radialMenu;
|
|
};
|
|
|
|
|
|
return radialMenu;
|
|
}
|