parent
b01d0d494a
commit
cd603b9d15
2 changed files with 186 additions and 2 deletions
@ -0,0 +1,184 @@ |
||||
'use strict'; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
function Point(x, y, hex) { |
||||
if (typeof x !== typeof 1) { |
||||
throw new Error("x = " + x + " must be of type 'number'; it is currently of type '" + (typeof x) + "'."); |
||||
} |
||||
|
||||
if (typeof y !== typeof 1) { |
||||
throw new Error("y = " + y + " must be of type 'number'; it is currently of type '" + (typeof y) + "'."); |
||||
} |
||||
|
||||
if (x < 0 || y < 0) { |
||||
throw new Error("X and Y must be greater than 0."); |
||||
} |
||||
|
||||
this.x = x; |
||||
this.y = y; |
||||
this.hex = hex; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
function Triangle(p1, p2, p3) { |
||||
if (!(p1 instanceof Point) || !(p2 instanceof Point) || !(p3 instanceof Point)) { |
||||
throw new Error("All three arguments must be of type Point."); |
||||
} |
||||
|
||||
this.vertexA = p1; |
||||
this.vertexB = p2; |
||||
this.vertexC = p3; |
||||
|
||||
// Midpoints on each edge.
|
||||
this.midpointAB = this.findMidpoint(this.vertexA, this.vertexB); |
||||
this.midpointAC = this.findMidpoint(this.vertexA, this.vertexC); |
||||
this.midpointBC = this.findMidpoint(this.vertexB, this.vertexC); |
||||
|
||||
// Midpoints of segments between midpoints.
|
||||
this.midpointABAC = this.findMidpoint(this.midpointAB, this.midpointAC); |
||||
this.midpointABBC = this.findMidpoint(this.midpointAB, this.midpointBC); |
||||
this.midpointACBC = this.findMidpoint(this.midpointAC, this.midpointBC); |
||||
|
||||
// Paths created from a vertex and the midpoints on its two adjacent edges.
|
||||
this.subpathA = [this.vertexA, this.midpointAB, this.midpointAC]; |
||||
this.subpathB = [this.vertexB, this.midpointAB, this.midpointBC]; |
||||
this.subpathC = [this.vertexC, this.midpointAC, this.midpointBC]; |
||||
} |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
Triangle.prototype = { |
||||
/** |
||||
* |
||||
*/ |
||||
findMidpoint: function(p1, p2) { |
||||
var minX = Math.min(p1.x, p2.x); |
||||
var maxX = Math.max(p1.x, p2.x); |
||||
var minY = Math.min(p1.y, p2.y); |
||||
var maxY = Math.max(p1.y, p2.y); |
||||
|
||||
var midX = minX + ((maxX - minX) / 2); |
||||
var midY = minY + ((maxY - minY) / 2); |
||||
|
||||
return new Point(midX, midY); |
||||
}, |
||||
|
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
buildPath: function(p1, p2, p3, fill) { |
||||
var path = d3.select(document.createElementNS(d3.ns.prefix.svg, "path")) |
||||
.attr("d", `M${p1.x},${p1.y} L${p2.x},${p2.y} L${p3.x},${p3.y} Z`) |
||||
// .attr("stroke", "#000")
|
||||
|
||||
var hex = /^#[\da-f]{3}$|^#[\da-f]{6}$/i; |
||||
|
||||
if (fill !== undefined) { |
||||
if (fill.match(hex)) { |
||||
path.attr("fill", fill).attr("stroke", fill); |
||||
} |
||||
else { |
||||
path.attr("fill", `url(#${fill})`) |
||||
// .attr("stroke", `url(#${fill})`);
|
||||
} |
||||
} |
||||
|
||||
return function() { |
||||
return path.node(); |
||||
}; |
||||
}, |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
buildGradient: function(p1, p2, id, hex) { |
||||
var fill = d3.select(document.createElementNS(d3.ns.prefix.svg, "linearGradient")) |
||||
.attr("gradientUnits", "userSpaceOnUse") |
||||
.attr("id", id) |
||||
.attr("x1", p1.x) |
||||
.attr("y1", p1.y) |
||||
.attr("x2", p2.x) |
||||
.attr("y2", p2.y) |
||||
|
||||
fill.append("stop") |
||||
.attr("offset", "0%") |
||||
.attr("stop-color", hex) |
||||
|
||||
fill.append("stop") |
||||
.attr("offset", "100%") |
||||
.attr("stop-color", "#fff") |
||||
.attr("stop-opacity", "0") |
||||
|
||||
return function() { |
||||
return fill.node(); |
||||
}; |
||||
}, |
||||
}; |
||||
|
||||
/** |
||||
* |
||||
*/ |
||||
(function() { |
||||
var svg = d3.select("body").append("svg") |
||||
.attr("width", 500) |
||||
.attr("height", 500); |
||||
|
||||
var defs = svg.append("defs"); |
||||
|
||||
var points = [ |
||||
[ |
||||
new Point(100, 0, '#f00'), |
||||
new Point(200, 200, '#0f0'), |
||||
new Point(0, 300, '#00f') |
||||
] |
||||
|
||||
// [
|
||||
// new Point(100, 0, '#f00'),
|
||||
// new Point(200, 200, '#0f0'),
|
||||
// new Point(300, 0, '#00f')
|
||||
// ],
|
||||
|
||||
// [
|
||||
// new Point(300, 300, '#f00'),
|
||||
// new Point(200, 200, '#0f0'),
|
||||
// new Point(300, 0, '#00f')
|
||||
// ],
|
||||
]; |
||||
|
||||
var subpathA; |
||||
var subpathB; |
||||
var subpathC; |
||||
var subpathM1; |
||||
var subpathM2; |
||||
var subpathM3; |
||||
|
||||
for (var i = 0, len = points.length; i < len; i++) { |
||||
var T = new Triangle(points[i][0], points[i][1], points[i][2]); |
||||
|
||||
subpathA = T.buildPath(T.subpathA[0], T.subpathA[1], T.subpathA[2], points[i][0].hex); |
||||
subpathB = T.buildPath(T.subpathB[0], T.subpathB[1], T.subpathB[2], points[i][1].hex); |
||||
subpathC = T.buildPath(T.subpathC[0], T.subpathC[1], T.subpathC[2], points[i][2].hex); |
||||
|
||||
defs.append(T.buildGradient(T.midpointACBC, T.midpointBC, `fill-${i}-0`, points[i][0].hex)); |
||||
defs.append(T.buildGradient(T.midpointABBC, T.midpointAC, `fill-${i}-1`, points[i][1].hex)); |
||||
defs.append(T.buildGradient(T.midpointABAC, T.midpointAB, `fill-${i}-2`, points[i][2].hex)); |
||||
|
||||
subpathM1 = T.buildPath(T.midpointAB, T.midpointAC, T.midpointBC, `fill-${i}-0`); |
||||
subpathM2 = T.buildPath(T.midpointAB, T.midpointAC, T.midpointBC, `fill-${i}-1`); |
||||
subpathM3 = T.buildPath(T.midpointAB, T.midpointAC, T.midpointBC, `fill-${i}-2`); |
||||
|
||||
svg.append(subpathA); |
||||
svg.append(subpathB); |
||||
svg.append(subpathC); |
||||
|
||||
svg.append(subpathM1); |
||||
svg.append(subpathM2); |
||||
svg.append(subpathM3); |
||||
} |
||||
}()); |
Loading…
Reference in new issue