snap.js/demos/illustrated-infographic-coffee/index.html

393 lines
15 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="copyright" content="Copyright © 2013 Adobe Systems Incorporated. All rights reserved.
Licensed under the Apache License, Version 2.0 (the “License”);
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an “AS IS” BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.">
<title>Coffee Maker</title>
<link rel="stylesheet" href="../../dist/fonts/stylesheet.css">
<style media="screen">
body {
background: #fff;
margin: 0;
padding: 0;
}
.shape {
fill: none;
stroke: #60544F;
}
.outline,
.doors {
fill: #F4EEE6;
stroke: #60544F;
stroke-width: 2pt;
}
.water {
fill: #D6EDEE;
stroke: #60544F;
}
.water-cut {
fill: #B4D6DB;
}
.milk {
fill: #fff;
stroke: #60544F;
}
.milk-cut {
fill: #F4EEE6;
}
.coffee {
fill: #60544F;
stroke: #60544F;
}
.coffee-cut {
fill: #60544F;
}
</style>
<script src="../../dist/snap.svg-min.js"></script>
<script>
window.onload = function () {
var s = Snap(1000, 800),
p = 100 / 30,
h = 250,
x = 400,
y = 200,
R = 100,
r = 70,
open = 0,
gstream,
gmilk = "l()#F4EEE6-#fff:50-#F4EEE6:50-#F4EEE6",
gcoffee = "l()#60544F-#8c7a73:50-#60544F:50-#60544F",
gwater = "l()#B4D6DB-#D6EDEE:50-#B4D6DB:50-#B4D6DB";
Snap.load("demo.svg", function (f) {
var top = f.select("#top"),
bot = f.select("#bottom"),
tap = f.select("#tap"),
knob = f.select("#knob"),
dot = f.select("#dot"),
arr = f.select("#arrow"),
knobcx = knob.attr("cx"),
knobcy = knob.attr("cy"),
lead = f.select("#lead"),
pie = {
cx: f.select("#pie-chart circle").attr("cx"),
cy: f.select("#pie-chart circle").attr("cy"),
r: f.select("#pie-chart circle").attr("r"),
coffee: f.select("#legend text"),
water: f.selectAll("#legend text")[1],
title: f.selectAll("#legend text")[2],
waterBox: f.select("#legend rect:nth-child(2)")
},
angle = 0,
lastAngle,
startAngle,
leadOpenPath = lead.attr("d"),
leadClosedPath = f.select("#lead-target").attr("d"),
closed,
grp = s.g().insertBefore(tap);
f.select("#pie-chart").remove();
f.select("#americano-area").click(function () {
chosen(0);
});
f.select("#latte-area").click(function () {
chosen(72);
});
f.select("#mocha-area").click(function () {
chosen(144);
});
f.select("#mochiatto-area").click(function () {
chosen(216);
});
f.select("#espresso-area").click(function () {
chosen(288);
});
x = +top.attr("cx");
y = +top.attr("cy");
R = +top.attr("rx");
r = +bot.attr("rx");
h = bot.attr("cy") - y;
s.add(f.select("g"));
lead.click(function () {
var path,
ease;
if (closed) {
path = leadOpenPath;
ease = mina.easein;
closed = 0;
} else {
path = leadClosedPath;
ease = mina.bounce;
closed = 1;
}
lead.stop().animate({
d: path
}, 1000, ease);
});
knob.attr({
fill: "#000",
opacity: 0
}).drag(function (dx, dy, x, y) {
var a = Snap.angle(knobcx, knobcy, x, y) - startAngle + angle;
dot.transform("r" + [a, knobcx, knobcy]);
arr.transform("r" + [a, knobcx, knobcy]);
lastAngle = a;
}, function (x, y) {
startAngle = Snap.angle(knobcx, knobcy, x, y);
lastAngle = angle;
dot.stop();
arr.stop();
}, function () {
angle = lastAngle;
var a = Snap.snapTo(72, angle, 36);
chosen(a);
});
function chosen(a) {
a = (a + 1080) % 360;
angle = a;
var to = "r" + [a, knobcx, knobcy];
dot.animate({
transform: to
}, 1000, mina.elastic);
arr.animate({
transform: to
}, 1000, mina.elastic, function () {
closeCup(function () {
types[a]();
pour();
pieShow();
});
});
}
grp.path(outline(0, h)).attr("class", "outline");
var o3 = (h - 70) / 3,
o2 = (h - 70) / 2,
cover = grp.ellipse(getEll(h - 60)).attr("class", "water"),
ct1 = grp.path(cut(10, 10 + o3, 0)).attr({
fill: gcoffee
}),
ct2 = grp.path(cut(10 + o3, h - 60, 0)).attr({
fill: gwater
}),
middle = 10 + o3,
pieCoffee,
pieTitle,
pieType,
g = grp.g(),
dr = grp.path(doors(0)).attr("class", "doors"),
types = {
// americano
0: function () {
cover.attr("class", "water");
ct2.attr("fill", gwater);
middle = 10 + o3;
pieCoffee = 1 / 3;
pieType = "water";
pieTitle = "Americano";
gstream = "l(0,1,0,0)#60544F-#60544F:33-#B4D6DB";
},
// latté
72: function () {
cover.attr("class", "milk");
ct2.attr("fill", gmilk);
middle = 10 + o3 * 2;
pieCoffee = 2 / 3;
pieType = "milk";
pieTitle = "Latté";
gstream = "l(0,1,0,0)#60544F-#60544F:66-#fff";
},
// mocha
144: function () {
cover.attr("class", "milk");
ct2.attr("fill", gmilk);
middle = 10 + o3;
pieCoffee = 1 / 3;
pieType = "milk";
pieTitle = "Mocha";
gstream = "l(0,1,0,0)#60544F-#60544F:33-#fff";
},
// machiatto
216: function () {
cover.attr("class", "milk");
ct2.attr("fill", gmilk);
middle = 10 + o2;
pieCoffee = 1 / 2;
pieType = "milk";
pieTitle = "Machiatto";
gstream = "l(0,1,0,0)#60544F-#60544F:50-#fff";
},
// espresso
288: function () {
cover.attr("class", "coffee");
ct2.attr("fill", gcoffee);
middle = 10;
pieCoffee = 1;
pieType = "milk";
pieTitle = "Espresso";
gstream = "#60544F";
}
};
function closeCup(callback) {
Snap.animate(90, 0, function (val) {
ct1.attr("path", cut(10, middle, val));
ct2.attr("path", cut(middle, h - 60, val));
dr.attr("path", doors(val));
}, 500, mina.easein, callback);
}
function pour() {
steam(g, function () {
Snap.animate(0, 90, function (val) {
ct1.attr("path", cut(10, middle, val));
ct2.attr("path", cut(middle, h - 60, val));
dr.attr("path", doors(val));
}, 1500, mina.elastic);
});
}
var pieShow = (function () {
var disc = s.circle(pie.cx, pie.cy, pie.r).attr({
fill: "#fff",
stroke: "#60544F"
}),
coffee = s.path().attr({
stroke: "#60544F",
strokeWidth: pie.r,
fill: "none"
}),
olda = 0,
a;
return function () {
var cof = pieCoffee,
type = pieType;
a = 360 * cof / 2;
pie.waterBox.attr({
fill: type == "water" ? "#d6edee" : "#fff"
});
disc.attr({
fill: type == "water" ? "#d6edee" : "#fff"
});
pie.title.attr({
"#text": pieTitle
});
pie.coffee.attr({
"#text": "Espresso (" + Math.round(cof * 100) + "%)"
});
pie.water.attr({
"#text": (type == "water" ? "Hot Water" : "Milk") + " (" + (100 - Math.round(cof * 100)) + "%)"
});
Snap.animate(olda, a, function (val) {
coffee.attr({
d: "M" + [pie.cx, pie.cy] +
"U" + [pie.r / 2, 90 - val, 90 + val]
});
}, 500, function () {
if (cof == 1) {
disc.attr({
fill: "#60544F"
});
}
});
olda = a;
};
}());
types[0]();
pour();
pieShow();
});
function getEll(height) {
var ra = r + (R - r) / h * height;
return {
cx: x,
cy: y + h - height,
rx: ra,
ry: ra / p
};
}
function arc(cx, cy, R, r, from, to, command) {
var start = pointAtAngle(cx, cy, R, r, from),
end = pointAtAngle(cx, cy, R, r, to);
command = command || "M";
return command + Snap.format("{sx},{sy}A{R},{r},0,{big},{way},{tx},{ty}", {
sx: start.x,
sy: start.y,
R: R,
r: r,
tx: end.x,
ty: end.y,
big: +(Math.abs(to - from) > 180),
way: +(from > to)
});
}
function pointAtAngle(cx, cy, rx, ry, angle) {
angle = Snap.rad(angle);
return {
x: cx + rx * Math.cos(angle),
y: cy - ry * Math.sin(angle)
};
}
function doors(alpha) {
var sa = 270 - alpha / 2,
ea = 270 + alpha / 2;
if (alpha) {
return arc(x, y, R, R / p, 180, sa) + arc(x, y + h, r, r / p, sa, 180, "L") + "z" +
arc(x, y, R, R / p, ea, 360) + arc(x, y + h, r, r / p, 360, ea, "L") + "z";
} else {
return arc(x, y, R, R / p, 180, 360) + arc(x, y + h, r, r / p, 360, 180, "L") + "z";
}
}
function fill(from, to) {
var start = getEll(from),
end = getEll(to);
return "M" + (start.cx - start.rx) + "," + start.cy + "h" + start.rx * 2 +
arc(end.cx, end.cy, end.rx, end.ry, 0, 180, "L") + "z";
}
function outline(from, to) {
var start = getEll(from),
end = getEll(to);
return arc(start.cx, start.cy, start.rx, start.ry, 180, 0) +
arc(end.cx, end.cy, end.rx, end.ry, 0, 180, "L") + "z";
}
function cut(from, to, alpha) {
var s = getEll(from),
e = getEll(to),
sa = Snap.rad(270 - alpha / 2),
ea = Snap.rad(270 + alpha / 2);
return "M" + [s.cx, s.cy,
s.cx + s.rx * Math.cos(ea), s.cy - s.ry * Math.sin(ea),
e.cx + e.rx * Math.cos(ea), e.cy - e.ry * Math.sin(ea),
e.cx, e.cy,
e.cx + e.rx * Math.cos(sa), e.cy - e.ry * Math.sin(sa),
s.cx + s.rx * Math.cos(sa), s.cy - s.ry * Math.sin(sa)
] + "z";
}
function steam(g, callback) {
g.rect(x - 10, y - 1030, 20, 1000, 10).attr({
fill: gstream,
clip: s.rect(x - 10, y - 200, 20, h + 200)
}).animate({y: y + 40}, 800, function () {
this.remove();
});
s.ellipse(x, y, R, R/p).attr({
fill: "#fff",
filter: s.filter(Snap.filter.blur(10))
}).animate({cy: y - 30, opacity: 0}, 1000, callback);
}
};
</script>
</head>
<body></body>
</html>