我很快就尝试根据jQuery knob library创建一个闪亮的旋钮自定义输入小部件。此外,我还根据我的具体情况调整了Rstudio tutorial。 这就是我得到的here。
更改输入的唯一方法是在旋钮文本输入区输入其值。但是,我希望在向上或向下滚动以及使用鼠标拖动时更改此输入。如何修改代码以实现此目标?
以下是js代码:
旋钮input.R
# This function generates the client-side HTML for a knob input
knobInput <- function(inputId, label, value = NULL, min = 0, max = 100,
angleArc = 360, angleOffset = 0, stopper = TRUE,
rotation = "clockwise", skin = "tron") {
tagList(
# This makes web page load the JS file in the HTML head.
# The call to singleton ensures it's only included once
# in a page.
shiny::singleton(
shiny::tags$head(
shiny::tags$script(src = "jquery.knob.js"),
shiny::tags$script(src = "knob-input-binding.js")
)
),
shiny::tags$label(label, `for` = inputId),
shiny::tags$input(id = inputId, type = "text", value = value, class = "dial",
"data-value" = value,
"data-min" = min,
"data-max" = max,
"data-angleArc" = angleArc,
"data-angleOffset" = angleOffset,
"data-stopper" = stopper,
"data-rotation" = rotation,
"data-skin" = skin
)
)
}
# Send an update message to a knob input on the client.
# This update message can change the value and/or label.
updateknobInput <- function(session, inputId,
label = NULL, value = NULL) {
message <- dropNulls(list(label = label, value = value))
session$sendInputMessage(inputId, message)
}
# Given a vector or list, drop all the NULL items in it
dropNulls <- function(x) {
x[!vapply(x, is.null, FUN.VALUE = logical(1))]
}
旋钮输入binding.js
// Knob input binding
var knobInputBinding = new Shiny.InputBinding();
// An input binding must implement these methods
$.extend(knobInputBinding, {
// This returns a jQuery object with the DOM element
find: function(scope) {
return $(scope).find('.dial');
},
// this method will be called on initialisation
initialize: function(el){
// extract the value from el
// note here our knobInput does not yet exist
var value = $(el).data("value");
// initialize our knob based on the extracted state
el.value = value;
},
// Given the DOM element for the input, return the value
getValue: function(el) {
return el.value;
},
// Set up the event listeners so that interactions with the
// input will result in data being sent to server.
// callback is a function that queues data to be sent to
// the server.
subscribe: function(el, callback) {
$(el).on('keyup.knobInputBinding', function(event) {
callback(true);
// When called with true, it will use the rate policy,
// which in this case is to debounce at 500ms.
});
$(el).on('change.knobInputBinding', function(event) {
callback(false);
// When called with false, it will NOT use the rate policy,
// so changes will be sent immediately
});
},
// Remove the event listeners
unsubscribe: function(el) {
$(el).off('.knobInputBinding');
},
// Receive messages from the server.
// Messages sent by updateknobInput() are received by this function.
receiveMessage: function(el, data) {
if (data.hasOwnProperty('value'))
this.initialize(el, data.value);
if (data.hasOwnProperty('label'))
$(el).parent().find('label[for="' + $escape(el.id) + '"]').text(data.label);
$(el).trigger('change');
},
// This returns a full description of the input's state.
// Note that some inputs may be too complex for a full description of the
// state to be feasible.
getState: function(el) {
return {
label: $(el).parent().find('label[for="' + $escape(el.id) + '"]').text(),
value: el.value
};
},
// The input rate limiting policy
getRatePolicy: function() {
return {
// Can be 'debounce' or 'throttle'
policy: 'debounce',
delay: 500
};
}
});
Shiny.inputBindings.register(knobInputBinding, 'shiny.knobInput');
基本-knob.js
$(function($) {
$(".dial").knob();
});
(如果第三个代码段不存在,则无法正确呈现旋钮。)
编辑:这是单个文件,shinyapp代码
library(purrr)
source("knob-input.R")
ui <- fluidPage(
titlePanel("Custom input example"),
includeScript("www/basic-knob.js"),
fluidRow(
column(4, wellPanel(
knobInput("knobval", "", value = 10),
knobInput("knobval2", "", value = 20),
actionButton("reset", "Reset Knob")
)),
column(8, wellPanel(
verbatimTextOutput("value")
))
)
)
server <- function(input, output, session) {
output$value <- renderText({
c(input$knobval, input$knobval2)
})
observe({
# Run whenever reset button is pressed
input$reset
knobvec <- c("knobval", "knobval2")
# Send an update to knobs, resetting their values
map(knobvec, updateknobInput, session = session, value = 0)
})
}
shinyApp(ui = ui, server = server)
我的第二个问题是:我怎样才能改变使用的皮肤?例如,我想使用data-skin="tron"
,例如in the jQuery knob showcase。
非常感谢提前。
答案 0 :(得分:2)
旋钮有一种特殊的方式来处理事件,触发更改你可以在你的订阅方法中添加这段代码:
$(el).trigger('configure', {
'change': function (v) {
callback(false);
}
});
编辑:没有真正的“tron”皮肤,这是在初始化时在draw参数中手动实现的,您可以使用以下方式更改basic-knob.js
文件:
$(function($) {
$(".dial").knob({
draw: function() {
// "tron" case
if (this.$.data('skin') == 'tron') {
this.cursorExt = 0.3;
var a = this.arc(this.cv) // Arc
,
pa // Previous arc
, r = 1;
this.g.lineWidth = this.lineWidth;
if (this.o.displayPrevious) {
pa = this.arc(this.v);
this.g.beginPath();
this.g.strokeStyle = this.pColor;
this.g.arc(this.xy, this.xy, this.radius - this.lineWidth, pa.s, pa.e, pa.d);
this.g.stroke();
}
this.g.beginPath();
this.g.strokeStyle = r ? this.o.fgColor : this.fgColor;
this.g.arc(this.xy, this.xy, this.radius - this.lineWidth, a.s, a.e, a.d);
this.g.stroke();
this.g.lineWidth = 2;
this.g.beginPath();
this.g.strokeStyle = this.o.fgColor;
this.g.arc(this.xy, this.xy, this.radius - this.lineWidth + 1 + this.lineWidth * 2 / 3, 0, 2 * Math.PI, false);
this.g.stroke();
return false;
}
}
});
});