Skip to content

Instantly share code, notes, and snippets.

@nlevick
Last active March 30, 2017 19:11
Show Gist options
  • Save nlevick/59a222b2b356201a47eb8c2a8b40628f to your computer and use it in GitHub Desktop.
Save nlevick/59a222b2b356201a47eb8c2a8b40628f to your computer and use it in GitHub Desktop.
Dot Drag and Delete Interactivity

DESCRIPTION

Click top row swatch to select a color. Click white canvas to add dots of that color. Click color swatch again to deselect color. With no color swatch seclected, in canvase click and drag placed dots to move. Double click to remove.

<!DOCTYPE html>
<div id="addIcons"></div>
<svg width="960" height="470"></svg>
<style>
text {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
pointer-events: none;
}
.ocean {
fill: white;
}
.hiIcon{
stroke: white;
stroke-width: 2px;
}
</style>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
svg.append('rect')
.attr('class', 'ocean')
.attr('width', width)
.attr('height', height);
var iconPanelHeight = 500 - height,
iconPanelWidth = width,
iconPanel = d3.select('#addIcons')
.append('svg')
.attr('id', 'iconPanel')
.style('background-color', 'black')
.attr('height', iconPanelHeight)
.attr('width', iconPanelWidth);
var color = d3.scale.category10(),
radius = 10,
cloneID = Array.apply(null, Array(10)).map(Number.prototype.valueOf,0),
sourceToggle = 0;
var drag = d3.behavior.drag()
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
var icon = iconPanel.selectAll('icons')
.data(d3.range(10))
.enter().append('circle')
.attr("fill", color )
.attr('id', function(d){ return 'icon_' + d; })
.attr('class', 'Icon')
.attr("cx", d3.scale.linear().domain([-1, 10]).range([0, 400]) )
.attr('cy',iconPanelHeight*.5)
.attr('r', radius)
.attr('stroke-width', 1)
.attr('cursor', 'pointer')
.on('click', function(d){ modeToggle(d); });
function modeToggle(e){
if (sourceToggle == 0){
d3.select('#icon_' + e).classed('hiIcon', true)
sourceToggle = 1;
svg.attr('cursor', 'crosshair')
.on('click', function(){addClone(e)})
} else {
d3.select('.hiIcon').classed('hiIcon', false)
sourceToggle = 0;
svg.on('click', null)
.attr('cursor', 'default');
d3.selectAll('.clone')
.attr('cursor', 'move')
.call(drag);
}
}
function addClone(e){
var clone = svg.append('circle')
.attr('class', 'clone')
.attr('id', 'clone' + e + '.' + cloneID[e])
.attr('r', radius)
.attr("fill", color(e) )
.attr('cx', d3.event.x)
.attr('cy', d3.event.y)
.on('dblclick', removeCircle);
cloneID[e]++;
}
function removeCircle(){
d3.select(this)
.transition()
.duration(300)
.attr('r', 0)
.each('end', function(){ d3.select(this).remove() });
var clones = d3.selectAll('.clone')[0]
clones.length === 0 ? cloneID = 0 : null;
}
function dragstarted() {
d3.select(this).transition()
.ease("elastic")
.duration(500)
.attr("r", 15);
}
function dragged(d) {
d3.select(this)
.attr("cx", Math.max(15, Math.min(width - 15, d3.event.x)))
.attr("cy", Math.max(15, Math.min(height - 15, d3.event.y)));
}
function dragended() {
d3.select(this).transition()
.ease("elastic")
.duration(500)
.attr("r", radius);
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment