当屏幕上显示夸托幻灯片时,使用echarts4r制作绘图动画

ffscu2ro  于 2022-12-20  发布在  Echarts
关注(0)|答案(1)|浏览(154)

我正在R Studio中使用夸托制作Revealjs演示文稿。我正在使用{echarts4r}包制作绘图。{echarts4r}附带默认动画。当我渲染演示文稿时,默认动画已经为所有幻灯片加载。
我想在幻灯片处于活动状态时(即幻灯片在视图中时)运行默认echarts4r动画,并在其他幻灯片在视图中时重置。有人能帮我吗?
下面是夸托演示文稿的代码。

---
title: "A Title"
subtitle: "A Subtitle"
author: "First Last"
institute: "Some Institute"
date: today
self-contained: true
format: revealjs
---

## Introduction

Hello There!

## Pie Chart

```{r}
library(tidyverse)
library(echarts4r)

data <- tibble(name = c("A", "B", "C", "D", "E", "F", "G"),
             number = c(9.7, 2.1, 2.1, 1.9, 1.9, 1.9, 80.4))

data %>% 
e_charts(name) %>% 
e_pie(number, radius = c("50%", "70%")) %>% 
e_legend(orient = "vertical", right = "5", top = "65%")
d8tt03nd

d8tt03nd1#

这不是一个修复或Quarto方法。然而,这个变通方案是动态的。由于@bretauv的注解,我计算出了echarts4rhighcharter需要发生什么。

分配元素ID

对图表唯一需要更改的是,您需要为它们提供一个元素ID。ID在整个演示文稿中必须是唯一的。使用诸如"ec0"、"ec1"等作为绘图的ID是完全可以的。(您只需要对动画绘图执行此操作。)
这里有一个例子。

```{r pltEchart, echo=F} 

iris |> group_by(Species) |> 
  e_charts(Sepal.Length, elementId = "pltEcht") |>  # <--- id is here
  e_scatter(Sepal.Width) 

对于`highcharter`和大多数其他小部件样式包,添加元素id不是内置的。下面是为`highcharter`添加id的方法。

hc <- hchart(penguins, "scatter", 
             hcaes(x = flipper_length_mm, y = bill_length_mm, group = species))

hc$elementId <- "hc_id"

hc

#### 重新设置图的动画

对于每个`echarts4r`图,要应用下一部分,您需要**幻灯片**和**元素ID**。
对于`highcharter`,您还需要知道它在演示文稿中出现的顺序(仅在其他`highcharter`图中)。
无论您使用较少动态的方法还是较多动态的方法,剩下的工作就是向QMD添加一个JS块,这个块可以放在脚本文件的任何地方(我通常将任何JS放在我的RMD/QMD的末尾)。
如果你不知道,JS是内置的。你不需要做任何新的或不同的事情来使用JS这种方式。但是,如果你要运行这个块在源代码窗格,它不会做任何事情。你必须呈现它看到它的行动。如果你结束了改变JS或写更多自己的,不要假设您在RStudio查看器或演示窗格中看到的内容与您在浏览器中看到的内容完全相同。
在你决定之前,我会略读一下你必须为这两种方法做些什么改变!如果你不习惯使用JS,第二种方法绝对是你最好的选择。

##### 每个重新动画图的每个演示的自定义信息

对于重新设置动画的每个图,必须确定:
1. a * 幻灯片标题的子字符串 * 或幻灯片编号(其中幻灯片编号通过YAML声明包含在幻灯片中)
1.* 绘图元素ID *
1.* 绘图顺序 *(绘图顺序或序列仅适用于Highcharts)。
对于**幻灯片标题子字符串**,如您在JS:

* 它是基于在后台分配的哈希或锚点的标题的子字符串
* 子字符串全部小写
* 无特殊字符
* 对于该幻灯片必须是唯一的

如果您不确定要使用什么或如何找到独特之处,有一种简单的方法可以找到这些信息。如果您在浏览器中从RStudio的演示文稿窗格打开演示文稿,幻灯片的URL将类似于下图。
每张幻灯片都将具有相同的URL初始组件`http://localhost:7287/#/`,但除此之外,每张幻灯片都将是"唯一的"。

http://localhost:7287/#/another-hc


# 后面的字符串是该幻灯片的标题锚点。您可以使用URL中(#/后面)的内容。

#### 把它放在一起

此操作将持续检查幻灯片是否已更改(10毫秒间隔)。如果幻灯片发生更改,则会检查三个图中是否有一个在该幻灯片上。如果是,则重新启动幻灯片动画。

##### 您需要在JS中进行个性化设置的内容

`charts4r`的`ecReloader`有两个参数:
1.标题子字符串或幻灯片编号
1.绘图元素ID
`highcharter`的`hcReloader`有3个参数:
1.标题子字符串或幻灯片编号
1.绘图元素ID
1.地块顺序号
在`setInterval`函数(块名为`customizeMe`)中,您需要为要重新动画的每个图编写一个函数调用。在我的示例中,我重新动画了三个图。**这是您修改的唯一部分。**(注意,每行都需要以分号结尾。)
一个三个三个一个
在你的演示中,你需要同时使用两个JS块(块名是`customizeMe`和`reloaders`)。
我确信有一种方法可以自定义幻灯片编号的外观;但是,此代码基于默认值。
这里的所有JS使这工作。

     /* assuming only one on slide */
setInterval(function() { 
  var current = window.location.hash;
  tellMe = keepLooking(current);
  if(tellMe) {                        /* if the slide changed, then look */
  ecReloader('code', 'pltEcht');
  hcReloader('highchart', 'hc_id', 0);
  hcReloader(6, 'another_hc_id', 1);    /* second highcharter plot */
  }
}, 10); // check every 10 milliseconds

// more dynamic; a couple of key words for each plot

// multiple options for addressing Echarts plots
function ecReloader(slide, id) {
  /* slide (string)  slide title unique substring (check URL when on the slide)
                --or-- 
           (integer) as in the slide number
     id (string)     element id of the plot to change */
  if(typeof slide === 'number') {                        // slide number provided
    which = document.querySelector('div.slide-number');  // page numbers like '6 / 10'
    validator = Number(which.innerText.split(' ')[0]);
    if(slide === validator) {                            // slide number matches current slide
      var ec = document.getElementById(id);
      ele = echarts.init(ec, get_e_charts_opts(ec.id));
      thatsIt = get_e_charts_opts(ec.id);          /* store data */
      ele.setOption({xAxis: {}, yAxis: {}}, true); /* remove data */
      ele.setOption(thatsIt, false);               /* append original data */
    }
  } else {                                               // unique element in slide title 
    if(window.location.hash.indexOf(slide) > -1) {
      var ec = document.getElementById(id);
      ele = echarts.init(ec, get_e_charts_opts(ec.id));
      thatsIt = get_e_charts_opts(ec.id);          /* store data */
      ele.setOption({xAxis: {}, yAxis: {}}, true); /* remove data */
      ele.setOption(thatsIt, false);               /* append original data */
    }
  }
}

// multiple options for addressing Highcharts plots, assumes 1 chart per slide!
function hcReloader(slide, id, order) {
  /* slide (string)  slide title unique substring (check URL when on the slide)
                --or-- 
           (integer) as in the slide number
     id (string)     element id of the plot to change
     order (integer) 0 through the number of charts in the plot, which one is this plot?
                  (in order of appearance) */
  if(typeof slide === 'number') {                        // slide number provided
    which = document.querySelector('div.slide-number');  // page numbers like '6 / 10'
    validator = Number(which.innerText.split(' ')[0]);
    if(slide === validator) {                            // slide number matches current slide
      var hc1 = document.getElementById(id).firstChild;  
      Highcharts.chart(hc1, Highcharts.charts[order].options); // re-draw plot
    }
  } else {                                               // unique element in slide title
    if(window.location.hash.indexOf(slide) > -1) {
      var hc1 = document.getElementById(id).firstChild;
      Highcharts.chart(hc1, Highcharts.charts[order].options); // re-draw plot
    }
  }
}

/* Current Slide Section (bookmark #) */
oHash = window.location.hash;

/* check if the slide has changed */
function keepLooking (nHash) { 
  if(oHash === nHash) {
    return false;
  } else {
    oHash = nHash;          /* if slide changed, reset the value of oHash */
    return true;
  }
}

下面是我用来创建和测试它的整个QMD脚本,以便您可以看到它是如何工作的。

title: "Untitled"
format:
revealjs:
slide-number: true
editor: source

Quarto

library(echarts4r)
library(tidyverse)
library(htmltools)
library(highcharter)

data("iris")
data(penguins, package = "palmerpenguins") 

word

Bullets

more words

More Plots; How about Highcharter?


hc <- hchart(penguins, "scatter", 
             hcaes(x = flipper_length_mm, y = bill_length_mm, group = species))

hc$elementId <- "hc_id"

hc

Code

echarts style plot


iris |> group_by(Species) |> 
  e_charts(Sepal.Length, elementId = "pltEcht") |> e_scatter(Sepal.Width) 

Another HC


hc2 <- hchart(iris, "scatter",
              hcaes(x = Sepal.Length, y = Sepal.Width, group = Species))

hc2$elementId <- "another_hc_id"

hc2

     /* assuming only one on slide */
setInterval(function() { 
  var current = window.location.hash;
  tellMe = keepLooking(current);
  if(tellMe) {                        /* if the slide changed, then look */
  ecReloader('code', 'pltEcht');
  hcReloader('highchart', 'hc_id', 0);
  hcReloader(6, 'another_hc_id', 1);    /* second highcharter plot */
  }
}, 10); // check every 10 milliseconds

// more dynamic; a couple of key words for each plot

// multiple options for addressing Echarts plots
function ecReloader(slide, id) {
  /* slide (string)  slide title unique substring (check URL when on the slide)
                --or-- 
           (integer) as in the slide number
     id (string)     element id of the plot to change */
  if(typeof slide === 'number') {                        // slide number provided
    which = document.querySelector('div.slide-number');  // page numbers like '6 / 10'
    validator = Number(which.innerText.split(' ')[0]);
    if(slide === validator) {                            // slide number matches current slide
      var ec = document.getElementById(id);
      ele = echarts.init(ec, get_e_charts_opts(ec.id));
      thatsIt = get_e_charts_opts(ec.id);          /* store data */
      ele.setOption({xAxis: {}, yAxis: {}}, true); /* remove data */
      ele.setOption(thatsIt, false);               /* append original data */
    }
  } else {                                               // unique element in slide title 
    if(window.location.hash.indexOf(slide) > -1) {
      var ec = document.getElementById(id);
      ele = echarts.init(ec, get_e_charts_opts(ec.id));
      thatsIt = get_e_charts_opts(ec.id);          /* store data */
      ele.setOption({xAxis: {}, yAxis: {}}, true); /* remove data */
      ele.setOption(thatsIt, false);               /* append original data */
    }
  }
}

// multiple options for addressing Highcharts plots, assumes 1 chart per slide!
function hcReloader(slide, id, order) {
  /* slide (string)  slide title unique substring (check URL when on the slide)
                --or-- 
           (integer) as in the slide number
     id (string)     element id of the plot to change
     order (integer) 0 through the number of charts in the plot, which one is this plot?
                  (in order of appearance) */
  if(typeof slide === 'number') {                        // slide number provided
    which = document.querySelector('div.slide-number');  // page numbers like '6 / 10'
    validator = Number(which.innerText.split(' ')[0]);
    if(slide === validator) {                            // slide number matches current slide
      var hc1 = document.getElementById(id).firstChild;  
      Highcharts.chart(hc1, Highcharts.charts[order].options); // re-draw plot
    }
  } else {                                               // unique element in slide title
    if(window.location.hash.indexOf(slide) > -1) {
      var hc1 = document.getElementById(id).firstChild;
      Highcharts.chart(hc1, Highcharts.charts[order].options); // re-draw plot
    }
  }
}

/* Current Slide Section (bookmark #) */
oHash = window.location.hash;

/* check if the slide has changed */
function keepLooking (nHash) { 
  if(oHash === nHash) {
    return false;
  } else {
    oHash = nHash;          /* if slide changed, reset the value of oHash */
    return true;
  }
}

您可以将JS放在QMD中的任何位置。
如果你看到加载延迟( Flink 之类的),你可以降低间隔之间的毫秒数(这个数字在`setInterval`函数的末尾,你可以看到`}, 10)`。
如果出现问题,您可以将JS设置为`eval=F`。实际上,您并没有永久更改演示文稿中的任何内容。

相关问题