Skip to content

Instantly share code, notes, and snippets.

@1wheel
Last active August 22, 2016 02:33
Show Gist options
  • Save 1wheel/dabdb5bd3eabf8e2da752fee31bbec14 to your computer and use it in GitHub Desktop.
Save 1wheel/dabdb5bd3eabf8e2da752fee31bbec14 to your computer and use it in GitHub Desktop.
circle-arc-drag
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body{
background: black;
}
circle{
fill: green;
fill-opacity: .3;
stroke: white;
stroke-width: 5;
cursor: pointer;
}
path{
fill: none;
stroke: green;
stroke-width: 3;
}
</style>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src='script.js'></script>
function translate(sel, pos){
sel.attr('transform', function(d){
var posStr = typeof(pos) == 'function' ? pos(d) : pos
return 'translate(' + posStr + ')'
})
}
function ƒ(str){ return function(d){ return str ? d[str] : d } }
d3.selection.prototype.appendMany = function(data, name){
return this.selectAll(name).data(data).enter().append(name)
}
var width = 960,
height = 500;
var svg = d3.select('html')
.append('svg')
.attr('width', width)
.attr('height', height)
var g = svg.append('g')
var path = svg.append('path')
var circles = [
[100, 300],
[400, 100],
[800, 200],
]
var drag = d3.behavior.drag()
.on('dragstart', function(d){})
.on('drag', function(d){
d[0] = d3.event.x
d[1] = d3.event.y
d3.select(this).call(translate, ƒ())
calcPath()
})
.origin(function(d){ return {x: d[0], y: d[1]} })
var circleSel = svg.appendMany(circles, 'circle')
.attr('r', 10)
.call(translate, ƒ())
.call(drag)
function calcPath(){
var a = circles[0]
var b = circles[2]
var c = circles[1]
var A = dist(b, c)
var B = dist(c, a)
var C = dist(a, b)
var angle = Math.acos((A*A + B*B - C*C)/(2*A*B))
//calc radius of circle
var K = .5*A*B*Math.sin(angle)
var r = A*B*C/4/K
//large arc flag
var laf = +(Math.PI/2 > angle)
//sweep flag
var saf = +((b[0] - a[0])*(c[1] - a[1]) - (b[1] - a[1])*(c[0] - a[0]) < 0)
path.attr('d', ['M', a, 'A', r, r, 0, laf, saf, b].join(' '))
}
function parsePath(str){
var path = svg.append('path').attr('d', str)
var l = path.node().getTotalLength()
circles = [0, .5, 1].map(function(d){
var p = path.node().getPointAtLength(d*l)
console.log(d, p)
return [p.x, p.y]
})
circleSel.data(circles).call(translate, ƒ())
calcPath()
}
parsePath('M 622,449 A 263 263 0 1 0 146,382')
function slope(a, b){
return (a[1] - b[1])/(a[0] + b[0])
}
function mid(a, b){
return [(a[0] + b[0])/2, (a[1] + b[1])/2]
}
function dist(a, b){
return Math.sqrt(
Math.pow(a[0] - b[0], 2) +
Math.pow(a[1] - b[1], 2))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment