UNPKG

@patricksurry/g3

Version:

A flexible Javascript framework for building steam gauge instrument panels that display live external metrics from flight (or other) simulators like XPlane or MS FS2020

129 lines (124 loc) 6.48 kB
import * as d3 from 'd3'; import * as g3 from '../g3.js'; const tachyLabels = [].concat( d3.range(60,95,5), d3.range(100,200,10), d3.range(200,300,25), d3.range(300,400,50), d3.range(400,600,100), ), noTachyLabels = (v => !tachyLabels.includes(v)), noNearlyFives = (v => Math.abs(v - 5*Math.round(v/5)) > 0.25); // See https://en.wikipedia.org/wiki/Omega_Speedmaster tho this is a date variant export function omegaSpeedmaster() { return g3.gauge() .metric('time').unit('s') .fake(g3.midnightSecondsSeries()) .measure(d3.scaleLinear().domain([0,60]).range([0, 360])) .css(` .g3-pointer-hub, .g3-pointer-blade {fill: #ddd; stroke: #ddd} text {fill: #ccc} .g3-highlight {fill-opacity: 0.5;} `) .append( // indicate the date at the 3 o'clock position g3.put().rotate(90).append( g3.gauge().autoindicate(true) .metric('date').unit('dateTime') .fake(g3.datetimeSeries()) .rescale(dt => dt.getDate()) .measure(d3.scaleLinear().domain([1,32]).range([0,360])) .append( g3.gaugeFace(), g3.axisLabels().step(1).orient('relative').rotate(-90).size(13).inset(45) ), ), g3.gaugeFace().window( g3.axisSector([13.75, 16.25]).inset(36).size(19).style('fill: black') ), g3.gaugeFace().r(45).style('fill: #282828'), g3.axisSector([13.75, 16.25]).inset(36).size(19).style('fill: none; stroke: #ccc; stroke-width: 3'), // watch outline and tachymetre divider g3.axisLine().style('stroke-width: 4; stroke: #aaa'), g3.axisSector().inset(14).size(10).style('fill: #aaa'), g3.axisSector().inset(17).size(1).style('fill: white; filter: url(#gaussianBlur1)'), // Gauge with no metric or pointer to render the inverted speed scale g3.gauge() .measure(d3.scalePow().exponent(-1).domain([60, 500]).range([360, 43.2])) .append( g3.axisTicks(d3.range(60,100).filter(noTachyLabels)).inset(12).size(-3), g3.axisTicks(d3.range(60,140,5).filter(noTachyLabels)).inset(12).size(-5), g3.axisTicks(tachyLabels).shape('dot').size(0.5).inset(12), g3.axisLabels(tachyLabels).inset(6).size(6), ), g3.axisLabels({3.6: 'TACHYMETRE'}).orient('clockwise').inset(7).size(7), // main face ticks g3.put().scale(0.72).append( g3.axisTicks(d3.range(0, 60, 0.2).filter(noNearlyFives)).size(3).style('stroke: #888'), g3.axisTicks(d3.range(0, 60, 1).filter(noNearlyFives)).size(8), g3.axisTicks([29, 31]).inset(3).size(5).class('g3-bg-stroke'), g3.axisTicks(d3.range(0, 60, 5).filter(v => v % 15)).inset(8).size(16) .shape('wedge').width(4).style('stroke-width: 3'), g3.axisLabels().step(5).start(5).format(d3.format('02d')).inset(2.5).size(7.5).orient('upward'), ), g3.axisLabels({31: 'SWISS', 29: 'MADE'}).orient('counterclockwise').inset(31.5).size(2.5), g3.element('image', { href: 'speedmaster_logo.png', width: 32, x: 9, y: -16, }), // Time seconds at the 9 o'clock position g3.put().x(-42).scale(0.25).append( g3.gaugeFace(), g3.axisLine().style('stroke: #aaa; stroke-width: 4'), g3.axisSector().size(50).style('fill: #282828'), g3.axisTicks(d3.range(5,60,5).filter(v => v % 15)).inset(5).size(20).style('stroke-width: 2'), g3.axisLabels().step(15).start(15).size(40), g3.indicatePointer().shape('wedge').rescale(g3.snapScale()), ), // gauge for chrono hour and minute g3.gauge() .metric('elapsed').unit('s') .fake(g3.elapsedSecondsSeries()) .measure(d3.scaleLinear().domain([0,60]).range([0, 360])) .append( // 30-minute counter at the 12 o'clock position g3.put().y(-42).scale(0.25).append( // TODO need to manually scale ticks/labels for 30 minute counter g3.gaugeFace(), g3.axisLine().style('stroke: #aaa; stroke-width: 4'), g3.axisSector().size(50).style('fill: #282828'), g3.axisTicks( d3.range(2, 60, 2) .filter(v => Math.abs(v - Math.round(v/20)*20) > 2) ).step(2).inset(5).size(10), g3.axisTicks().start(10).step(20).inset(5).size(20).style('stroke-width: 2'), g3.axisLabels().start(20).step(20).size(40).format(v => v/2), g3.indicatePointer().shape('wedge').rescale(v => v/30), ), // 12-hour counter at the 6 o'clock position g3.put().y(42).scale(0.25).append( g3.gaugeFace(), g3.axisLine().style('stroke: #aaa; stroke-width: 4'), g3.axisSector().size(50).style('fill: #282828'), g3.axisTicks(d3.range(5,60,5).filter(v => v % 15)).inset(5).size(20).style('stroke-width: 2'), g3.axisLabels().step(15).start(15).size(40).format(v => v/5), g3.indicatePointer().shape('wedge').rescale(v => v/60/12), ), ), // time hours and minutes indicator g3.put().scale(0.75).append( g3.indicatePointer().shape('omega-baton-short').rescale(v => v/60/12), g3.indicatePointer().shape('omega-baton-long').rescale(v => v/60), // indicator for chrono seconds g3.gauge() .metric('elapsed').unit('s') .measure(d3.scaleLinear().domain([0,60]).range([0, 360])) .append( g3.indicatePointer().shape('omega-second') ), ), ) }