Comparing version 0.1.10 to 0.1.11
@@ -0,1 +1,6 @@ | ||
# 0.1.11 | ||
* Fix 'Enter' key not toggling toolbar buttons. | ||
* Add zoom limits. | ||
* Add a reset zoom button. | ||
# 0.1.10 | ||
@@ -2,0 +7,0 @@ * Keyboard shortcuts for the selection tool. |
@@ -18,2 +18,4 @@ import EditorImage from './EditorImage'; | ||
wheelEventsEnabled: boolean | 'only-if-focused'; | ||
minZoom: number; | ||
maxZoom: number; | ||
} | ||
@@ -20,0 +22,0 @@ export declare class Editor { |
@@ -29,3 +29,3 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
constructor(parent, settings = {}) { | ||
var _a, _b; | ||
var _a, _b, _c, _d; | ||
this.announceUndoCallback = (command) => { | ||
@@ -44,2 +44,4 @@ this.announceForAccessibility(this.localization.undoAnnouncement(command.description(this.localization))); | ||
localization: this.localization, | ||
minZoom: (_c = settings.minZoom) !== null && _c !== void 0 ? _c : 2e-10, | ||
maxZoom: (_d = settings.maxZoom) !== null && _d !== void 0 ? _d : 1e12, | ||
}; | ||
@@ -76,2 +78,16 @@ this.container = document.createElement('div'); | ||
this.hideLoadingWarning(); | ||
// Enforce zoom limits. | ||
this.notifier.on(EditorEventType.ViewportChanged, evt => { | ||
if (evt.kind === EditorEventType.ViewportChanged) { | ||
const zoom = evt.newTransform.transformVec3(Vec2.unitX).length(); | ||
if (zoom > this.settings.maxZoom || zoom < this.settings.minZoom) { | ||
const oldZoom = evt.oldTransform.transformVec3(Vec2.unitX).length(); | ||
let resetTransform = Mat33.identity; | ||
if (oldZoom <= this.settings.maxZoom && oldZoom >= this.settings.minZoom) { | ||
resetTransform = evt.oldTransform; | ||
} | ||
this.viewport.resetTransform(resetTransform); | ||
} | ||
} | ||
}); | ||
} | ||
@@ -78,0 +94,0 @@ // Returns a reference to this' container. |
@@ -9,3 +9,3 @@ import { defaultEditorLocalization } from '../localization'; | ||
// (see src/toolbar/localization.ts) | ||
pen: 'Lapiz', eraser: 'Borrador', select: 'Selecciona', thicknessLabel: 'Tamaño: ', colorLabel: 'Color: ', doneLoading: 'El cargado terminó', fontLabel: 'Fuente: ', anyDevicePanning: 'Mover la pantalla con todo dispotivo', touchPanning: 'Mover la pantalla con un dedo', touchPanTool: 'Instrumento de mover la pantalla con un dedo', outlinedRectanglePen: 'Rectángulo con nada más que un borde', filledRectanglePen: 'Rectángulo sin borde', linePen: 'Línea', arrowPen: 'Flecha', freehandPen: 'Dibuja sin restricción de forma', selectObjectType: 'Forma de dibuja:', handTool: 'Mover', resizeImageToSelection: 'Redimensionar la imagen a lo que está seleccionado', deleteSelection: 'Borra la selección', duplicateSelection: 'Duplica la selección', pickColorFronScreen: 'Selecciona un color de la pantalla', dropdownShown(toolName) { | ||
pen: 'Lapiz', eraser: 'Borrador', select: 'Selecciona', thicknessLabel: 'Tamaño: ', colorLabel: 'Color: ', doneLoading: 'El cargado terminó', fontLabel: 'Fuente: ', anyDevicePanning: 'Mover la pantalla con todo dispotivo', touchPanning: 'Mover la pantalla con un dedo', touchPanTool: 'Instrumento de mover la pantalla con un dedo', outlinedRectanglePen: 'Rectángulo con nada más que un borde', filledRectanglePen: 'Rectángulo sin borde', linePen: 'Línea', arrowPen: 'Flecha', freehandPen: 'Dibuja sin restricción de forma', selectObjectType: 'Forma de dibuja:', handTool: 'Mover', zoom: 'Zoom', resetView: 'Reiniciar vista', resizeImageToSelection: 'Redimensionar la imagen a lo que está seleccionado', deleteSelection: 'Borra la selección', duplicateSelection: 'Duplica la selección', pickColorFronScreen: 'Selecciona un color de la pantalla', dropdownShown(toolName) { | ||
return `Menú por ${toolName} es visible`; | ||
@@ -12,0 +12,0 @@ }, dropdownHidden: function (toolName) { |
@@ -24,2 +24,3 @@ export interface ToolbarLocalization { | ||
zoom: string; | ||
resetView: string; | ||
selectionToolKeyboardShortcuts: string; | ||
@@ -26,0 +27,0 @@ dropdownShown: (toolName: string) => string; |
@@ -7,2 +7,3 @@ export const defaultToolbarLocalization = { | ||
zoom: 'Zoom', | ||
resetView: 'Reset view', | ||
thicknessLabel: 'Thickness: ', | ||
@@ -9,0 +10,0 @@ colorLabel: 'Color: ', |
@@ -48,3 +48,3 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
setupActionBtnClickListener(button) { | ||
const clickTriggers = { enter: true, ' ': true, }; | ||
const clickTriggers = { Enter: true, ' ': true, }; | ||
button.onkeydown = (evt) => { | ||
@@ -51,0 +51,0 @@ let handled = false; |
@@ -13,6 +13,8 @@ import Mat33 from '../../geometry/Mat33'; | ||
const decreaseButton = document.createElement('button'); | ||
const resetViewButton = document.createElement('button'); | ||
const zoomLevelDisplay = document.createElement('span'); | ||
increaseButton.innerText = '+'; | ||
decreaseButton.innerText = '-'; | ||
zoomLevelRow.replaceChildren(zoomLevelDisplay, increaseButton, decreaseButton); | ||
resetViewButton.innerText = localizationTable.resetView; | ||
zoomLevelRow.replaceChildren(zoomLevelDisplay, increaseButton, decreaseButton, resetViewButton); | ||
zoomLevelRow.classList.add(`${toolbarCSSPrefix}zoomLevelEditor`); | ||
@@ -38,2 +40,4 @@ zoomLevelDisplay.classList.add('zoomDisplay'); | ||
updateZoomDisplay(); | ||
// Can't reset if already reset. | ||
resetViewButton.disabled = event.newTransform.eq(Mat33.identity); | ||
} | ||
@@ -52,2 +56,5 @@ }); | ||
}; | ||
resetViewButton.onclick = () => { | ||
editor.dispatch(new Viewport.ViewportTransform(editor.viewport.canvasToScreenTransform.inverse()), true); | ||
}; | ||
return zoomLevelRow; | ||
@@ -54,0 +61,0 @@ }; |
@@ -124,5 +124,5 @@ import Mat33 from '../geometry/Mat33'; | ||
onWheel({ delta, screenPos }) { | ||
if (this.transform === null) { | ||
this.transform = new Viewport.ViewportTransform(Mat33.identity); | ||
} | ||
// Reset the transformation -- wheel events are individual events, so we don't | ||
// need to unapply/reapply. | ||
this.transform = new Viewport.ViewportTransform(Mat33.identity); | ||
const canvasPos = this.editor.viewport.screenToCanvas(screenPos); | ||
@@ -133,3 +133,3 @@ const toCanvas = this.editor.viewport.screenToCanvasTransform; | ||
const pinchZoomScaleFactor = 1.04; | ||
const transformUpdate = Mat33.scaling2D(Math.pow(pinchZoomScaleFactor, -delta.z), canvasPos).rightMul(Mat33.translation(translation)); | ||
const transformUpdate = Mat33.scaling2D(Math.max(0.25, Math.min(Math.pow(pinchZoomScaleFactor, -delta.z), 4)), canvasPos).rightMul(Mat33.translation(translation)); | ||
this.updateTransform(transformUpdate); | ||
@@ -142,2 +142,4 @@ return true; | ||
} | ||
// No need to keep the same the transform for keyboard events. | ||
this.transform = new Viewport.ViewportTransform(Mat33.identity); | ||
let translation = Vec2.zero; | ||
@@ -144,0 +146,0 @@ let scale = 1; |
@@ -82,2 +82,3 @@ import EventDispatcher from './EventDispatcher'; | ||
readonly newTransform: Mat33; | ||
readonly oldTransform: Mat33; | ||
} | ||
@@ -84,0 +85,0 @@ export interface DisplayResizedEvent { |
@@ -41,2 +41,3 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { | ||
resetTransform(newTransform = Mat33.identity) { | ||
const oldTransform = this.transform; | ||
this.transform = newTransform; | ||
@@ -47,2 +48,3 @@ this.inverseTransform = newTransform.inverse(); | ||
newTransform, | ||
oldTransform, | ||
}); | ||
@@ -49,0 +51,0 @@ } |
{ | ||
"name": "js-draw", | ||
"version": "0.1.10", | ||
"version": "0.1.11", | ||
"description": "Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript. ", | ||
@@ -5,0 +5,0 @@ "main": "dist/src/Editor.js", |
@@ -34,2 +34,5 @@ | ||
wheelEventsEnabled: boolean|'only-if-focused'; | ||
minZoom: number, | ||
maxZoom: number, | ||
} | ||
@@ -73,2 +76,4 @@ | ||
localization: this.localization, | ||
minZoom: settings.minZoom ?? 2e-10, | ||
maxZoom: settings.maxZoom ?? 1e12, | ||
}; | ||
@@ -116,2 +121,20 @@ | ||
this.hideLoadingWarning(); | ||
// Enforce zoom limits. | ||
this.notifier.on(EditorEventType.ViewportChanged, evt => { | ||
if (evt.kind === EditorEventType.ViewportChanged) { | ||
const zoom = evt.newTransform.transformVec3(Vec2.unitX).length(); | ||
if (zoom > this.settings.maxZoom || zoom < this.settings.minZoom) { | ||
const oldZoom = evt.oldTransform.transformVec3(Vec2.unitX).length(); | ||
let resetTransform = Mat33.identity; | ||
if (oldZoom <= this.settings.maxZoom && oldZoom >= this.settings.minZoom) { | ||
resetTransform = evt.oldTransform; | ||
} | ||
this.viewport.resetTransform(resetTransform); | ||
} | ||
} | ||
}); | ||
} | ||
@@ -118,0 +141,0 @@ |
@@ -36,2 +36,4 @@ import { defaultEditorLocalization, EditorLocalization } from '../localization'; | ||
handTool: 'Mover', | ||
zoom: 'Zoom', | ||
resetView: 'Reiniciar vista', | ||
resizeImageToSelection: 'Redimensionar la imagen a lo que está seleccionado', | ||
@@ -38,0 +40,0 @@ deleteSelection: 'Borra la selección', |
@@ -26,2 +26,3 @@ | ||
zoom: string; | ||
resetView: string; | ||
selectionToolKeyboardShortcuts: string; | ||
@@ -41,2 +42,3 @@ | ||
zoom: 'Zoom', | ||
resetView: 'Reset view', | ||
thicknessLabel: 'Thickness: ', | ||
@@ -43,0 +45,0 @@ colorLabel: 'Color: ', |
@@ -54,3 +54,3 @@ import Editor from '../../Editor'; | ||
protected setupActionBtnClickListener(button: HTMLElement) { | ||
const clickTriggers = { enter: true, ' ': true, }; | ||
const clickTriggers = { Enter: true, ' ': true, }; | ||
button.onkeydown = (evt) => { | ||
@@ -57,0 +57,0 @@ let handled = false; |
@@ -17,6 +17,8 @@ import Editor from '../../Editor'; | ||
const decreaseButton = document.createElement('button'); | ||
const resetViewButton = document.createElement('button'); | ||
const zoomLevelDisplay = document.createElement('span'); | ||
increaseButton.innerText = '+'; | ||
decreaseButton.innerText = '-'; | ||
zoomLevelRow.replaceChildren(zoomLevelDisplay, increaseButton, decreaseButton); | ||
resetViewButton.innerText = localizationTable.resetView; | ||
zoomLevelRow.replaceChildren(zoomLevelDisplay, increaseButton, decreaseButton, resetViewButton); | ||
@@ -46,2 +48,5 @@ zoomLevelRow.classList.add(`${toolbarCSSPrefix}zoomLevelEditor`); | ||
updateZoomDisplay(); | ||
// Can't reset if already reset. | ||
resetViewButton.disabled = event.newTransform.eq(Mat33.identity); | ||
} | ||
@@ -64,2 +69,8 @@ }); | ||
resetViewButton.onclick = () => { | ||
editor.dispatch(new Viewport.ViewportTransform( | ||
editor.viewport.canvasToScreenTransform.inverse() | ||
), true); | ||
}; | ||
return zoomLevelRow; | ||
@@ -66,0 +77,0 @@ }; |
@@ -161,5 +161,5 @@ | ||
public onWheel({ delta, screenPos }: WheelEvt): boolean { | ||
if (this.transform === null) { | ||
this.transform = new Viewport.ViewportTransform(Mat33.identity); | ||
} | ||
// Reset the transformation -- wheel events are individual events, so we don't | ||
// need to unapply/reapply. | ||
this.transform = new Viewport.ViewportTransform(Mat33.identity); | ||
@@ -176,3 +176,3 @@ const canvasPos = this.editor.viewport.screenToCanvas(screenPos); | ||
const transformUpdate = Mat33.scaling2D( | ||
Math.pow(pinchZoomScaleFactor, -delta.z), canvasPos | ||
Math.max(0.25, Math.min(Math.pow(pinchZoomScaleFactor, -delta.z), 4)), canvasPos | ||
).rightMul( | ||
@@ -191,2 +191,5 @@ Mat33.translation(translation) | ||
// No need to keep the same the transform for keyboard events. | ||
this.transform = new Viewport.ViewportTransform(Mat33.identity); | ||
let translation = Vec2.zero; | ||
@@ -193,0 +196,0 @@ let scale = 1; |
@@ -120,2 +120,3 @@ // Types related to the image editor | ||
readonly newTransform: Mat33; | ||
readonly oldTransform: Mat33; | ||
} | ||
@@ -122,0 +123,0 @@ |
@@ -106,2 +106,3 @@ import Command from './commands/Command'; | ||
public resetTransform(newTransform: Mat33 = Mat33.identity) { | ||
const oldTransform = this.transform; | ||
this.transform = newTransform; | ||
@@ -112,2 +113,3 @@ this.inverseTransform = newTransform.inverse(); | ||
newTransform, | ||
oldTransform, | ||
}); | ||
@@ -114,0 +116,0 @@ } |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
974707
20616