mirror of
https://github.com/rstudio/shiny.git
synced 2026-02-08 13:45:28 -05:00
Initialize brush dims for renderImage objects (#2198)
* wait for image to be loaded in browser before initializing handlers
reverts similar behavior in 3354a47e8a
* default the height and width to the image clientHeight and clientWidth
* use raw image clientWidth and clientHeight instead of container clientWidth and clientHeight
prevents being able to brush on non image areas
This commit is contained in:
@@ -104,79 +104,89 @@ $.extend(imageOutputBinding, {
|
||||
$el.off('.image_output');
|
||||
$img.off('.image_output');
|
||||
|
||||
imageutils.initCoordmap($el, opts.coordmap);
|
||||
// When the image loads, initialize all the interaction handlers. When the
|
||||
// value of src is set, the browser may not load the image immediately,
|
||||
// even if it's a data URL. If we try to initialize this stuff
|
||||
// immediately, it can cause problems because we use we need the raw image
|
||||
// height and width
|
||||
$img.off("load.shiny-image-interaction");
|
||||
$img.on("load.shiny-image-interaction", function() {
|
||||
|
||||
// This object listens for mousedowns, and triggers mousedown2 and dblclick2
|
||||
// events as appropriate.
|
||||
var clickInfo = imageutils.createClickInfo($el, opts.dblclickId, opts.dblclickDelay);
|
||||
imageutils.initCoordmap($el, opts.coordmap);
|
||||
|
||||
$el.on('mousedown.image_output', clickInfo.mousedown);
|
||||
// This object listens for mousedowns, and triggers mousedown2 and dblclick2
|
||||
// events as appropriate.
|
||||
var clickInfo = imageutils.createClickInfo($el, opts.dblclickId, opts.dblclickDelay);
|
||||
|
||||
if (browser.isIE && browser.IEVersion === 8) {
|
||||
$el.on('dblclick.image_output', clickInfo.dblclickIE8);
|
||||
}
|
||||
$el.on('mousedown.image_output', clickInfo.mousedown);
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Register the various event handlers
|
||||
// ----------------------------------------------------------
|
||||
if (opts.clickId) {
|
||||
var clickHandler = imageutils.createClickHandler(opts.clickId,
|
||||
opts.clickClip, opts.coordmap);
|
||||
$el.on('mousedown2.image_output', clickHandler.mousedown);
|
||||
if (browser.isIE && browser.IEVersion === 8) {
|
||||
$el.on('dblclick.image_output', clickInfo.dblclickIE8);
|
||||
}
|
||||
|
||||
$el.on('resize.image_output', clickHandler.onResize);
|
||||
// ----------------------------------------------------------
|
||||
// Register the various event handlers
|
||||
// ----------------------------------------------------------
|
||||
if (opts.clickId) {
|
||||
var clickHandler = imageutils.createClickHandler(opts.clickId,
|
||||
opts.clickClip, opts.coordmap);
|
||||
$el.on('mousedown2.image_output', clickHandler.mousedown);
|
||||
|
||||
// When img is reset, do housekeeping: clear $el's mouse listener and
|
||||
// call the handler's onResetImg callback.
|
||||
$img.on('reset.image_output', clickHandler.onResetImg);
|
||||
}
|
||||
$el.on('resize.image_output', clickHandler.onResize);
|
||||
|
||||
if (opts.dblclickId) {
|
||||
// We'll use the clickHandler's mousedown function, but register it to
|
||||
// our custom 'dblclick2' event.
|
||||
var dblclickHandler = imageutils.createClickHandler(opts.dblclickId,
|
||||
opts.clickClip, opts.coordmap);
|
||||
$el.on('dblclick2.image_output', dblclickHandler.mousedown);
|
||||
// When img is reset, do housekeeping: clear $el's mouse listener and
|
||||
// call the handler's onResetImg callback.
|
||||
$img.on('reset.image_output', clickHandler.onResetImg);
|
||||
}
|
||||
|
||||
$el.on('resize.image_output', dblclickHandler.onResize);
|
||||
$img.on('reset.image_output', dblclickHandler.onResetImg);
|
||||
}
|
||||
if (opts.dblclickId) {
|
||||
// We'll use the clickHandler's mousedown function, but register it to
|
||||
// our custom 'dblclick2' event.
|
||||
var dblclickHandler = imageutils.createClickHandler(opts.dblclickId,
|
||||
opts.clickClip, opts.coordmap);
|
||||
$el.on('dblclick2.image_output', dblclickHandler.mousedown);
|
||||
|
||||
if (opts.hoverId) {
|
||||
var hoverHandler = imageutils.createHoverHandler(opts.hoverId,
|
||||
opts.hoverDelay, opts.hoverDelayType, opts.hoverClip,
|
||||
opts.hoverNullOutside, opts.coordmap);
|
||||
$el.on('mousemove.image_output', hoverHandler.mousemove);
|
||||
$el.on('mouseout.image_output', hoverHandler.mouseout);
|
||||
$el.on('resize.image_output', dblclickHandler.onResize);
|
||||
$img.on('reset.image_output', dblclickHandler.onResetImg);
|
||||
}
|
||||
|
||||
$el.on('resize.image_output', hoverHandler.onResize);
|
||||
$img.on('reset.image_output', hoverHandler.onResetImg);
|
||||
}
|
||||
if (opts.hoverId) {
|
||||
var hoverHandler = imageutils.createHoverHandler(opts.hoverId,
|
||||
opts.hoverDelay, opts.hoverDelayType, opts.hoverClip,
|
||||
opts.hoverNullOutside, opts.coordmap);
|
||||
$el.on('mousemove.image_output', hoverHandler.mousemove);
|
||||
$el.on('mouseout.image_output', hoverHandler.mouseout);
|
||||
|
||||
if (opts.brushId) {
|
||||
// Make image non-draggable (Chrome, Safari)
|
||||
$img.css('-webkit-user-drag', 'none');
|
||||
// Firefox, IE<=10
|
||||
$img.on('dragstart', function() { return false; });
|
||||
$el.on('resize.image_output', hoverHandler.onResize);
|
||||
$img.on('reset.image_output', hoverHandler.onResetImg);
|
||||
}
|
||||
|
||||
// Disable selection of image and text when dragging in IE<=10
|
||||
$el.on('selectstart.image_output', function() { return false; });
|
||||
if (opts.brushId) {
|
||||
// Make image non-draggable (Chrome, Safari)
|
||||
$img.css('-webkit-user-drag', 'none');
|
||||
// Firefox, IE<=10
|
||||
$img.on('dragstart', function() { return false; });
|
||||
|
||||
var brushHandler = imageutils.createBrushHandler(opts.brushId, $el, opts,
|
||||
opts.coordmap, outputId);
|
||||
$el.on('mousedown.image_output', brushHandler.mousedown);
|
||||
$el.on('mousemove.image_output', brushHandler.mousemove);
|
||||
// Disable selection of image and text when dragging in IE<=10
|
||||
$el.on('selectstart.image_output', function() { return false; });
|
||||
|
||||
$el.on('resize.image_output', brushHandler.onResize);
|
||||
$img.on('reset.image_output', brushHandler.onResetImg);
|
||||
}
|
||||
var brushHandler = imageutils.createBrushHandler(opts.brushId, $el, opts,
|
||||
opts.coordmap, outputId);
|
||||
$el.on('mousedown.image_output', brushHandler.mousedown);
|
||||
$el.on('mousemove.image_output', brushHandler.mousemove);
|
||||
|
||||
if (opts.clickId || opts.dblclickId || opts.hoverId || opts.brushId) {
|
||||
$el.addClass('crosshair');
|
||||
}
|
||||
$el.on('resize.image_output', brushHandler.onResize);
|
||||
$img.on('reset.image_output', brushHandler.onResetImg);
|
||||
}
|
||||
|
||||
if (data.error)
|
||||
console.log('Error on server extracting coordmap: ' + data.error);
|
||||
if (opts.clickId || opts.dblclickId || opts.hoverId || opts.brushId) {
|
||||
$el.addClass('crosshair');
|
||||
}
|
||||
|
||||
if (data.error)
|
||||
console.log('Error on server extracting coordmap: ' + data.error);
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
renderError: function(el, err) {
|
||||
@@ -333,8 +343,8 @@ imageutils.initPanelScales = function(panels) {
|
||||
// 3. data: The coordinates in the data space. This is a bit more complicated
|
||||
// than the other two, because there can be multiple panels (as in facets).
|
||||
imageutils.initCoordmap = function($el, coordmap) {
|
||||
const el = $el[0];
|
||||
const $img = $el.find("img");
|
||||
const img = $img[0];
|
||||
|
||||
// If we didn't get any panels, create a dummy one where the domain and range
|
||||
// are simply the pixel dimensions.
|
||||
@@ -343,8 +353,8 @@ imageutils.initCoordmap = function($el, coordmap) {
|
||||
let bounds = {
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: el.clientWidth - 1,
|
||||
bottom: el.clientHeight - 1
|
||||
right: img.clientWidth - 1,
|
||||
bottom: img.clientHeight - 1
|
||||
};
|
||||
|
||||
coordmap.panels[0] = {
|
||||
@@ -354,6 +364,10 @@ imageutils.initCoordmap = function($el, coordmap) {
|
||||
};
|
||||
}
|
||||
|
||||
// if no dim height and width values are found, set them to the image height and width
|
||||
coordmap.dims.height = coordmap.dims.height || img.clientHeight;
|
||||
coordmap.dims.width = coordmap.dims.width || img.clientWidth;
|
||||
|
||||
// Add scaling functions to each panel
|
||||
imageutils.initPanelScales(coordmap.panels);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user