JSFiddle - React, Tailwind, and code Playground
by Serhii Matrunchyk
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Drawing</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.1.1/d3.min.js" integrity="sha512-COTaPOlz12cG4fSfcBsxZsjauBAyldqp+8FQUM/dZHm+ts/jR4AFoJhCqxy8K10Jrf3pojfsbq7fAPTb1XaVkg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
<h3>Draw a polygon :D</h3>
CSS
svg {
border: 1px solid;
}
path {
fill: lightsalmon;
stroke: salmon;
stroke-width: 5px;
}
circle.handler {
fill: transparent;
}
svg:not(.is-drawing) circle.handler:hover {
fill: #f2cb63;
cursor: move;
}
circle.indicator {
pointer-events: none;
fill: #0254ff;
}
circle.indicator.initial-vertex:hover {
fill: red;
}
line.edge {
pointer-events: none;
}
polygon:hover {
opacity: 0.8;
stroke: black;
stroke-width: 1.2px;
cursor: move;
}
polyline {
pointer-events: none;
}
JavaScript
let dragging = false;
let drawing = false;
let snapping = false;
let startPoint = [];
/* const rect = document.body;
rect.height -= 15;
const margin = { top: 25, right: 0, bottom: 55, left: 65 };
const width = rect.width - margin.left - margin.right;
const height = rect.height - margin.top - margin.bottom; */
const svg = d3.select('body').append('svg')
.attr('height', 1000)
.attr('width', 1000);
let points = [];
let group = null;
let idx = 0;
const dragger = d3.drag()
.on('drag', handleDrag)
.on('end', function(d) {
dragging = false;
});
document.body.addEventListener('keydown', function(event) {
if (!group) return;
d3.select(group).node().remove();
group = null;
points = [];
drawing = false;
dragging = false;
});
svg.on('mouseup', function(event) {
console.log('asdasd');
if (dragging) return;
if (!group) {
group = svg.append('g')
.attr('class', 'polygon-group')
.attr('polygon-index', idx++);
}
drawing = true;
startPoint = [event.x - 10, event.y - 60];
svg.classed('is-drawing', drawing);
const initialNode = group.select('.initial-vertex');
if (d3.select(event.target).classed('initial-vertex')) {
// Close polygon
group.append('polygon')
.attr('points', points)
.style('fill', '#d9d9d9')
.lower();
group.selectAll('polyline').remove();
group.selectAll('line').remove();
drawing = false;
points = [];
group = null;
svg.classed('is-drawing', drawing);
return;
}
points.push(startPoint);
group.select('polyline').remove();
const polyline = group
.append('polyline')
.attr('points', points)
.style('fill', 'none')
.attr('stroke', '#000');
group.selectAll('circle.indicator')
.data(points)
.enter()
.append('circle')
.attr('class', 'indicator')
.attr('cx', d => d[0])
.attr('cy', d => d[1])
.attr('r', 4)
.attr('stroke', '#000')
.classed('initial-vertex', (d, index) =>...