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:
Barret Schloerke
2018-09-26 13:29:42 -04:00
committed by GitHub
parent 37736119be
commit 1d0edd2ad0
5 changed files with 149 additions and 122 deletions

View File

@@ -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);