在 R 中,如何使用 highcharter 包复制 highchart 图表

In R how to replicate highchart chart with highcharter package

提问人:JohnBones JohnBones 提问时间:11/5/2022 最后编辑:T.J. CrowderJohnBones JohnBones 更新时间:11/6/2022 访问量:120

问:

我需要在我闪亮的应用程序中复制下面的这张图表。但我正在努力处理 javascript 部分 任何帮助都会很棒:

时钟图表 Highchart

这是 javascript 代码:如何将其“翻译”为 R?

在 R 中处理 javascript 的任何帮助/指示都会很棒。

很多很多 tahnks 家伙

`/**
 * Get the current time
 */
function getNow() {
    var now = new Date();

    return {
        hours: now.getHours() + now.getMinutes() / 60,
        minutes: now.getMinutes() * 12 / 60 + now.getSeconds() * 12 / 3600,
        seconds: now.getSeconds() * 12 / 60
    };
}

/**
 * Pad numbers
 */
function pad(number, length) {
    // Create an array of the remaining length + 1 and join it with 0's
    return new Array((length || 2) + 1 - String(number).length).join(0) + number;
}

var now = getNow();

// Create the chart
Highcharts.chart('container', {

    chart: {
        type: 'gauge',
        plotBackgroundColor: null,
        plotBackgroundImage: null,
        plotBorderWidth: 0,
        plotShadow: false,
        height: '80%'
    },

    credits: {
        enabled: false
    },

    title: {
        text: 'The Highcharts clock'
    },

    pane: {
        background: [{
            // default background
        }, {
            // reflex for supported browsers
            backgroundColor: Highcharts.svg ? {
                radialGradient: {
                    cx: 0.5,
                    cy: -0.4,
                    r: 1.9
                },
                stops: [
                    [0.5, 'rgba(255, 255, 255, 0.2)'],
                    [0.5, 'rgba(200, 200, 200, 0.2)']
                ]
            } : null
        }]
    },

    yAxis: {
        labels: {
            distance: -20
        },
        min: 0,
        max: 12,
        lineWidth: 0,
        showFirstLabel: false,

        minorTickInterval: 'auto',
        minorTickWidth: 1,
        minorTickLength: 5,
        minorTickPosition: 'inside',
        minorGridLineWidth: 0,
        minorTickColor: '#666',

        tickInterval: 1,
        tickWidth: 2,
        tickPosition: 'inside',
        tickLength: 10,
        tickColor: '#666',
        title: {
            text: 'Powered by<br/>Highcharts',
            style: {
                color: '#BBB',
                fontWeight: 'normal',
                fontSize: '8px',
                lineHeight: '10px'
            },
            y: 10
        }
    },

    tooltip: {
        formatter: function () {
            return this.series.chart.tooltipText;
        }
    },

    series: [{
        data: [{
            id: 'hour',
            y: now.hours,
            dial: {
                radius: '60%',
                baseWidth: 4,
                baseLength: '95%',
                rearLength: 0
            }
        }, {
            id: 'minute',
            y: now.minutes,
            dial: {
                baseLength: '95%',
                rearLength: 0
            }
        }, {
            id: 'second',
            y: now.seconds,
            dial: {
                radius: '100%',
                baseWidth: 1,
                rearLength: '20%'
            }
        }],
        animation: false,
        dataLabels: {
            enabled: false
        }
    }]
},

// Move
function (chart) {
    setInterval(function () {

        now = getNow();

        if (chart.axes) { // not destroyed
            var hour = chart.get('hour'),
                minute = chart.get('minute'),
                second = chart.get('second'),
                // run animation unless we're wrapping around from 59 to 0
                animation = now.seconds === 0 ?
                    false : {
                        easing: 'easeOutBounce'
                    };

            // Cache the tooltip text
            chart.tooltipText =
                    pad(Math.floor(now.hours), 2) + ':' +
                    pad(Math.floor(now.minutes * 5), 2) + ':' +
                    pad(now.seconds * 5, 2);


            hour.update(now.hours, true, animation);
            minute.update(now.minutes, true, animation);
            second.update(now.seconds, true, animation);
        }

    }, 1000);

});

/**
 * Easing function from https://github.com/danro/easing-js/blob/master/easing.js
 */
Math.easeOutBounce = function (pos) {
    if ((pos) < (1 / 2.75)) {
        return (7.5625 * pos * pos);
    }
    if (pos < (2 / 2.75)) {
        return (7.5625 * (pos -= (1.5 / 2.75)) * pos + 0.75);
    }
    if (pos < (2.5 / 2.75)) {
        return (7.5625 * (pos -= (2.25 / 2.75)) * pos + 0.9375);
    }
    return (7.5625 * (pos -= (2.625 / 2.75)) * pos + 0.984375);
};`
Highcharts R-HighCharter

评论

1赞 T.J. Crowder 11/5/2022
请不要标记不相关的技术。仅仅因为你是从 JavaScript 开始的,这并不意味着召集 JavaScript 专家会帮助你解决这个 R 问题。

答:

0赞 Kat 11/6/2022 #1

这会将该 JS 转换为 R/JS(您需要在 Javascript 中收集时间)。当它运行时,我注意到 RStudio 的查看器窗格中有奇怪的垂直线,但这些线没有出现在我的浏览器中。

对于 JS 中的大多数调用,函数或参数在 R 中是相同的。我在 R 代码中使用了时间函数。(不过,你可以将时间设置为静态值,因为时间不受 R 代码控制。highcharterlubridate

创建图形后,我曾经添加动画,使其遵循实际时间。htmlwidgets::onRender

如果你在没有 的情况下运行它,这就是你将看到的。(好吧,在渲染它的那一刻,您会在时钟上看到当地时间的时间。htmlwidgets

enter image description here

library(highcharter)
library(lubridate)

highchart() %>%
  hc_chart(type = "gauge", plotBackgroundColor = NULL,
           plotBackgroundImage = NULL, plotBorderWidth = 0,
           plotShadow = F) %>%
  hc_pane(
    background = list(
      backgroundColor = list(
        radialGradient = list(cx = .5, cy = -.4, r = 1.9),
        stops = list(
          list(.5, "rgba(255, 255, 255, .2)"),
          list(.5, "rgba(200, 200, 200, .2)"))
      ))) %>%
  hc_tooltip(enabled = FALSE) %>% 
  hc_yAxis(
    labels = list(distance = -20),
    min = 0, max = 12, lineWidth = 0, showFirstLabel = F,
    minorTickInterval = "auto", minorTickWidth = 1,
    minorTickColor = "#666", tickColor = "#666",
    minorTickPosition = "inside", minorGridLineWidth = 0,
    tickInterval = 1, tickWidth = 2, tickPosition = "inside",
    tickLength = 10) %>%
  hc_add_series(
    data = list(
      list(id = "hour", y = hour(now()), dial = list(
        radius = "60%", baseWidth = 4, baseLength = "95%", rearLength = 0)),
      list(id = "minute", y = minute(now()), dial = list(
        baseLength = "95%", rearLength = 0)),
      list(id = "second", y = second(now()), dial = list(
        radius = "100%", baseWidth = 1, rearLength = "20%"))),
    dataLabels = list(enabled = F)) %>% 
  htmlwidgets::onRender("
        function(el, x) {
        chart = $('#' + el.id).highcharts()
        $.extend($.easing, {
          easeOutElastic: function (x, t, b, c, d) {
              var s = 1.70158; var p = 0; var a = c;
              if (t == 0) return b;  if ((t /= d) == 1) return b+c;  
              if (!p) p = d*.3;
              if (a < Math.abs(c)) { a = c; var s = p/4; }
              else var s = p/(2 * Math.PI) * Math.asin (c/a);
              return a * Math.pow(2, -10 * t) * Math.sin( (t * d - s) * (2 * Math.PI)/p) + c + b;
          }
        });
        function getNow () {
          var now = new Date();
          return {
              hours: now.getHours() + now.getMinutes() / 60,
              minutes: now.getMinutes() * 12 / 60 + now.getSeconds() * 12 / 3600,
              seconds: now.getSeconds() * 12 / 60
            };
        };
        setInterval(function () {
            var hour = chart.get('hour'),
                minute = chart.get('minute'),
                second = chart.get('second'),
                now = getNow(),
                /* run animation unless we're wrapping around from 59 to 0 */
                animation = now.seconds == 0 ? 
                    false : {easing: 'easeOutElastic'};
            hour.update(now.hours, true, animation);
            minute.update(now.minutes, true, animation);
            second.update(now.seconds, true, animation);
        }, 1000);
        }")

在这个 JS 中,你会看到一些与原始代码的偏差。我需要定义“图表”。我使用用于将任何 R 对象更改为其 HTML 呈现的相同机制来做到这一点:.由于设置间隔的函数最初是创建图形的一部分,因此它是一个未命名的函数。由于我们在渲染图形后调用,因此我删除了外部 .highcharterchart = $('#' + el.id).highcharts()function(chart)