A huge image is shown on screen; you can pan/zoom the image to see all the detail or the entire image at once.
Each of the possible operations can be performed by one of several mouse actions. Some operations have only one type of mouse activity.
When the operation can be performed using the keyboard, then the key bindings are listed as well.
Click and drag the image (background), release during drag, i.e. act it out as a swipe movement.
keys: ---
Either swipe (see above) or drag the image (background) and hold in place, then release, to pan the image around.
You may also move the mouse near the 'edges' to auto-pan.
keys: [Page Up], [Page Down], [Arrow Up], [Arrow Down]
Click somewhere to center on that pixel.
keys: ---
Zooming in/out:
keys: [+], [-], [Keypad +], [Keypad -]
Right click.
keys: [END], [E]
Create and test mobile/tablet actions for each of the operations.
xxxxxxxxxx
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script type="text/javascript" src="../../html/js/d3/d3.latest.js"></script>
<script type="text/javascript" src="../../html/js/jwerty/jwerty.js"></script>
<link href='https://fonts.googleapis.com/css?family=Abel' rel='stylesheet' type='text/css'>
<style type="text/css">
body
{
font-family: 'Abel', sans-serif;
font-size: 14px;
}
h1
{
font-size: 200%;
font-weight: normal;
}
#chart
{
position: relative;
text-align: center;
margin: 0 auto;
height: 460px;
width: 920px;
}
#manipulated-area
{
position: relative;
height: 460px;
width: 920px;
overflow: hidden;
}
#progress
{
position: absolute;
top: 45%;
left: 50%;
}
#konachan
{
position: absolute;
top: -500px;
left: -12000px;
opacity: 0.2;
}
#tip_of_the_day
{
background: black;
border: solid white 3px;
border-radius: 10px;
box-shadow: 0 0 0 3px black, 2px 2px 6px 3px black;
padding: 6px 24px;
color: white;
width: 600px;
display: none;
position: absolute;
top: 30%;
left: 15%;
}
#tip_of_the_day h1
{
text-align: center;
}
</style>
</head>
<body>
<div id="chart">
<div id="manipulated-area">
<img id="progress" src="images/progress.gif" >
<img id="konachan" src="https://hebbut.net/gist-3732893/Konachan.com-82511.akiyama_mio.cirno.crossover.flcl.hanyuu.ikari_gendo.k-on!.parody.porco_rosso.rakka.reki.rozen_maiden.souseiseki.suigintou.takano_miyo.touhou.jpg" >
</div>
<div id="tip_of_the_day">
<h1>title</h1>
<p>bla bla bla bla</p>
</div>
</div>
<script type="text/javascript">
var viewarea = d3.select("#chart");
var img = viewarea.select("#konachan");
/*
{
"title": <string>,
"description": [ ... ],
"keys": [...]
}
*/
function show_tip(tip, duration) {
var tip_box = d3.select("#tip_of_the_day");
tip_box
.style("opacity", 1e-6)
.style("display", "block")
.transition()
.duration(1000)
.style("opacity", 1.0)
.transition()
.delay(duration)
.duration(1000)
.style("opacity", 1e-6)
// only once we're COMPLETELY TRANSPARENT, do we 'hide' the node:
.each("end", function(d) {
d3.select(this)
.style("display", "none");
});
tip_box.select("h1")
.text(tip.title);
var p = tip_box.selectAll("p").data(tip.description)
.text(function(d) {
return d;
});
p
.exit().remove();
p
.enter().append("p").text(function(d) {
return d;
});
}
function hide_tip(tip) {
var tip_box = d3.select("#tip_of_the_day");
// this transition nukes all the previous registered/running ones for this selection ~ DOM node set.
tip_box
.transition()
.style("opacity", 1e-6)
// only once we're COMPLETELY TRANSPARENT, do we 'hide' the node:
.each("end", function(d) {
d3.select(this)
.style("display", "none");
});
}
d3.json("README.json", function(json) {
var tip = null;
var tip_index = 0;
var duration = 1000;
var inactivity_action = function() {
tip_index %= json.tip_of_the_day.length;
tip = json.tip_of_the_day[tip_index++];
duration = 0;
tip.description.forEach(function(d) {
duration += d.length;
});
duration *= 1000 / 16; // reading speed estimate (the lower bound): 16 characters per second
show_tip(tip, duration);
duration += 3000; // 3 seconds between tips
d3.timer(inactivity_action, duration);
// return true; // stop timer from calling us again based on the original d3.timer setup call
return false; // make sure our callback, now with new timeout, will be triggered
};
// show first tip after 1 second
d3.timer(inactivity_action, duration);
d3.select("body")
.on("mousemove", function() {
if (tip) {
hide_tip(tip);
tip = null;
}
d3.timer(inactivity_action, duration = 5000);
});
var pan_behaviour = d3.behavior.drag()
.origin(function() {
return this; /* DOM node already delivers .x and .y by itself */
})
.on("dragstart", function() {
console.log(d3.event);
})
.on("drag", function() {
console.log(d3.event);
})
.on("dragend", function() {
console.log(d3.event);
});
img.call(pan_behaviour)
.on("mousemove.monitor", function() {
console.log(d3.event);
});
img.on("mousemove", function() {
});
});
</script>
</body>
</html>