子弹仪表盘

BulletGraph是一种专为仪表板设计的线性测量仪。 它显示单个关键指标以及比较测量和定性范围,以立即表明该指标是好的,坏的还是在某些其他状态。

Bullet Graph由仪表板设计专家Stephen Few创建并推广。

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; import * as wijmo from '@grapecity/wijmo'; import * as gauge from '@grapecity/wijmo.gauge'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { // dashboard dada let dashboard = [ { heading: 'Revenue', sub: 'US$, thousands', max: 400, actual: 345, target: 340, bad: 210, good: 300 }, { heading: 'Profit', sub: '%', max: 50, actual: 37, target: 32, bad: 20, good: 30 }, { heading: 'Order Size', sub: 'US$, average', max: 600, actual: 320, target: 520, bad: 400, good: 500 }, { heading: 'New Customers', sub: 'count', max: 1500, actual: 1100, target: 1000, bad: 600, good: 900 }, { heading: 'Satisfaction', sub: '0 to 5', max: 5, actual: 4, target: 4.5, bad: 2.5, good: 4.5 }, ]; // // create the dashboard let table = document.createElement('table'); document.getElementById('dashboard').appendChild(table); dashboard.forEach(function (item) { let tr = document.createElement('tr'); table.appendChild(tr); // // heading let td = document.createElement('td'); tr.appendChild(td); let fmt = '<div class="heading">{heading}</div><div class="sub">{sub}</div>'; td.innerHTML = wijmo.format(fmt, item); // // warning td = document.createElement('td'); tr.appendChild(td); if (item.actual < item.target) { td.innerHTML = '<span class="glyphicon glyphicon-thumbs-down warning"></span>'; } // // bullet graph td = document.createElement('td'); tr.appendChild(td); let bg = new gauge.BulletGraph(document.createElement('div'), { value: item.actual, target: item.target, max: item.max, bad: item.bad, good: item.good }); td.appendChild(bg.hostElement); // // max value td = document.createElement('td'); tr.appendChild(td); td.innerHTML = wijmo.format('<span class="max">{max:n0}</span>', item); }); } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Bullet Graphs</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div id="dashboard"> </div> </div> </body> </html> #dashboard { padding: 12px; background: rgba(0, 0, 0, .02); box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); } .heading { font-weight: bold; text-align: right; } .sub { font-size: 70%; text-align: right; } .max { font-size: 70%; } .warning { color: darkred; padding-left: 12px; } .wj-gauge { margin-left: 1em; margin-right: 1em; margin-bottom: 6px; } body { margin-bottom: 24pt; } import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import './styles.css'; // import { Component, enableProdMode, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { WjGaugeModule } from '@grapecity/wijmo.angular2.gauge'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { dashboard = [ { heading: 'Revenue', sub: 'US$, thousands', max: 400, actual: 345, target: 340, bad: 210, good: 300 }, { heading: 'Profit', sub: '%', max: 50, actual: 37, target: 32, bad: 20, good: 30 }, { heading: 'Order Size', sub: 'US$, average', max: 600, actual: 320, target: 520, bad: 400, good: 500 }, { heading: 'New Customers', sub: 'count', max: 1500, actual: 1100, target: 1000, bad: 600, good: 900 }, { heading: 'Satisfaction', sub: '0 to 5', max: 5, actual: 4, target: 4.5, bad: 2.5, good: 4.5 }, ] } // @NgModule({ imports: [WjGaugeModule, BrowserModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Bullet Graphs</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <div id="dashboard"> <table> <ng-template ngFor let-item [ngForOf]="dashboard"> <tr> <td> <div class="heading">{{item.heading}}</div> <div class="sub">{{item.sub}}</div> </td> <td> <span *ngIf="item.actual < item.target" class="glyphicon glyphicon-thumbs-down warning"></span> </td> <td> <wj-bullet-graph [value]="item.actual" [target]="item.target" [max]="item.max" [bad]="item.bad" [good]="item.good"></wj-bullet-graph> </td> <td> <div class="max">{{item.max | number:'1.0-0'}}</div> </td> </tr> </ng-template> </table> </div> </div> #dashboard { padding: 12px; background: rgba(0, 0, 0, .02); box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); } .heading { font-weight: bold; text-align: right; } .sub { font-size: 70%; text-align: right; } .max { font-size: 70%; } .warning { color: darkred; padding-left: 12px; } .wj-gauge { margin-left: 1em; margin-right: 1em; margin-bottom: 6px; } body { margin-bottom: 24pt; } <template> <div class="container-fluid"> <div id="dashboard"> <table> <tr v-for="item in dashboard" :key="item.heading"> <td> <div class="heading">{{item.heading}}</div> <div class="sub">{{item.sub}}</div> </td> <td> <span v-if="item.actual < item.target" class="glyphicon glyphicon-thumbs-down warning"></span> </td> <td> <wj-bullet-graph :value="item.actual" :target="item.target" :max="item.max" :bad="item.bad" :good="item.good"></wj-bullet-graph> </td> <td> <div class="max">{{item.max | number:'1.0-0'}}</div> </td> </tr> </table> </div> </div> </template> <script> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import Vue from 'vue'; import '@grapecity/wijmo.vue2.gauge'; let App = Vue.extend({ name: 'app', data: function(){ return { dashboard: [ { heading: 'Revenue', sub: 'US$, thousands', max: 400, actual: 345, target: 340, bad: 210, good: 300 }, { heading: 'Profit', sub: '%', max: 50, actual: 37, target: 32, bad: 20, good: 30 }, { heading: 'Order Size', sub: 'US$, average', max: 600, actual: 320, target: 520, bad: 400, good: 500 }, { heading: 'New Customers', sub: 'count', max: 1500, actual: 1100, target: 1000, bad: 600, good: 900 }, { heading: 'Satisfaction', sub: '0 to 5', max: 5, actual: 4, target: 4.5, bad: 2.5, good: 4.5 }, ] } } }) new Vue({ render: h => h(App) }).$mount('#app'); </script> <style> #dashboard { padding: 12px; background: rgba(0, 0, 0, .02); box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); } .heading { font-weight: bold; text-align: right; } .sub { font-size: 70%; text-align: right; } .max { font-size: 70%; } .warning { color: darkred; padding-left: 12px; } .container-fluid .wj-gauge { margin-left: 1em; margin-right: 1em; margin-bottom: 6px; } body { margin-bottom: 24pt; } </style> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Bullet Graphs</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"> </div> </body> </html> import './app.css'; import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; // import * as wjGauge from '@grapecity/wijmo.react.gauge'; class App extends React.Component { constructor(props) { super(props); this.state = [ { heading: 'Revenue', sub: 'US$, thousands', max: 400, actual: 345, target: 340, bad: 210, good: 300 }, { heading: 'Profit', sub: '%', max: 50, actual: 37, target: 32, bad: 20, good: 30 }, { heading: 'Order Size', sub: 'US$, average', max: 600, actual: 320, target: 520, bad: 400, good: 500 }, { heading: 'New Customers', sub: 'count', max: 1500, actual: 1100, target: 1000, bad: 600, good: 900 }, { heading: 'Satisfaction', sub: '0 to 5', max: 5, actual: 4, target: 4.5, bad: 2.5, good: 4.5 }, ]; } renderSpan(item) { if (item.actual < item.target) { return <span className="glyphicon glyphicon-thumbs-down warning"></span>; } return; } renderTableTr(item) { return (<tr key={item.heading}> <td> <div className="heading">{item.heading}</div> <div className="sub">{item.sub}</div> </td> <td> {this.renderSpan(item)} </td> <td> <wjGauge.BulletGraph value={item.actual} target={item.target} max={item.max} bad={item.bad} good={item.good}></wjGauge.BulletGraph> </td> <td> <div className="max">{item.max}</div> </td> </tr>); } renderTable() { let table = []; this.state.forEach(item => { table.push(this.renderTableTr(item)); }); return table; } render() { return (<div className="container-fluid"> <div id="dashboard"> <table> {this.renderTable()} </table> </div> </div>); } } ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AutoComplete</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html> #dashboard { padding: 12px; background: rgba(0, 0, 0, .02); box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23); } .heading { font-weight: bold; text-align: right; } .sub { font-size: 70%; text-align: right; } .max { font-size: 70%; } .warning { color: darkred; padding-left: 12px; } .container-fluid .wj-gauge { margin-left: 1em; margin-right: 1em; margin-bottom: 6px; } body { margin-bottom: 24pt; }