@@ -44,20 +44,13 @@ class DraggableGroup extends Group {
4444 };
4545
4646 /**
47- * Function to create a [DragImage] for this draggable. Default function
48- * returns null.
47+ * Function to create a [DragImage] for this draggable. If null is returned
48+ * from the function (the default), the browser's drag image is used instead.
4949 */
5050 DragImageFunction dragImageFunction = (Element draggable) {
5151 return null ;
5252 };
5353
54- /**
55- * If set to true, a custom drag image is drawn even if the browser supports
56- * the setting a custom drag image. The polyfill is a bit slower but allows
57- * opacity settings on [DragImage] to have an effect.
58- */
59- bool alwaysUseDragImagePolyfill = false ;
60-
6154 // -------------------
6255 // Draggable Events
6356 // -------------------
@@ -205,16 +198,38 @@ class DraggableGroup extends Group {
205198
206199 dragImage = dragImageFunction (element);
207200 if (dragImage != null ) {
208- if (alwaysUseDragImagePolyfill || ! html5.supportsSetDragImage) {
201+ if (html5.supportsSetDragImage) {
202+ mouseEvent.dataTransfer.setDragImage (dragImage.element, dragImage.x,
203+ dragImage.y);
204+ } else {
209205 usingDragImagePolyfill = true ;
210206 // Install the polyfill.
211207 polyfillDragOverSubscription = _polyfillSetDragImage (element,
212208 mouseEvent, dragImage);
213-
209+ }
210+ } else if (! html5.supportsDraggable) {
211+ // Browser does not create a drag image by default --> polyfill it.
212+ _logger.finest ('Manually creating drag image from current drag element.' );
213+ usingDragImagePolyfill = true ;
214+
215+ // Install the polyfill with a clone of the current drag element as drag image.
216+ if (element is ImageElement ) {
217+ // Calc the mouse position relative to the draggable.
218+ num mouseRelativeLeft = mouseEvent.page.x - css.getLeftOffset (element);
219+ num mouseRelativeTop = mouseEvent.page.y - css.getTopOffset (element);
220+ dragImage = new DragImage (new ImageElement (src: element.src,
221+ width: element.width, height: element.height),
222+ mouseRelativeLeft.round (), mouseRelativeTop.round ());
214223 } else {
215- mouseEvent.dataTransfer.setDragImage (dragImage.image, dragImage.x,
216- dragImage.y);
224+ // Not an image --> Make sure mouse is outside of drag image.
225+ Element clone = element.clone (true );
226+ clone.attributes.remove ('id' );
227+ clone.style.width = element.getComputedStyle ().width;
228+ clone.style.height = element.getComputedStyle ().height;
229+ dragImage = new DragImage (clone, 0 , - 5 );
217230 }
231+ polyfillDragOverSubscription = _polyfillSetDragImage (element,
232+ mouseEvent, dragImage);
218233 }
219234
220235 if (_onDragStart != null ) {
@@ -305,10 +320,11 @@ class DraggableGroup extends Group {
305320 */
306321 StreamSubscription _polyfillSetDragImage (Element element, MouseEvent mouseEvent,
307322 DragImage dragImage) {
323+ _logger.finest ('Polyfilling setDragImage function.' );
308324 _preventDefaultDragImage (element, mouseEvent);
309325
310326 // Manually add the drag image polyfill with absolute position.
311- document.body .children.add (dragImage.polyfill);
327+ element.parent .children.add (dragImage.polyfill);
312328 dragImage.polyfill.style.position = 'absolute' ;
313329 dragImage.polyfill.style.visibility = 'hidden' ;
314330
@@ -332,10 +348,10 @@ class DraggableGroup extends Group {
332348 // Set drag image to
333349 mouseEvent.dataTransfer.setDragImage (
334350 new ImageElement (src: DragImage .EMPTY ), 0 , 0 );
335- } else {
351+ } else if (html5.supportsDraggable) {
336352 // To force the browser not to display the default drag image, which is the
337353 // html element beeing dragged, we must set display to 'none'. Visibility
338- // 'hidden' won't work (IE drags a white box). To still keep the space
354+ // 'hidden' won't work (IE10 drags a white box). To still keep the space
339355 // of the display='none' element, we create a clone as a temporary
340356 // replacement.
341357 Element tempReplacement = element.clone (true );
@@ -368,14 +384,21 @@ class DraggableEvent {
368384}
369385
370386/**
371- * A drag feedback [image] element. The [x] and [y] define where the image
372- * should appear relative to the mouse cursor.
387+ * A drag feedback image. The [x] and [y] define where the drag image should
388+ * appear relative to the mouse cursor.
389+ *
390+ * The drag image [element] can be an HTML img element, an HTML canvas element
391+ * or any visible HTML node on the page.
392+ *
393+ * **Important:** In IE9 and IE10, mouse events can only be passed through
394+ * [ImageElement] s. If another HTML element is provided, the mouse must be
395+ * positioned outside of the drag image with [x] and [y] .
373396 */
374397class DragImage {
375398 /// A small transparent gif.
376399 static const String EMPTY = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' ;
377400
378- final ImageElement image ;
401+ final Element element ;
379402 final int x;
380403 final int y;
381404
@@ -384,7 +407,7 @@ class DragImage {
384407
385408 Element _polyfill;
386409
387- DragImage (this .image , this .x, this .y);
410+ DragImage (this .element , this .x, this .y);
388411
389412 /**
390413 * Returns the element that is used for the polyfill drag image.
@@ -399,37 +422,40 @@ class DragImage {
399422 if (_polyfill == null ) {
400423 // Make sure that mouse events are forwarded to the layer below.
401424 if (html5.supportsPointerEvents) {
402- _polyfill = image;
403- } else {
425+ _polyfill = element;
426+ _polyfill.style.pointerEvents = 'none' ;
427+ } else if (element is ImageElement ) {
404428 // IE9 and IE10 support pointer-events on SVGs only.
405- _polyfill = _createSvgElement ();
429+ _polyfill = _createSvgFromImage (element as ImageElement );
430+ _polyfill.style.pointerEvents = 'none' ;
431+ } else {
432+ // No support for pointer-events.
433+ _logger.finest ('pointer-events not supported: mouse must be outside of drag image.' );
434+ _polyfill = element;
406435 }
407- _polyfill.style.pointerEvents = 'none' ;
408436
409437 // Add some transparency.
410438 _polyfill.style.opacity = polyfillOpacity;
411439 }
412440 return _polyfill;
413441 }
414442
415-
416443 /**
417444 * Creates an SVG tag containing the [image] .
418445 */
419- Element _createSvgElement ( ) {
446+ Element _createSvgFromImage ( ImageElement image ) {
420447 return new svg.SvgElement .svg ("""
421448 <svg xmlns="http://www.w3.org/2000/svg"
422449 xmlns:xlink="http://www.w3.org/1999/xlink"
423-
424450 width="${image .width }"
425451 height="${image .height }">
426452 <image xlink:href="${image .src }"
427- x="0"
428- y="0"
429- width="${image .width }"
430- height="${image .height }"
431- />
453+ x="0"
454+ y="0"
455+ width="${image .width }"
456+ height="${image .height }"
457+ />
432458 </svg>
433459 """ );
434- }
460+ }
435461}
0 commit comments