diff --git a/src/canvas/config/config.js b/src/canvas/config/config.js index 3c8c2a3b6..ab8547a26 100644 --- a/src/canvas/config/config.js +++ b/src/canvas/config/config.js @@ -26,6 +26,11 @@ module.exports = { */ customBadgeLabel: '', + /** + * Indicate when to start the auto scroll of the canvas on component/block dragging (value in px ) + */ + autoscrollLimit: 50, + /** * When some textable component is selected and focused (eg. input or text component) the editor * stops some commands (eg. disables the copy/paste of components with CTRL+C/V to allow the copy/paste of the text). diff --git a/src/canvas/index.js b/src/canvas/index.js index 432bb80e3..9b500e97d 100644 --- a/src/canvas/index.js +++ b/src/canvas/index.js @@ -28,9 +28,11 @@ * @module Canvas */ -import { on, off, hasDnd, getElement } from 'utils/mixins'; +import { on, off, hasDnd, getElement, getPointerEvent } from 'utils/mixins'; import Droppable from 'utils/Droppable'; +const { requestAnimationFrame } = window; + module.exports = () => { var c = {}, defaults = require('./config/config'), @@ -81,6 +83,7 @@ module.exports = () => { this.startAutoscroll = this.startAutoscroll.bind(this); this.stopAutoscroll = this.stopAutoscroll.bind(this); this.autoscroll = this.autoscroll.bind(this); + this.updateClientY = this.updateClientY.bind(this); return this; }, @@ -452,22 +455,27 @@ module.exports = () => { // By detaching those from the stack avoid browsers lags // Noticeable with "fast" drag of blocks setTimeout(() => { - on(toListen, 'mousemove', this.autoscroll); + on(toListen, 'mousemove dragover', this.updateClientY); on(toListen, 'mouseup', this.stopAutoscroll); + requestAnimationFrame(this.autoscroll); }, 0); }, + updateClientY(ev) { + ev.preventDefault(); + this.lastClientY = getPointerEvent(ev).clientY; + }, + /** * @private */ - autoscroll(e) { - e.preventDefault(); + autoscroll() { if (this.dragging) { let frameWindow = this.getFrameEl().contentWindow; let actualTop = frameWindow.document.body.scrollTop; let nextTop = actualTop; - let clientY = e.clientY; - let limitTop = 50; + let clientY = this.lastClientY; + let limitTop = this.getConfig().autoscrollLimit; let limitBottom = frameRect.height - limitTop; if (clientY < limitTop) { @@ -478,8 +486,8 @@ module.exports = () => { nextTop += clientY - limitBottom; } - //console.log(`actualTop: ${actualTop} clientY: ${clientY} nextTop: ${nextTop} frameHeigh: ${frameRect.height}`); frameWindow.scrollTo(0, nextTop); + requestAnimationFrame(this.autoscroll); } }, @@ -490,7 +498,7 @@ module.exports = () => { stopAutoscroll() { this.dragging = 0; let toListen = this.getScrollListeners(); - off(toListen, 'mousemove', this.autoscroll); + off(toListen, 'mousemove dragover', this.updateClientY); off(toListen, 'mouseup', this.stopAutoscroll); }, diff --git a/src/utils/mixins.js b/src/utils/mixins.js index 4b5bbde2e..e8915d9e8 100644 --- a/src/utils/mixins.js +++ b/src/utils/mixins.js @@ -121,6 +121,13 @@ const getModel = (el, $) => { return model; }; +/** + * Get cross-device pointer event + * @param {Event} ev + * @return {Event} + */ +const getPointerEvent = (ev) => ev.touches && ev.touches[0] ? ev.touches[0] : ev; + export { on, off, @@ -132,5 +139,6 @@ export { getElement, shallowDiff, normalizeFloat, - getUnitFromValue + getPointerEvent, + getUnitFromValue, };