I am new to the world of combining Javascript with R and my Javascript knowledge is quite limited. I am trying to make a plotly
plot of chess openings and when you click on the opening it shows a board with the initial moves of the opening.
library(plotly)
library(htmlwidgets)
library(data.table)
library(rchess)
data("chessopenings")
setDT(chessopenings)
mychess = chessopenings[1:10]
mychess[, Pop := sample(c(1,2,4), nrow(mychess), replace = T)]
mychess[, fens := sapply(pgn, function(x) {chsspgn <- Chess$new(); chsspgn$load_pgn(x); chsspgn$fen()})]
The code above just creates a sample dataset of 10 openings. I then plot those using plotly and based on the guidance I found here https://plotly-r.com/supplying-custom-data.html#fig:hover-annotate I tried to create a new function that shows the chessboard when you click on the points. The chessboard function is the one specified here https://chessboardjs.com/examples#1002 and if I understand it correctly (please correct me if I am wrong) it returns a 'div' element which is the one I have to show.
q = plot_ly(mychess, x = ~eco, y = ~Pop) %>%
add_markers(text = ~name,
customdata = ~fens)
onRender(
q, "
function(el) {
el.on('plotly_click', function(d) {
var pt = d.points[0];
var fen = d.points[0].customdata
var newboard = Chessboard('myBoard', fen);
newboard.style.visibility = 'visible';
newboard.style.display = 'block';
})}")
Unfortunately nothing shows. I used the information provided here Show/hide 'div' using JavaScript but it seems I am missing something.
Update: I tried the suggestion by @Bas to convert the images by using the following code:
png(pic1 <- tempfile(fileext = ".png"));chessboardjs(fen = mychess$fens[1]); dev.off()
text = knitr::image_uri(pic1)
text = sub(".*?,", "", text)
html <- sprintf('<html><body><img src="data:image/png;base64,%s"></body></html>', text)
cat(html, file = tf2 <- tempfile(fileext = ".html"))
browseURL(tf2)
But this doesn't work either.
You have to include the Chessboard JavaScript and CSS-Files in order to use the Chessboard
function. The function will not create a div
but append the chessboard-visualization to a given CSS-selector. So the div
has to be created beforehand.
Shiny version:
library(plotly)
library(htmlwidgets)
library(data.table)
library(rchess)
library(shiny)
data("chessopenings")
setDT(chessopenings)
mychess = chessopenings[1:10]
mychess[, Pop := sample(c(1,2,4), nrow(mychess), replace = T)]
mychess[, fens := sapply(pgn, function(x) {chsspgn <- Chess$new();
chsspgn$load_pgn(x); chsspgn$fen()})]
ui <- fluidPage(
tags$head(tags$link(href = "https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css", rel = "stylesheet", type = "text/css")),
tags$head(tags$script(src = "https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.js")),
plotlyOutput("plt"),
div(id = "myBoard", style="width: 400px")
)
server <- function(input, output, session) {
output$plt <- renderPlotly({
q = plot_ly(mychess, x = ~eco, y = ~Pop) %>%
add_markers(text = ~name,
customdata = ~fens)
onRender(
q, "
function(el) {
el.on('plotly_click', function(d) {
var pt = d.points[0];
var fen = d.points[0].customdata;
var newboard = Chessboard('myBoard', fen);
})}")
})
}
shinyApp(ui, server)
To see the images of chess pieces you have the include them in the www/img/chesspieces/wikipedia/
folder of your Shiny App. Otherwise you will see some errors in the browser console.
GET http://127.0.0.1:5247/img/chesspieces/wikipedia/wK.png HTTP/1.1 404 Not Found 11ms
A Markdown version:
To see the chess positions you have to download the png files and put them in this folder structure /img/chesspieces/wikipedia/
based on where the .Rmd document is.
---
title: "Chess Openings"
output: html_document
---
<style type="text/css">
@import url("https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css");
</style>
<script src="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.js"></script>
```{r setup, include=FALSE}
library(plotly)
library(htmlwidgets)
library(data.table)
library(rchess)
library(shiny)
data("chessopenings")
setDT(chessopenings)
mychess = chessopenings[1:10]
mychess[, Pop := sample(c(1,2,4), nrow(mychess), replace = T)]
mychess[, fens := sapply(pgn, function(x) {chsspgn <- Chess$new();
chsspgn$load_pgn(x); chsspgn$fen()})]
```
```{r out.width='100%', echo=FALSE, warning = FALSE}
q = plot_ly(mychess, x = ~eco, y = ~Pop) %>%
add_markers(text = ~name,
customdata = ~fens)
onRender(
q, "
function(el) {
el.on('plotly_click', function(d) {
var pt = d.points[0];
var fen = d.points[0].customdata;
var newboard = Chessboard('myBoard', fen);
})}")
```
<div id="myBoard" style="width: 400px"></div>