diff --git a/src/components/stage/stage.css b/src/components/stage/stage.css
index dfce6ba24044ccbc6ff026947cd1ed3cbf3677b7..17c6e87b4b6504b6ebecfb621a8cc4f8378805d6 100644
--- a/src/components/stage/stage.css
+++ b/src/components/stage/stage.css
@@ -8,6 +8,10 @@
     */
     display: block;
 
+    /* Attach border radius directly to canvas to prevent needing overflow:hidden; */
+    border-radius: $space;
+    border: 1px solid $ui-black-transparent;
+
     /* @todo: This is for overriding the value being set somewhere. Where is it being set? */
     background-color: transparent;
 }
@@ -30,10 +34,6 @@
 
 .stage-wrapper {
     position: relative;
-    border-radius: $space;
-    border: 1px solid $ui-black-transparent;
-    /* Keep the canvas inside the border radius */
-    overflow: hidden;
 }
 
 .stage-wrapper-overlay {
@@ -78,3 +78,11 @@
     pointer-events: none;
     overflow: hidden;
 }
+
+.dragging-sprite {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 1000; /* Above everything so it is draggable into other panes */
+    filter: drop-shadow(5px 5px 5px $ui-black-transparent);
+ }
diff --git a/src/components/stage/stage.jsx b/src/components/stage/stage.jsx
index f79bd3d772709b59dd988c4fa16bd284b808e4d9..37f12706b0cc0de16bb334dc1fc7f8b8d6e8d5d4 100644
--- a/src/components/stage/stage.jsx
+++ b/src/components/stage/stage.jsx
@@ -12,6 +12,7 @@ import styles from './stage.css';
 const StageComponent = props => {
     const {
         canvasRef,
+        dragRef,
         height,
         isColorPicking,
         isFullScreen,
@@ -24,7 +25,7 @@ const StageComponent = props => {
     } = props;
 
     const stageSize = getStageSize(isFullScreen, height, width);
-    
+
     return (
         <div>
             <Box
@@ -71,6 +72,12 @@ const StageComponent = props => {
                         </div>
                     </div>
                 )}
+                <canvas
+                    className={styles.draggingSprite}
+                    height={0}
+                    ref={dragRef}
+                    width={0}
+                />
             </Box>
             {isColorPicking ? (
                 <Box
@@ -84,6 +91,7 @@ const StageComponent = props => {
 StageComponent.propTypes = {
     canvasRef: PropTypes.func,
     colorInfo: Loupe.propTypes.colorInfo,
+    dragRef: PropTypes.func,
     height: PropTypes.number,
     isColorPicking: PropTypes.bool,
     isFullScreen: PropTypes.bool.isRequired,
@@ -94,6 +102,7 @@ StageComponent.propTypes = {
 };
 StageComponent.defaultProps = {
     canvasRef: () => {},
+    dragRef: () => {},
     width: 480,
     height: 360
 };
diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx
index cf10d50019342bdf9942d36dfb580d7a6f6ff9f0..688951f73e858b61c583c624fe45d716df010fb4 100644
--- a/src/containers/stage.jsx
+++ b/src/containers/stage.jsx
@@ -34,7 +34,11 @@ class Stage extends React.Component {
             'onWheel',
             'updateRect',
             'questionListener',
-            'setCanvas'
+            'setCanvas',
+            'setDragCanvas',
+            'clearDragCanvas',
+            'drawDragCanvas',
+            'positionDragCanvas'
         ]);
         this.state = {
             mouseDownTimeoutId: null,
@@ -170,6 +174,7 @@ class Stage extends React.Component {
                 y: -(spritePosition[1] + this.state.dragOffset[1]),
                 force: true
             });
+            this.positionDragCanvas(mousePosition[0], mousePosition[1]);
         }
         const coordinates = {
             x: mousePosition[0],
@@ -248,11 +253,47 @@ class Stage extends React.Component {
         }
         this.setState({mouseDownTimeoutId: null});
     }
+    drawDragCanvas (drawableData) {
+        const {
+            data,
+            width,
+            height,
+            x,
+            y
+        } = drawableData;
+        this.dragCanvas.width = width;
+        this.dragCanvas.height = height;
+        // Need to convert uint8array from WebGL readPixels into Uint8ClampedArray
+        // for ImageData constructor. Shares underlying buffer, so it is fast.
+        const imageData = new ImageData(
+            new Uint8ClampedArray(data.buffer), width, height);
+        this.dragCanvas.getContext('2d').putImageData(imageData, 0, 0);
+        // Position so that pick location is at (0, 0) so that  positionDragCanvas()
+        // can use translation to move to mouse position smoothly.
+        this.dragCanvas.style.left = `${-x}px`;
+        this.dragCanvas.style.top = `${-y}px`;
+    }
+    clearDragCanvas () {
+        this.dragCanvas.width = this.dragCanvas.height = 0;
+    }
+    positionDragCanvas (mouseX, mouseY) {
+        // mouseX/Y are relative to stage top/left, and dragCanvas is already
+        // positioned so that the pick location is at (0,0).
+        this.dragCanvas.style.transform = `translate(${mouseX}px, ${mouseY}px)`;
+    }
     onStartDrag (x, y) {
+        if (this.state.dragId) return;
         const drawableId = this.renderer.pick(x, y);
         if (drawableId === null) return;
         const drawableData = this.renderer.extractDrawable(drawableId, x, y);
         const targetId = this.props.vm.getTargetIdForDrawableId(drawableId);
+
+        // Only start drags on non-draggable targets in editor drag mode
+        if (!this.props.useEditorDragStyle) {
+            const target = this.props.vm.runtime.getTargetById(targetId);
+            if (!target.draggable) return;
+        }
+
         if (targetId === null) return;
         this.props.vm.startDrag(targetId);
         this.setState({
@@ -260,18 +301,41 @@ class Stage extends React.Component {
             dragId: targetId,
             dragOffset: drawableData.scratchOffset
         });
+        if (this.props.useEditorDragStyle) {
+            this.drawDragCanvas(drawableData);
+            this.positionDragCanvas(x, y);
+            this.props.vm.postSpriteInfo({visible: false});
+        }
     }
     onStopDrag () {
-        this.props.vm.stopDrag(this.state.dragId);
-        this.setState({
-            isDragging: false,
-            dragOffset: null,
-            dragId: null
-        });
+        const dragId = this.state.dragId;
+        const commonStopDragActions = () => {
+            this.props.vm.stopDrag(dragId);
+            this.setState({
+                isDragging: false,
+                dragOffset: null,
+                dragId: null
+            });
+        };
+        if (this.props.useEditorDragStyle) {
+            // Need to sequence these actions to prevent flickering.
+            this.props.vm.postSpriteInfo({visible: true});
+            setTimeout(() => {
+                this.clearDragCanvas();
+                setTimeout(() => {
+                    commonStopDragActions();
+                }, 30);
+            }, 30);
+        } else {
+            commonStopDragActions();
+        }
     }
     setCanvas (canvas) {
         this.canvas = canvas;
     }
+    setDragCanvas (canvas) {
+        this.dragCanvas = canvas;
+    }
     render () {
         const {
             vm, // eslint-disable-line no-unused-vars
@@ -282,6 +346,7 @@ class Stage extends React.Component {
             <StageComponent
                 canvasRef={this.setCanvas}
                 colorInfo={this.state.colorInfo}
+                dragRef={this.setDragCanvas}
                 question={this.state.question}
                 onDoubleClick={this.handleDoubleClick}
                 onQuestionAnswered={this.handleQuestionAnswered}
@@ -297,13 +362,20 @@ Stage.propTypes = {
     isFullScreen: PropTypes.bool.isRequired,
     onActivateColorPicker: PropTypes.func,
     onDeactivateColorPicker: PropTypes.func,
+    useEditorDragStyle: PropTypes.bool,
     vm: PropTypes.instanceOf(VM).isRequired,
     width: PropTypes.number
 };
 
+Stage.defaultProps = {
+    useEditorDragStyle: true
+};
+
 const mapStateToProps = state => ({
     isColorPicking: state.colorPicker.active,
-    isFullScreen: state.stageSize.isFullScreen
+    isFullScreen: state.stageSize.isFullScreen,
+    // Do not use editor drag style in fullscreen mode.
+    useEditorDragStyle: !state.stageSize.isFullScreen
 });
 
 const mapDispatchToProps = dispatch => ({