You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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)

核心逻辑说明

  1. 定时更新:通过reactiveTimer(1000)实现每秒刷新一次,确保时钟与系统时间同步。
  2. 角度映射:将时分秒转换为Highcharts仪表盘支持的角度范围,再映射到0-12的数值轴范围。
  3. 指针样式定制:通过hc_series的dial参数分别定义时针、分针、秒针的长度、宽度,还原原Demo的视觉效果。
  4. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 13:35:40