如何用R的highcharter包复现Highcharts时钟仪表盘?
在Shiny中复现Highcharts时钟仪表盘的解决方案
完整可运行代码
借助highcharter包对接Highcharts,结合Shiny的定时更新机制,以下是实现时钟仪表盘的完整代码:
library(shiny) library(highcharter) ui <- fluidPage( highchartOutput("clock_gauge", height = "400px") ) server <- function(input, output, session) { # 每秒触发一次更新,同步系统时间 timer <- reactiveTimer(1000) output$clock_gauge <- renderHighchart({ timer() # 触发定时刷新 # 获取当前时间的时分秒 now <- Sys.time() hours <- as.integer(format(now, "%H")) minutes <- as.integer(format(now, "%M")) seconds <- as.integer(format(now, "%S")) # 转换为Highcharts仪表盘的角度值(仪表盘角度范围:-90°到270°,对应12点到12点) hour_angle <- (hours %% 12) * 30 + minutes / 2 - 90 # 时针每小时30°,每分钟额外加0.5° minute_angle <- minutes * 6 - 90 # 分针每分钟6° second_angle <- seconds * 6 - 90 # 秒针每秒6° highchart() %>% hc_chart( type = "gauge", plotBackgroundColor = NULL, plotBackgroundImage = NULL, plotBorderWidth = 0, plotShadow = FALSE ) %>% hc_title(text = "Highcharts Clock Gauge") %>% hc_pane( startAngle = -90, endAngle = 270, background = list( list( backgroundColor = list(linearGradient = list(x1 = 0, y1 = 0, x2 = 0, y2 = 1), stops = list( list(0, '#FFF'), list(1, '#333') )), borderWidth = 0, outerRadius = '109%' ), list( backgroundColor = list(linearGradient = list(x1 = 0, y1 = 0, x2 = 0, y2 = 1), stops = list( list(0, '#333'), list(1, '#FFF') )), borderWidth = 1, outerRadius = '107%' ), list(), list( backgroundColor = '#DDD', borderWidth = 0, outerRadius = '105%', innerRadius = '103%' ) ) ) %>% hc_yAxis( min = 0, max = 12, lineWidth = 0, minorTickInterval = NULL, tickAmount = 12, labels = list( distance = 20, style = list(fontSize = '15px') ), tickLength = 15, tickWidth = 2, tickPosition = 'outside' ) %>% hc_plotOptions( gauge = list( dataLabels = list(enabled = FALSE), dial = list( radius = '80%' ) ) ) %>% hc_series( # 时针配置 list( name = 'Hours', data = list((hour_angle + 90)/30), # 转换为0-12的数值范围 dial = list( radius = '60%', baseWidth = 4, baseLength = '95%', rearLength = 0 ) ), # 分针配置 list( name = 'Minutes', data = list((minute_angle + 90)/6), dial = list( radius = '80%', baseWidth = 3, baseLength = '95%', rearLength = 0 ) ), # 秒针配置 list( name = 'Seconds', data = list((second_angle + 90)/6), dial = list( radius = '90%', baseWidth = 1, baseLength = '95%', rearLength = '20%' ) ) ) %>% # 添加Highcharts扩展逻辑,优化指针交互状态 hc_add_js(" (function(H) { H.wrap(H.seriesTypes.gauge.prototype.pointClass.prototype, 'setState', function(proceed) { proceed.apply(this, Array.prototype.slice.call(arguments, 1)); if (this.series.chart.pointer) { this.series.chart.pointer.onMouseOut(); } }); }(Highcharts)); ") }) } shinyApp(ui, server)
核心逻辑说明
- 定时更新:通过
reactiveTimer(1000)实现每秒刷新一次,确保时钟与系统时间同步。 - 角度映射:将时分秒转换为Highcharts仪表盘支持的角度范围,再映射到0-12的数值轴范围。
- 指针样式定制:通过
hc_series的dial参数分别定义时针、分针、秒针的长度、宽度,还原原Demo的视觉效果。 - JS扩展嵌入:用
hc_add_js()添加Highcharts原生方法的扩展代码,优化指针的交互表现。
R中处理JavaScript的常用方法
JS()函数:在highcharter或htmlwidgets的配置中,用JS("你的代码")包裹JS片段,用于设置事件回调、自定义格式化函数等需要JS逻辑的参数。hc_add_js():highcharter专属方法,用于添加全局的Highcharts扩展代码,比如修改原生原型方法。tags$script():在Shiny的UI中插入全局JS,可定义全局函数、监听页面事件,示例:tags$script(HTML(" function customFunc() { // 自定义JS逻辑 } "))onRender():htmlwidgets包的方法,在widget渲染完成后执行JS代码,常用于动态修改已渲染的图表,示例:highchart() %>% onRender("function(el, x) { // 图表渲染后的JS操作 }")- Shiny与JS数据交互:用
Shiny.onInputChange('inputId', value)在JS中向Shiny传数据,R中通过input$inputId接收;用session$sendCustomMessage()从R向JS发数据,JS中用Shiny.addCustomMessageHandler()监听。
内容的提问来源于stack exchange,提问作者JohnBones JohnBones
相关产品推荐
相关产品推荐

