drag = {
function dragstarted(event, d) {
d.originalP1 = d.point1;
d.originalP2 = d.point2;
if (d.drawOriginLine && !d.hasOwnProperty('isAwayFromOrigin')) {
svg.selectAll(`line.ghost${d.label}`).remove();
svg.append('line')
.classed(`ghost${d.label}`, true)
.attr('x1', xScale(d.originalP1[0]))
.attr('y1', yScale(d.originalP1[1]))
.attr('x2', xScale(d.originalP2[0]))
.attr('y2', yScale(d.originalP2[1]))
.attr('stroke-width', d.width)
.attr('stroke', getColor(d))
.attr('filter', 'brightness(2)')
svg.selectAll(`text.ghost${d.label}`).remove();
svg.append('text')
.classed(`ghost${d.label}`, true)
.attr('x', xScale(d.originalP2[0]))
.attr('y', yScale(d.originalP2[1]))
.style('fill', getColor(d))
.style("font-size", d.labelSize)
.style("font-weight", 'bold')
.style('text-shadow', textShadowDark)
.attr('filter', 'brightness(2)')
.text(() => `Old ${d.label}`);
d.isAwayFromOrigin = true;
}
else if (d.drawOriginLine && !d.isAwayFromOrigin) {
svg.select(`line.ghost${d.label}`)
.attr('opacity', '1')
d3.select(`text.ghost${d.label}`)
.attr('opacity', '1')
d.isAwayFromOrigin = true;
}
if (d.moveX || d.moveY) {
d3.select(this).raise();
d3.select(this).attr("stroke-width", d.width*1.5).attr("filter", "drop-shadow(0 0 .5rem yellow)");
}
appendIntersectionObjects();
}
function dragged(event, d) {
svg.selectAll("line.vDrop").remove();
svg.selectAll("line.hDrop").remove();
appendLabels();
var dx=event.dx;
var dy=event.dy;
if (d.moveX) {
d.point1[0] = xScale.invert(xScale(d.point1[0])+dx);
d.point2[0] = xScale.invert(xScale(d.point2[0])+dx);
}
if (d.moveY) {
d.point1[1] = yScale.invert(yScale(d.point1[1])+dy);
d.point2[1] = yScale.invert(yScale(d.point2[1])+dy);
}
d.x1 = xScale(d.point1[0]);
d.y1 = yScale(d.point1[1]);
d.x2 = xScale(d.point2[0]);
d.y2 = yScale(d.point2[1]);
d.il = false;
d.ib = false;
d.it = false;
d.ir = false;
// handle line crossing interaction boundaries
if (intersectLines(d, yAxisLine)) {
// console.log("intersecting Y at", intersectLines(d, yAxisLine));
d.il = true;
if (xScale(d.point1[0]) < xScale(interactionBoundary.xMin)) {
d.x1 = xScale(interactionBoundary.xMin);
d.y1 = yScale(intersectLines(d, yAxisLine).y);
}
else if (xScale(d.point2[0]) < xScale(interactionBoundary.xMin)) {
d.x2 = xScale(interactionBoundary.xMin);
d.y2 = yScale(intersectLines(d, yAxisLine).y);
}
}
if(intersectLines(d, xAxisLine)) {
// console.log("intersecting X at", intersectLines(d, xAxisLine));
// remember that yScale is inverted, so this is checking for being less than min.
d.ib = true;
if (yScale(d.point1[1]) > yScale(interactionBoundary.yMin)) {
d.x1 = xScale(intersectLines(d, xAxisLine).x);
d.y1 = yScale(interactionBoundary.yMin);
}
else if (yScale(d.point2[1]) > yScale(interactionBoundary.yMin)) {
d.x2 = xScale(intersectLines(d, xAxisLine).x);
d.y2 = yScale(interactionBoundary.yMin);
}
}
if(intersectLines(d, topLine)) {
d.it = true;
if (yScale(d.point1[1]) < yScale(interactionBoundary.yMax)) {
d.x1 = xScale(intersectLines(d, topLine).x);
d.y1 = yScale(interactionBoundary.yMax);
}
else if (yScale(d.point2[1]) < yScale(interactionBoundary.yMax)) {
d.x2 = xScale(intersectLines(d, topLine).x);
d.y2 = yScale(interactionBoundary.yMax);
}
}
if (intersectLines(d, rightLine)) {
d.ir = true;
if (xScale(d.point1[0]) > xScale(xAxisScale.domain[1])) {
d.x1 = xScale(rightLine.point1[0]);
d.y1 = yScale(intersectLines(d, rightLine).y);
}
else if (xScale(d.point2[0]) > xScale(0)) {
d.x2 = xScale(rightLine.point1[0]);
d.y2 = yScale(intersectLines(d, rightLine).y);
}
}
// if the edit would make the line too short, bounce it.
if (distance(xyScale(d.point1), xyScale(d.point2)) * LINE_MIN_LENGTH > distance([d.x1, d.y1], [d.x2, d.y2])) {
console.log("too short")
if (d.il) {
d.point1[0] += (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
d.point2[0] += (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
}
if (d.ib) {
d.point1[1] += (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
d.point2[1] += (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
}
if (d.it) {
d.point1[1] -= (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
d.point2[1] -= (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
}
if (d.ir) {
d.point1[0] -= (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
d.point2[0] -= (xAxisScale.domain[1] - xAxisScale.domain[0]) / 100;
}
}
else {
d3.select(this)
.attr('x1', d.x1)
.attr('y1', d.y1)
.attr('x2', d.x2)
.attr('y2', d.y2)
}
svg.selectAll("text.label")
.data(lines)
.enter().append('text')
.classed('label', true)
.style("font-size", d => d.labelSize)
.style("font-family", 'Helvetica Neue, sans-serif')
.style('fill', d => getColor(d))
.style("font-weight", 'bold')
.style('text-shadow', textShadow)
.attr("x", d => {
return ('x2' in d) ? d.x2 : d.point2[0]
})
.attr("y", d => {
return ('y2' in d) ? d.y2 : d.point2[1]
})
.text(d => d.label);
appendIntersectionObjects();
}
function dragended(event, d) {
// if (d.drawOriginLine) {
// const ghostLineX1 = d3.select(`line.ghost${d.label}`).attr("x1")
// const draggedLineX1 = xScale(d.point1[0])
// const ghostLineY1 = d3.select(`line.ghost${d.label}`).attr("y1")
// const draggedLineY1 = d.y1
// if (
// (ghostLineX1 < draggedLineX1 + GHOST_MIN_DISTANCE && ghostLineX1 > draggedLineX1 - GHOST_MIN_DISTANCE) &&
// (ghostLineY1 < draggedLineY1 + GHOST_MIN_DISTANCE && ghostLineY1 > draggedLineY1 - GHOST_MIN_DISTANCE))
// {
// d3.select(`line.ghost${d.label}`)
// .attr('opacity', '0')
// d3.select(`text.ghost${d.label}`)
// .attr('opacity', '0')
// d.isAwayFromOrigin = false;
// }
// }
console.log(this)
d3.select(this)
.attr("cursor", getCursor(d))
.transition().duration(200).attr("stroke-width", d.width).attr("filter", "drop-shadow(0)")
}
return d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended);
}