envision.js demo
HTML
<script src="https://raw.github.com/HumbleSoftware/envisionjs/master/envision.js"></script>
<div id="container"></div>
CSS
/* Flotr */
.flotr-handles-handle {
background: #eee;
border: 1px solid #333;
position: absolute;
cursor: pointer;
border-radius: 3px;
}
.flotr-handles-handle,
.flotr-grid-label {
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
user-select: none;
}
.flotr-handles-drag {
height: 12px;
width: 6px;
}
.flotr-handles-scroll {
height: 6px;
cursor: move;
}
.flotr-handles-left {
cursor: w-resize;
}
.flotr-handles-right {
cursor: e-resize;
}
/* Dimensions */
.envision-finance {
width: 600px;
}
.envision-finance-price .envision-component {
height : 200px;
}
.envision-finance-volume .envision-component {
height : 60px;
}
.envision-finance-connection .envision-component {
height: 16px;
}
.envision-finance-summary .envision-component {
cursor: all-scroll;
height : 70px;
margin-top: -2px;
}
/* Bubble Borders */
.envision-finance-price,
.envision-finance-volume {
border: 1px solid #B6D9FF;
background: #fff;
}
.envision-finance-price {
border-top-right-radius: 5px;
border-top-left-radius: 5px;
}
.envision-finance-volume {
border-top: 0px;
}
/* Connection overlay */
.envision-finance-connection canvas {
z-index: 10;
background: #fff;
}
.envision-finance-connection canvas object {
position: absolute;
top: 0px;
}
/* Y-Axis Labels */
.envision-finance-price .flotr-grid-label {
margin-left: 4px;
}
.envision-finance-price .flotr-grid-label.first {
margin-top: -6px;
}
.envision-finance-price .flotr-grid-label.last {
margin-top: 6px;
}
/* X-Axis Labels */
.envision-finance-summary .flotr-grid-label {
margin-top: 3px;
}
/* Mouse Tracker */
.envision-finance-price .flotr-mouse-value {
font-size: 12px;
}
.envision-finance-volume .flotr-mouse-value {
display: none;
}
@media screen and (max-width: 600px) {
.envision-finance {
width: 100%;
}
.envision-finance-price .envision-component {
height: 120px;
}
.envision-finance-summary...
JavaScript
(function realtime_demo (container) {
var
x = [],
dataA = [],
dataB = [],
data = [
// Default data using lite-lines type
[x, dataA],
// Custom data configuration
{
// Array of data:
data : [x, dataB],
// Enable bars:
bars : {
show : true
},
// Disable lines:
'lite-lines' : {
show: false
}
}
],
options, i, timesries;
// Mock Data:
function sample(i) {
x.push(i);
dataA.push(Math.sin(i / 6) * (Math.random() + 1) / 2);
dataB.push(Math.sin(i / 6 + Math.PI / 2) * (Math.random() + 1) / 2);
}
// Initial Data:
for (i = 0; i < 100; i++) {
sample(i);
}
// Envision Timeseries Options
options = {
container : container,
data : {
detail : data,
summary : data
},
defaults : {
summary : {
config : {
handles : { show : false }
}
}
}
}
// Render the timeseries
timeseries = new envision.templates.TimeSeries(options);
// Method to get new data
// This could be part of an Ajax callback, a websocket callback,
// or streaming / long-polling data source.
function getNewData () {
i++;
// Short circuit (no need to keep going! you get the idea)
if (i > 1000) return;
sample(i);
animate(i);
}
// Initial request for new data
getNewData();
// Animate the new data
function animate (i) {
var
start = (new Date()).getTime(),
length = 500, // 500ms animation length
max = i - 1, // One new point comes in at a time
min = i - 51, // Show 50 in the top
offset = 0; // Animation frame offset
// Render animation frame
(function frame () {
var
time = (new Date()).getTime(),
tick = Math.min(time - start, length),
offset = (Math.sin(Math.PI * (tick) / length - Math.PI / 2) + 1) / 2;
// Draw the summary first
...