xxxxxxxxxx
<meta charset="utf-8">
<style>
.path--background {
fill: none;
stroke: #000;
stroke-width: 2px;
}
.chrono_label {
font: 16px sans-serif;
text-anchor: middle;
}
:root {
--accent-color: #E8336D;
}
h1{
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 22px;
font-style: bold;
}
h2{
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 18px;
}
p{
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 16px;
}
.annotation path {
stroke: var(--accent-color);
fill: var(--accent-color);
}
.annotation path.connector-arrow{
fill: var(--accent-color);
}
.annotation-note-title {
font-weight: bold;
}
.annotation-subject{
stroke-width: 0px;
}
.annotation-note-bg {
fill: #111144;
fill-opacity: 0.9;
filter: url(#blur-effect);
}
rect.annotation-note-bg {
fill: rgba(100, 100, 100, 1);
}
text.hover {
font-size: .7em;
}
.hidden {
display: none;
}
.monotone {
stroke: var(--accent-color);
fill: var(--accent-color);
}
.annotation-tip .annotation path {
stroke: var(--accent-color);
}
.annotation-tip .annotation text.annotation-note-title {
fill: black;
}
.annotation-tip .annotation text.annotation-note-label {
fill: #E8336D;
}
.annotation-tip .annotation .annotation-note {
width: 160px;
}
</style>
<body>
<h1> IV Tournoi de Balle Sanglante de Laelith - Terrain du Grand Theâtre </h1>
<h2> Match de round#3: Les Gorilles Blancs vs L'Amicale des brasseurs bourrus </h2>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/susielu/d3-annotation/d3-annotation.min.js"></script>
<script>
var points = [];
points.push([494,297, d3.randomUniform(0, 5000)() ]);
var LesEquipes = [];
var LesJoueurs = [];
var zones = [0,38,76,114,152,190,228,266,304,342,380,418,456,494,532,570,608,646,684,722,760,798,836,874,912,950];
// Timer variables
var now, startTime, isStarted = false, elapsedTime = 0;
var body = d3.select("body"); // select the 'body' element
var svg = body.append("svg") // append an SVG element to the body
.attr("width", 1400)
.attr("height", 600);
var arc = d3.arc()
.innerRadius(30)
.outerRadius(45)
.startAngle(0)
.endAngle(function(d) { return (d.value / d.size) * 2 * Math.PI; });
var chrono_calque;
var chrono_path;
var chrono_label;
var ball_calque;
DrawPitch();
DrawBall();
DrawChrono();
startTime = Date.now();
d3.json('LogTT1.json', function(data) {
log = data.log_data;
log.forEach((d,i) => { points.push([zones[d.ball]+d3.randomUniform(2, 36)(),d3.randomUniform(52, 542)(), d3.randomUniform(0, 5000)() ]); });
points.forEach(function(d,i) {
svg.append("path")
.attr("id", function(d,i) { return "balltrack_" + i;})
.style("stroke", "#ffab00")
.style("stroke-width", 0.4) // set the stroke width
.attr("d", function() {
var next = i+1;
if (i==points.length-1) {next = i;}
return "M"+points[i][0]+","+points[i][1]+" L"+points[next][0]+","+points[next][1];
});
});
});
d3.json('FeuilleDeMatch.json', function(data) {
LesEquipes = data.teams;
LesJoueurs = data.players;
LesEquipes.forEach(equipe => {DrawPlayer(equipe);})
Legende();
update();
});
function DrawPlayer(team) {
var player_data = LesJoueurs.filter(function(p){ return p.properties.team==team.properties.id;})
svg.selectAll(".player").filter(function(p){ return p.properties.team==team.properties.id;})
.data(player_data)
.enter()
.append("circle")
.attr("class","player")
.attr("cx", function(d) { return d.geometry.coordinates[0]; })
.attr("cy", function(d) { return d.geometry.coordinates[1]; })
.attr("r", 14)
.style("fill", team.properties.fillcolor)
.style("stroke", team.properties.strokecolor)
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
};
function dragstarted(d) {
d3.select(this).raise();
}
function dragended(d) {
d3.select(this).style("opacity", 1);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.x = d3.event.x)
.attr("cy", d.y = d3.event.y)
.style("opacity", .5);
}
function DrawPitch() {
for (var i = 1; i < 26; i++) {
if(i&1)
c = "#80B266"
else
c = "#80B280"
svg.append("rect") // attach a rectangle
.attr("x", i*38) // position the left of the rectangle
.attr("y", 50) // position the top of the rectangle
.attr("height", 497) // set the height
.attr("width", 38) // set the width
.style("stroke-width", 4) // set the stroke width
.style("fill", c); // set the fill colour
}
// draw a rectangle - pitch
svg.append("rect") // attach a rectangle
.attr("x", 0) // position the left of the rectangle
.attr("y", 52) // position the top of the rectangle
.attr("height", 492) // set the height
.attr("width", 988) // set the width
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "transparent"); // set the fill colour
// draw a rectangle - halves
svg.append("rect") // attach a rectangle
.attr("x", 0) // position the left of the rectangle
.attr("y", 52) // position the top of the rectangle
.attr("height", 492) // set the height
.attr("width", 494) // set the width
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "transparent"); // set the fill colour
svg.append("line")
.attr("x1", 342)
.attr("y1", 52)
.attr("x2", 342)
.attr("y2", 542)
.style("stroke-dasharray", ("3, 3")) // <== This line here!!
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400"); // set the line colour
svg.append("line")
.attr("x1", 646)
.attr("y1", 52)
.attr("x2", 646)
.attr("y2", 542)
.style("stroke-dasharray", ("3, 3")) // <== This line here!!
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400"); // set the line colour
// draw a circle - center circle
svg.append("circle") // attach a circle
.attr("cx", 494) // position the x-centre
.attr("cy", 297) // position the y-centre
.attr("r", 38) // set the radius
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "none"); // set the fill colour
// draw a rectangle - six yard box 1
svg.append("rect") // attach a rectangle
.attr("x", 2) // position the left of the rectangle
.attr("y", 52) // position the top of the rectangle
.attr("height", 492) // set the height
.attr("width", 36) // set the width
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "seagreen"); // set the fill colour
// draw a rectangle - six yard box 2
svg.append("rect") // attach a rectangle
.attr("x", 950) // position the left of the rectangle
.attr("y", 52) // position the top of the rectangle
.attr("height", 492) // set the height
.attr("width", 38) // set the width
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "seagreen"); // set the fill colour
// draw a rectangle - zone des remplacants pour equipe 1
svg.append("rect") // attach a rectangle
.attr("x", 100) // position the left of the rectangle
.attr("y", 2) // position the top of the rectangle
.attr("height", 42) // set the height
.attr("width", 152) // set the width
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "seagreen"); // set the fill colour
// draw a rectangle - zone des remplacants pour equipe 2
svg.append("rect") // attach a rectangle
.attr("x", 736) // position the left of the rectangle
.attr("y", 552) // position the top of the rectangle
.attr("height", 42) // set the height
.attr("width", 152) // set the width
.style("stroke-width", 4) // set the stroke width
.style("stroke", "#001400") // set the line colour
.style("fill", "seagreen"); // set the fill colour
// draw a circle - penalty spot 1
svg.append("circle") // attach a circle
.attr("cx", 19) // position the x-centre
.attr("cy", 297) // position the y-centre
.attr("r", 4) // set the radius
.style("fill", "#001400"); // set the fill colour
// draw a circle - penalty spot 2
svg.append("circle") // attach a circle
.attr("cx", 969) // position the x-centre
.attr("cy", 297) // position the y-centre
.attr("r", 4) // set the radius
.style("fill", "#001400"); // set the fill colour
// draw a circle - center spot
svg.append("circle") // attach a circle
.attr("cx", 494) // position the x-centre
.attr("cy", 297) // position the y-centre
.attr("r", 4) // set the radius
.style("fill", "#001400"); // set the fill colour
}
function DrawBall() {
var ball_holder = {pos:0};
ball_calque = svg.selectAll(".ball_calque")
.data([ball_holder])
.enter().append("g")
.attr("class", "ball_calque");
ball_calque.append("ellipse")
.attr("class", "ball")
.attr("cx", 494) // position the x-centre
.attr("cy", 297) // position the y-centre
.attr("rx", 6) // set the radius
.attr("ry", 8) // set the radius
.style("stroke-width", 2) // set the stroke width
.style("stroke", "darkred") // set the line colour
.style("fill", "peru"); // set the fill colour
}
function DrawChrono() {
var chronos = [
{value: 3, size: 3, label: "TT", update: function(d) { return d; }},
{value: 10, size: 10, label: "min", update: function(d) { return ((d*10) % 10); }},
{value: 10, size: 10, label: "round", update: function(d) { return ((d*100) % 10); }}
];
chrono_calque = svg.selectAll(".chrono")
.data(chronos)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + 1108 + "," + (100 + 104*i) + ")"; })
.attr("class", "chrono");
chrono_calque.append("path")
.attr("class", "chrono_path path--background")
.attr("d", arc);
chrono_path = chrono_calque.append("path")
.attr("class", "chrono_path path--foreground");
chrono_label = chrono_calque.append("text")
.attr("class", "chrono_label")
.attr("dy", ".35em");
}
function update() {
var TT = tick();
chrono_calque
.each(function(d) { d.previous = d.value, d.value = d.update(TT); });
ball_calque
.each(function(d) { d.pos = Math.floor(TT*100); });
chrono_path.transition()
.ease(d3.easeElasticInOut)
.duration(750)
.attrTween("d", arcTween);
ball_calque.transition()
.ease(d3.easeLinear)
.duration(750)
.attrTween("transform", function(d) {
var next = d.pos+1;
if (d.pos==points.length-1) { next = d.pos;}
var prot = d3.interpolate(points[d.pos][2], points[next][2]);
var px = d3.interpolateNumber(points[d.pos][0], points[next][0]);
var py = d3.interpolateNumber(points[d.pos][1], points[next][1]);
var rounds = TT*100;
var tt = rounds - Math.floor(rounds);
return function(t) {
return "translate(" + (px(tt) - 494) + "," + (py(tt) -297) +") rotate(" + prot(tt) + ",494, 297)";
};
});
chrono_label
.text(function(d) {
if (d.label== "TT") {
return Math.floor(d.value+1) + d.label;
} else {
return Math.floor(d.value) + d.label;
}
})
setTimeout(update, TT);
};
function arcTween(b) {
var i = d3.interpolate({value: b.previous}, b);
return function(t) {
return arc(i(t));
};
}
function tick(){
now = Date.now();
elapsedTime = elapsedTime + now - startTime;
startTime = now;
return elapsedTime/100000;
}
function Legende(){
var calqueTips = svg.append("g").attr("class","calqueTips");
createTips = d3.annotation()
.annotations(LesJoueurs.map(function(d,i){
return {
data: {x: d.geometry.coordinates[0], y: d.geometry.coordinates[1]},
dx: d.dx || (d.geometry.coordinates[0] > 968) ? -20 : 20,
dy: d.dy || (d.geometry.coordinates[1] > 472) ? -20 : 20,
note: { title: d.properties.name },
subject : { radius: 20, radiusPadding: 2}
}
}))
.type(d3.annotationCalloutCircle)
.accessors({ x: d => d.x , y: d => d.y})
.on('subjectover', function (annotation) {
annotation.type.a.selectAll("g.annotation-connector, g.annotation-note").classed("hidden", false);
})
.on('subjectout', function (annotation) {
annotation.type.a.selectAll("g.annotation-connector, g.annotation-note").classed("hidden", true);
});
calqueTips.attr("class", "annotation-tip").call(createTips);
calqueTips.selectAll("g.annotation-connector, g.annotation-note").classed("hidden", true);
}
</script>
</body>
Updated missing url https://rawgit.com/susielu/d3-annotation/master/d3-annotation.min.js to https://cdn.jsdelivr.net/gh/susielu/d3-annotation/d3-annotation.min.js
https://d3js.org/d3.v4.min.js
https://rawgit.com/susielu/d3-annotation/master/d3-annotation.min.js