Skip to content

Instantly share code, notes, and snippets.

@mforando
Last active October 18, 2017 00:05
Show Gist options
  • Save mforando/23ba947c8c761a3cb62ee79318131131 to your computer and use it in GitHub Desktop.
Save mforando/23ba947c8c761a3cb62ee79318131131 to your computer and use it in GitHub Desktop.
Brady Bezier Curves w.Fill
license: mit
<!doctype html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<style>
body {
font-family: Franklin Gothic Book;
font-size: 1.5em;
}
h1 {
font-family: Franklin Gothic Medium;
font-size: 42px;
margin:10px;
color:black;
}
h2.subtitle {
font-family: Franklin Gothic Book;
font-size: .8em;
padding: 0px;
opacity:.7
color: #666;
color:black;
}
.domain {
stroke: rgb(210,210,210);
}
.curve, .line {
stroke: black;
fill: none;
stroke-width: 1px;
stroke-opacity: .6;
}
.curve {
stroke: red;
stroke-width: 3px;
}
.control {
fill: #ccc;
stroke: #000;
stroke-width: .5px;
cursor: move;
z-index:10;
r:7;)
}
.control.drag, .control:hover {
fill: rgb(0,50,100);
}
.t, .controltext {
font-size: .6em;
}
svg {
display: inline-block;
}
.curve {
stroke-width: 2px;
stroke: red;
stroke-opacity:.8;
}
.t {
font-size: 64px;
}
</style>
<body>
<div id="container">
<svg id="vis-canvas" width="800" height="500" xmlns="http://www.w3.org/2000/svg">
<g stroke="null" id="bradySVG" transform="translate(105,307)">
<path stroke="#000000" id="svg_2" d="m24.074259,133.186095l4.747152,-19.225967c0,0 -2.136219,-10.91845 7.832801,-20.175398l4.03508,-14.478815c0,0 -5.221868,-15.665603 -4.98451,-23.498404c0,0 2.373576,-2.136219 -0.712073,-4.98451l-9.01959,-8.070159l2.610934,-4.03508c0,0 -12.579954,-6.408656 -17.801821,-13.054669c0,0 -3.204328,0.356036 -4.272437,-2.729613c0,0 -4.509795,-2.136219 -2.492255,-4.865831c0,0 -0.94943,-13.410705 13.292027,-17.801821c0,0 10.443735,5.103189 1.661503,20.294076c0,0 13.766742,3.797722 19.700682,12.342596c0,0 9.01959,0.356036 11.867881,2.254897c0,0 -2.729613,-18.513894 15.072209,-18.276537c0,0 12.223917,0.593394 10.91845,12.93599c0,0 1.068109,-0.118679 1.780182,0.593394l-1.898861,7.239407l0.94943,0.356036l-1.186788,2.96697l-0.94943,-0.356036l-1.186788,4.391116c0,0 -9.612984,0.356036 -6.527335,4.03508c0,0 10.443735,6.171298 10.799772,5.103189c0,0 -0.474715,-3.679043 6.052619,2.254897l2.254897,-1.305467l0,-1.898861c0,0 -2.373576,-8.307517 0,-8.188838c0,0 -0.118679,-1.780182 2.848291,8.070159c0,0 2.136219,-6.527335 4.03508,-8.544874c0,0 0.94943,0.118679 -1.068109,9.01959c0,0 2.729613,-5.340546 3.916401,-4.747152c0,0 -3.560364,9.850341 -2.729613,8.426195c0,0 -2.01754,2.254897 2.729613,0c0,0 0.712073,1.780182 -3.560364,4.865831c0,0 3.441685,35.603643 -4.391116,32.636673c0,0 -9.96902,2.254897 -12.461275,-10.681093l-1.661503,2.136219c0,0 -0.367904,14.426121 -4.509795,16.258997c0,0 7.120729,8.307517 6.171298,10.206378c0,0 0.830752,3.679043 -4.747152,2.96697l7.832801,13.766742c0,0 1.542825,3.797722 0,3.797722l-25.753302,0l-4.628474,-6.171298l-2.254897,6.171298l-22.311616,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="null" id="svg_3" d="m86.261955,68.86218c0,0 -0.712073,5.577904 2.96697,5.696583s4.339372,-4.64319 4.339372,-4.64319l0.091145,13.059416c0,0 -9.830641,4.298546 -14.577793,-1.506509l7.180305,-12.606301z" fill="#EF382B"/>
<polygon stroke="null" id="svg_4" points="24.637264251708984,115.93066400289536 38.76765441894531,121.96688836812973 42.06025695800781,109.89443963766098 48.370880126953125,98.09631341695786 51.25171661376953,95.76406854391098 42.33442687988281,91.6484984755516 34.926246643066406,99.05651849508286 " fill="#0D244D"/>
<path stroke="null" id="svg_5" d="m44.012299,48.805461l2.01754,5.577904c0,0 7.595444,-14.95353 6.527335,-18.157858c0,0 -0.929492,-2.271512 -7.407457,-2.915938l-1.137418,15.495892z" fill="#0D244D"/>
<polygon stroke="null" id="svg_6" points="83.65100860595703,58.452392518520355 81.15877532958984,65.30180352926254 81.15877532958984,66.72596734762192 85.66856384277344,63.16557306051254 " fill="#FFFFFF"/>
<g stroke="null" id="svg_7">
<polygon stroke="null" id="svg_8" points="57.395957946777344,53.55451959371567 57.395957946777344,50.051574647426605 66.20118713378906,52.82487481832504 62.707061767578125,76.32402032613754 65.36238861083984,77.49180597066879 65.22234344482422,80.99424737691879 53.343284606933594,77.63703912496567 54.88018798828125,73.69670099020004 57.395957946777344,74.28056329488754 60.99999237060547,54.625915467739105 " fill="#EF382B"/>
<polygon stroke="null" id="svg_9" points="74.72636413574219,65.52299493551254 70.53367614746094,62.74955743551254 70.53367614746094,58.51695245504379 73.75936889648438,57.53689569234848 75.5305404663086,59.95913690328598 81.15498352050781,63.91731256246567 79.75763702392578,73.57090753316879 78.91929626464844,77.92900079488754 75.84407043457031,77.19911187887192 73.46790313720703,72.67533868551254 71.65187072753906,77.19911187887192 71.23221588134766,82.30802911520004 73.18877410888672,84.35093683004379 74.37698364257812,79.97547906637192 76.82296752929688,82.30802911520004 75.70476531982422,85.22677606344223 73.88731384277344,89.60559076070786 67.59805297851562,82.74525445699692 68.99608612060547,69.17146295309067 73.32878875732422,67.71241754293442 75.98389434814453,71.50730890035629 78.22026824951172,64.64741510152817 75.22055053710938,62.25456231832504 " fill="#EF382B"/>
</g>
<g stroke="null" id="svg_10">
<polygon stroke="null" id="svg_11" points="58.224327087402344,54.48019403219223 58.224327087402344,51.23835748434067 66.7350082397461,53.804931581020355 63.357643127441406,75.55375665426254 65.92443084716797,76.63468927145004 65.78890991210938,79.87651056051254 54.306976318359375,76.76972955465317 55.79283142089844,73.12251275777817 58.224327087402344,73.66249078512192 61.707794189453125,55.47212213277817 " fill="#FFFFFF"/>
<polygon stroke="null" id="svg_12" points="74.9748764038086,65.55772393941879 70.92247009277344,62.99043267965317 70.92247009277344,59.073303163051605 74.0404052734375,58.16635125875473 75.7524642944336,60.40773004293442 81.18892669677734,64.07136529684067 79.83834838867188,73.00621026754379 79.02801513671875,77.03965753316879 76.05558776855469,76.36433404684067 73.75912475585938,72.17662042379379 72.00340270996094,76.36433404684067 71.59777069091797,81.09223932027817 73.48904418945312,82.98350518941879 74.63761138916016,78.93376153707504 77.0014419555664,81.09223932027817 75.9207763671875,83.79414361715317 74.16432189941406,87.84680169820786 68.0853500366211,81.49723809957504 69.43663787841797,68.93458551168442 73.6245346069336,67.58403009176254 76.19086456298828,71.09617608785629 78.35199737548828,64.74711602926254 75.45269012451172,62.53254693746567 " fill="#FFFFFF"/>
</g>
<g stroke="null" id="svg_13">
<polygon stroke="null" id="svg_14" points="59.427490234375,55.62875360250473 59.427490234375,52.68222039937973 67.30492401123047,55.01473993062973 64.17892456054688,74.77998346090317 66.55462646484375,75.76216119527817 66.4297866821289,78.70869439840317 55.80113983154297,75.88487237691879 57.17662048339844,72.57041925191879 59.427490234375,73.06129449605942 62.651519775390625,56.52980035543442 " fill="#0D244D"/>
<polygon stroke="null" id="svg_15" points="74.93240356445312,65.69535821676254 71.18097686767578,63.36283868551254 71.18097686767578,59.80274957418442 74.0669937133789,58.97834771871567 75.65206146240234,61.01539605855942 80.68403625488281,64.34480279684067 79.43388366699219,72.46528619527817 78.6836166381836,76.13053888082504 75.93262481689453,75.51676934957504 73.80709838867188,71.71073907613754 72.1814193725586,75.51676934957504 71.80640411376953,79.81336969137192 73.55692291259766,81.53208917379379 74.61955261230469,77.85212701559067 76.80776977539062,79.81336969137192 75.8075180053711,82.26881402730942 74.1821060180664,85.9519652724266 68.55529022216797,80.18177789449692 69.80570983886719,68.76441949605942 73.6817626953125,67.53703302145004 76.0577163696289,70.72874444723129 78.05840301513672,64.95857232809067 75.37437438964844,62.94648736715317 " fill="#0D244D"/>
</g>
<path stroke="null" id="svg_16" d="m17.505624,-1c0,0 -9.725966,1.477314 -12.023825,12.147251c0,0 -0.492517,4.596193 4.924459,5.252724c0,0 2.790614,2.954628 2.462348,3.447145c0,0 3.52927,2.379985 6.360709,0.205077c0,0 10.13612,-11.531783 -1.723691,-21.052197z" fill="#682D2D"/>
<path stroke="null" id="svg_18" d="m78.675293,27.414081c0,0 -11.788604,-4.865831 -18.118457,-2.650573l-1.265591,2.650573l-2.215496,0l0,2.729613c0,0 14.95353,8.070159 20.294076,8.070159c0,0 6.266953,-9.109785 1.305467,-10.799772z" fill="#EF382B"/>
<path stroke="null" id="svg_19" d="m63.890762,24.981165l-1.582226,0l0,1.582463l1.582226,3.164689l13.925297,5.221868l1.265591,-6.487696c0,0 -6.012743,-3.481324 -15.190888,-3.481324z" fill="#FFFFFF"/>
<path stroke="null" id="svg_20" d="m37.75935,89.819196c0,0 29.955718,13.195659 32.006251,12.628849c0,0 3.883171,-3.784667 4.509795,-16.258997l1.661503,-2.136219c0,0 0.488482,12.163866 13.572583,10.842496c0,0 3.736009,0.21291 3.902159,-11.710038c0,0 0.09613,-21.074746 -0.622352,-21.0878c0,0 5.069721,-3.863945 3.560364,-4.865831c0,0 -3.870591,1.872277 -2.729613,0l2.729613,-8.426195c0,0 -1.259657,-0.224303 -3.916401,4.747152c0,0 1.707313,-8.848455 1.068109,-9.01959c0,0 -3.949868,6.817148 -4.03508,8.544874c0,0 -2.369778,-8.192873 -2.848291,-8.070159c0,0 -2.218819,-0.361733 -0.084025,7.882647l0.084025,2.205052l-2.254897,1.305467c0,0 -3.935152,-4.045523 -5.713435,-3.243967c0,0 -0.728451,0.646087 -0.339184,0.989069c0,0 -2.209087,-0.263942 -10.799772,-5.103189c0,0 -2.139304,-2.590046 3.140241,-3.635369c0,0 -14.850992,-5.951742 -17.998591,-8.403884c0,0 -4.401085,14.029734 -6.622515,17.617157l-2.01754,-5.577904l1.137418,-15.495892c0,0 -5.60164,-0.948244 -6.477964,-0.644426l-10.087699,5.815262l-2.610934,4.03508c0,0 13.337599,10.337636 9.731662,13.054669c0,0 -0.191785,16.904372 4.98451,23.498404l-2.929942,10.513281z" fill="none"/>
<path stroke="#000000" id="svg_21" d="m75.936898,84.053068c1.588635,2.267952 10.325056,-15.190888 10.325056,-15.190888c2.149748,-8.246041 -7.95148,-14.716172 -7.95148,-14.716172" stroke-miterlimit="10" fill="none"/>
<polygon stroke="#000000" id="svg_22" points="38.67176818847656,32.66513055562973 44.012298583984375,48.80549615621567 45.14972686767578,33.309570252895355 " stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#FFFFFF" id="svg_23" d="m38.671752,32.902501l-10.087699,5.815262l-2.610934,4.03508c0,0 13.021439,10.654509 9.731662,13.054669c0,0 -0.982661,12.473855 4.98451,23.498404l-2.929942,10.513518l4.968844,2.163752l3.301644,-37.362463l-7.358086,-21.718222z" stroke-miterlimit="10" fill="#0D244D"/>
<path stroke="null" id="svg_24" d="m79.082124,81.467531c0,0 1.835724,2.590758 5.672847,2.946083l-0.232373,10.271651c0,0 -6.718407,-0.678843 -8.545349,-10.429019l3.104875,-2.788715z" fill="#0D244D"/>
<path stroke="#FFFFFF" id="svg_25" d="m37.996707,89.581839c0,0 30.715737,14.538629 32.006251,12.628849c0,0 8.392965,9.270002 6.171298,10.206378c0,0 0.322806,3.573419 -4.747152,2.96697c0,0 12.03237,17.564464 7.832801,17.564464l-25.753302,0l-4.628474,-6.171298l-2.254897,6.171298l-22.311616,0l3.907856,-15.826531l-3.344844,-1.428893l4.099641,-6.723392c0,0 0.605025,-9.119754 7.917301,-15.422786l1.105137,-3.965059z" stroke-miterlimit="10" fill="#0D244D"/>
<path stroke="#FFFFFF" id="svg_26" d="m71.427104,115.621631c0,0 -16.225767,-5.195521 -17.649913,-6.303032l-2.525485,-13.701469c0,0 18.397589,7.58049 18.751252,6.830915c0,0.000237 13.69411,13.779797 1.424146,13.173585z" stroke-miterlimit="10" fill="#0D244D"/>
<path stroke="null" id="svg_27" d="m42.520506,91.648512l3.271975,-37.027789c0,0 8.188126,-17.142442 6.622515,-17.617157c0,0 1.757396,1.450492 -6.233486,17.617157l-3.359322,37.362463l-0.301682,-0.334674z" fill="#EF382B"/>
<path stroke="#000000" id="svg_28" d="m47.527328,117.623743c-0.138617,0.426532 -0.596717,0.659617 -1.023011,0.521l-13.695772,-4.454016c-0.426294,-0.138617 -0.659379,-0.596717 -0.520763,-1.022774l0,0c0.138617,-0.426294 0.59648,-0.659379 1.022774,-0.520763l13.696009,4.454016c0.426057,0.138379 0.659142,0.59648 0.520763,1.022537l0,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#000000" id="svg_29" d="m47.527328,120.662632c-0.138617,0.426532 -0.596717,0.659617 -1.023011,0.521l-13.695772,-4.454016c-0.426294,-0.138617 -0.659379,-0.596717 -0.520763,-1.022774l0,0c0.138617,-0.426294 0.59648,-0.659379 1.022774,-0.520763l13.696009,4.454016c0.426057,0.138379 0.659142,0.59648 0.520763,1.022537l0,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#000000" id="svg_30" d="m47.527328,123.701522c-0.138617,0.426532 -0.596717,0.659617 -1.023011,0.521l-13.695772,-4.454016c-0.426294,-0.138617 -0.659379,-0.596717 -0.520763,-1.022774l0,0c0.138617,-0.426294 0.59648,-0.659379 1.022774,-0.520763l13.696009,4.454016c0.426057,0.138379 0.659142,0.59648 0.520763,1.022537l0,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#000000" id="svg_31" d="m77.14766,124.373244c-0.134582,0.414189 -0.57939,0.640628 -0.993579,0.506046l-13.300809,-4.325605c-0.413952,-0.134344 -0.640153,-0.57939 -0.505809,-0.993342l0,0c0.134344,-0.413714 0.57939,-0.640391 0.993579,-0.505809l13.300809,4.325605c0.413952,0.134344 0.640153,0.579153 0.505809,0.993104l0,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#000000" id="svg_32" d="m77.14766,127.324311c-0.134582,0.414189 -0.57939,0.640628 -0.993579,0.506046l-13.300809,-4.325605c-0.413952,-0.134344 -0.640153,-0.57939 -0.505809,-0.993342l0,0c0.134344,-0.413714 0.57939,-0.640391 0.993579,-0.505809l13.300809,4.325605c0.413952,0.134582 0.640153,0.57939 0.505809,0.993104l0,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#000000" id="svg_33" d="m77.14766,130.275616c-0.134582,0.414189 -0.57939,0.640628 -0.993579,0.506046l-13.300809,-4.325605c-0.413952,-0.134344 -0.640153,-0.57939 -0.505809,-0.993342l0,0c0.134344,-0.413714 0.57939,-0.640391 0.993579,-0.505809l13.300809,4.325605c0.413952,0.134582 0.640153,0.57939 0.505809,0.993104l0,0z" stroke-miterlimit="10" fill="#FFFFFF"/>
<path stroke="#000000" id="svg_34" d="m10.406257,16.399975c0,0 4.295461,-3.817897 7.099366,-17.399975" stroke-miterlimit="10" fill="none"/>
<path stroke="#000000" stroke-width="0" id="svg_17" d="m73.984632,45.213054c0,0 -8.988496,2.220243 -23.796051,-10.215397c-0.050795,-0.042724 -0.101589,-0.085449 -0.152621,-0.128648c0,0 -2.255135,-19.548299 15.869968,-18.397114c0,0 12.365383,0.773074 10.614395,13.30698c0,0 0.932103,-0.348441 1.811276,0.602888l-1.477314,7.525661l0.511268,0.191548l-1.207676,3.014442l-2.173246,4.099641z" fill="none"/>
</g>
<circle r=8 cx=125 cy =300 class="control"></circle>
<circle r=8 cx=325 cy =50 class="control"></circle>
<circle r=8 cx=525 cy =300 class="control"></circle>
</svg>
<script>
var w = 800,
h = 500,
t = 0,
padding =10,
n = 4;
var points = [
{x: 125, y: 300},
{x: 325,y: 50},
{x: 525,y: 300}
];
var svgBezier = d3.select("#vis-canvas")
var vis = svgBezier.attr("transform", "translate(" + padding + "," + padding + ")")
var curve = svgBezier.append("g").append("path").attr("class", "curve");
var controlPath = svgBezier.append("g").attr("class", "controlPath");
var circles = svgBezier.append("g").attr("class", "controlCircles");
var PathData = [];
var lineGenerator = d3.line();
var cp1 = controlPath.append("line").attr("id","controlPath1").attr("x1",points[0].x).attr("x2",points[1].x).attr("y1",points[0].y).attr("y2",points[1].y).attr("stroke","black").attr("stroke-width",.5)
var cp2 = controlPath.append("line").attr("id","controlPath2").attr("x1",points[1].x).attr("x2",points[2].x).attr("y1",points[1].y).attr("y2",points[2].y).attr("stroke","black").attr("stroke-width",.5)
circles.selectAll(".control")
.data(points)
.enter()
.append("circle")
.attr("class", "control")
.attr("cx", x)
.attr("cy", y)
.attr("fill","gray")
.call(d3.drag()
.on("start", function(d) {
this.__origin__ = [d.x, d.y];
d3.select(this).classed("drag", true);
})
.on("drag", function(d) {
getBezier();
d.x = Math.min(w, Math.max(0, this.__origin__[0] += d3.event.dx));
d.y = Math.min(400, Math.max(15, this.__origin__[1] += d3.event.dy));
bezier = {};
update();
vis.selectAll("circle.control")
.attr("cx", x)
.attr("cy", y);
})
.on("end", function() {
delete this.__origin__;
d3.select(this).classed("drag", false);
}));
vis.append("text")
.attr("class", "t")
.attr("x", 700)
.attr("y", 50)
.attr("text-anchor", "middle");
controlLabels = vis.selectAll("text.controltext")
.data(points)
.enter()
.append("text")
.attr("class", "controltext")
.attr("x", x)
.attr("y", y)
.attr("dx", "10px")
.attr("dy", "15px")
.text(function(d, i) { return "P" + i });
var BezierX=0;
var BezierY=0;
var CircleData=[];
getBezier();
update();
var last = 0;
d3.timer(function(elapsed) {
t = (t + (elapsed - last) / 3000) % 1;
last = elapsed;
update();
});
function update() {
curve.attr("d", lineGenerator(PathData.slice(0,PathData.length*t)));
t1 = t;
vis.selectAll("text.t").attr("fill","red").text("t=" + t1.toFixed(2));
cp1.attr("x1",points[0].x).attr("x2",points[1].x).attr("y1",points[0].y).attr("y2",points[1].y)
cp2.attr("x1",points[1].x).attr("x2",points[2].x).attr("y1",points[1].y).attr("y2",points[2].y)
d3.selectAll(".controltext")
.attr("x", x)
.attr("y", y)
.attr("dx", "10px")
.attr("dy", "15px")
.text(function(d, i) { return "P" + i })
d3.selectAll("#bradySVG").attr("transform","translate("+(points[0].x-20)+","+(points[0].y+7)+")")
}
function getBezier(){
x1 = points[0].x;
x2 = points[1].x;
x3 = points[2].x;
y1 = points[0].y;
y2 = points[1].y;
y3 = points[2].y;
PathData = [];
CircleData = [];
NewData = [];
for (z=0; z<=1; z+=.01) {
BezierX = Math.pow((1-z),2)*x1+2*(1-z)*z*x2+(Math.pow(z,2))*x3;
BezierY = Math.pow((1-z),2)*y1+2*(1-z)*z*y2+(Math.pow(z,2))*y3;
PathData.push([BezierX,BezierY]);
;}
;}
function x(d) {return d.x; }
function y(d) {return d.y; }
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment