Skip to content

Commit

Permalink
[2.1.0] Improves UX
Browse files Browse the repository at this point in the history
#19
#20
- Enable/disable tap&hold mechanic using new button in top right menu (or by holding Shift key). When disabled, tap&hold works like a tap.
- Hold Ctrl key and tap in front view mode to clone the currently selected layer, or create a new symbol if nothing selected.
- Redesigned list of layers in side view mode. It now shows in front view mode as well, and includes all containers/symbols, options for renaming/deleting/searching layers, and displays symbol previews.
- Press Up/Down Arrow keys to navigate through the layers in the Symbol Art.
- Press Enter key while renaming layers to submit the new name.
- fixes bug where renaming layers would not register a new history state.
  • Loading branch information
malulleybovo committed Dec 14, 2021
1 parent 34a1434 commit 97398eb
Show file tree
Hide file tree
Showing 25 changed files with 922 additions and 331 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.vs/*
node_modules/*
*.stg
package-lock.json
package.json
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Pseudo-vector image creator.

## [Launch Application](https://malulleybovo.github.io/SymbolArtEditorOnline/)
#### Version 2.0.1
#### Version 2.1.0

### Quickly get down to business and make art with fluidity and agility.
<br>Symbol Art Editor was designed based on three pillars: simplicity, ease of use, and agility.
Expand Down
4 changes: 2 additions & 2 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@
<script src="src/components/ui/UIMenu.js"></script>
<script src="src/components/ui/UIColorPreview.js"></script>
<script src="src/components/ui/UIColorPicker.js"></script>
<script src="src/components/ui/UIContainer.js"></script>
<script src="src/components/ui/UIContainerPicker.js"></script>
<script src="src/components/ui/UILayer.js"></script>
<script src="src/components/ui/UILayerPicker.js"></script>
<script src="src/components/ui/UICopyrightView.js"></script>
<script src="src/components/ui/UIAsset.js"></script>
<script src="src/components/ui/UIAssetPicker.js"></script>
Expand Down
1 change: 0 additions & 1 deletion res/templates/container.html

This file was deleted.

8 changes: 0 additions & 8 deletions res/templates/containerpicker.html

This file was deleted.

2 changes: 1 addition & 1 deletion res/templates/copyrightview.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div class="disable-select" style="pointer-events: none;transition: all 0.3s ease-in-out 0s;position: absolute;right: 10px;bottom: 10px;width: 170px;text-align: right;font-size: 16px;">
<div class="disable-select" style="pointer-events: none;transition: all 0.3s ease-in-out 0s;position: absolute;right: 10px;top: 10px;width: 170px;text-align: right;font-size: 16px;">
<div class="disable-select" style="color: #808080;font-size: 12px;padding: 0 10px 4px 0;">by malulleybovo</div>
</div>
20 changes: 20 additions & 0 deletions res/templates/layer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div style="margin: 4px 0px;pointer-events: all;cursor: pointer;overflow: hidden;background: #ffffff10;border-radius: 6px;position: relative;">
<div id="collapsebutton" style="position: absolute;left: 0;top: 0;bottom: 0;background: white;width: 12px;font-size: 10px;text-align: center;color: #3c3c3c;text-shadow: none;">
<i style="position: absolute;transform: translate(-50%, -50%);top: 50%;" class="fas fa-angle-down"></i>
</div>
<div id="symbolpreview" style="position: absolute;left: 0;top: 0;bottom: 0;width: 24px;">
<svg style="position: absolute;width: 16px;height: 16px;left: 50%;top: 50%;transform: translate(-50%, -50%);">
<filter id="placeholderid" color-interpolation-filters="sRGB">
<feColorMatrix type="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0"></feColorMatrix>
</filter>
<image filter="url(#placeholderid)" href="" style="width: 100%;"></image>
</svg>
</div>
<div id="textview" style="margin-left: 20px;margin-right: 40px;margin-top: 2px;margin-bottom: 4px;padding-left: 4px;"></div>
<div id="renamebutton" style="position: absolute;right: 20px;top: 0;bottom: 0;width: 20px;font-size: 10px;text-align: center;color: white;text-shadow: none;">
<i class="fas fa-pen" style="position: absolute;transform: translate(-50%, -50%);top: 50%;"></i>
</div>
<div id="deletebutton" style="position: absolute;right: 0;top: 0;bottom: 0;width: 20px;font-size: 10px;text-align: center;color: white;text-shadow: none;">
<i style="position: absolute;transform: translate(-50%, -50%);top: 50%;" class="fas fa-trash"></i>
</div>
</div>
18 changes: 18 additions & 0 deletions res/templates/layerpicker.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<div class="disable-select" style="text-shadow: 0px 0px 2px #3c3c3c;transition: all 0.3s ease-in-out 0s;position: absolute;right: 0;bottom: 0;width: 240px;max-width: 45%;text-align: right;font-size: 14px;">
<div style="color: #808080;font-size: 12px;padding: 0 10px 4px 0;">
<span id="symbolcount">0</span><span>/</span><span id="symboltotal">0</span><span> Symbols</span>
<br/>
<span id="containercount">0</span><span>/</span><span id="containertotal">0</span><span> Containers</span>
</div>
<div id="layersearchcontainer" style="color: #808080;font-size: 12px;padding: 0 10px 4px 0;">
<div style="position: relative;height: 30px;background: #80808040;border-radius: 6px;margin-left: 60px;">
<div style="position: absolute;top: 0;left: 12px;bottom: 0;right: 30px;">
<input id="layersearchtextfield" style="padding: 0;height: 100%;border: none;text-align: right;position: relative;top: 0;left: 0;color: white;outline: none;font-family: Verdana;font-weight: bold;font-size: 12pt;width: 100%;" type="text" class="gradient-text">
</div>
<div id="searchbutton" style="position: absolute;right: 0;top: 0;bottom: 0;width: 30px;font-size: 14px;text-align: center;color: white;text-shadow: none;">
<i style="position: absolute;transform: translate(-50%, -50%);top: 50%;" class="fas fa-search"></i>
</div>
</div>
</div>
<div id="listview" style="max-height: 180px;overflow-x: hidden;overflow-y: scroll;scrollbar-width: thin;scrollbar-color: rgba(255,255,255,0.2) rgba(0,0,0,0);"></div>
</div>
9 changes: 6 additions & 3 deletions res/templates/menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
<i id="ellipsisbutton" style="font-size: 18pt;pointer-events: all;" class="fas fa-ellipsis-v fa-fw"></i>
<div id="collapsiblemenu"></div>
</div>
<div style="float: left;margin-left: 12pt;pointer-events: all;">
<i id="undobutton" style="font-size: 18pt;width: 100%;" class="fas fa-undo fa-fw"></i>
<div style="float: left;margin-left: 6pt;pointer-events: all;position: relative;">
<i id="tapholdtogglebutton" style="font-size: 18pt; width: 100%;" class="far fa-dot-circle fa-fw" title="Tap & Hold On/Off (shortcut: Shift)"></i>
</div>
<div style="float: left;margin-left: 15pt;pointer-events: all;">
<i id="undobutton" style="font-size: 18pt;width: 100%;" class="fas fa-undo fa-fw" title="Undo (shortcut: Ctrl+Z)"></i>
</div>
<div style="float: left;margin-left: 16pt;pointer-events: all;">
<i id="redobutton" style="font-size: 18pt;width: 100%;" class="fas fa-redo fa-fw"></i>
<i id="redobutton" style="font-size: 18pt;width: 100%;" class="fas fa-redo fa-fw" title="Redo (shortcut: Ctrl+Y or Ctrl+Shift+Z)"></i>
</div>
<div id="symbolarttypelabel" class="disable-select" style="text-shadow: none;float: left;margin-left: 16pt;background-color: #ff9e2c;color: #3c3c3c;font-size: 10px;font-weight: bold; padding: 3px 6px;margin-top: 3px;border-radius: 6px;transition: all 0.05s ease-in-out 0s;">SYMBOL ART</div>
</div>
2 changes: 1 addition & 1 deletion res/templates/optionsview.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div class="disable-select" style="position: fixed;left: 0;top: 0;width: 100%;height: 100%;opacity: 0.95;background: #3c3c3c;z-index: 1000;transition: all 0.25s ease-in-out 0s;" oncontextmenu="return false;">

<div style="position: absolute;bottom: 30px;left: 50%;transform: translateX(-50%);color: #808080;font-size: 12px;text-align: center;">v2.0.1<br />&copy; 2021 Copyright malulleybovo</div>
<div style="position: absolute;bottom: 30px;left: 50%;transform: translateX(-50%);color: #808080;font-size: 12px;text-align: center;">v2.1.0<br />&copy; 2021 Copyright malulleybovo</div>

<div style="position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);max-width: 720px;font-weight: bold;min-width: 360px;text-align: center;">

Expand Down
61 changes: 54 additions & 7 deletions src/UIApplication.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ class UIApplication {
} else if (originalColorInContainer) {
this._renderer.presenter.setColorForSelectedContainer({ originalColorInContainer: originalColorInContainer, hexValue: hexValue, opacity: opacity, updatesHistory: lastInteraction });
}
if (lastInteraction) {
this._layerPicker.updateWith({ container: this._symbolArt.root });
}
},
requestedEyeDropperColors: _ => {
this._symbolArt.helperImage.imageColors().then(colors => {
Expand All @@ -88,15 +91,55 @@ class UIApplication {
},
onAssetChange: (selectedAsset) => {
this._renderer.presenter.setAssetForSelectedSymbol({ asset: selectedAsset });
this._layerPicker.updateWith({ container: this._symbolArt.root });
}
});
_containerPicker = new UIContainerPicker({
onContainerSelected: (containerUuid) => {
let container3D = Layer3D.layersInUse[containerUuid];
if (container3D instanceof Container3D) {
this._renderer.setSelection({ layer3D: container3D });
_layerPicker = new UILayerPicker({
onLayerSelected: (layerUuid) => {
let layer3D = Layer3D.layersInUse[layerUuid];
if (layer3D instanceof Layer3D) {
this._renderer.setSelection({ layer3D: layer3D });
this._renderer.panToSelection();
SymbolControls3D.shared.attach({ toSymbol3D: this._renderer.selectionGroup });
ContainerControls3D.shared.attach({ toContainer3D: this._renderer.selectionGroup });
HelperImageControls3D.shared.attach({ toHelperImage: null });
}
},
onRenameTapped: layerUuid => {
let layerToRename = null;
this._symbolArt.root.depthFirstIterator(layer => {
if (layer.uuid === layerUuid) {
layerToRename = layer;
return true;
}
});
if (!(layerToRename instanceof Layer)) return;
new UIModalTextField({
title: 'Rename layer:', initialText: layerToRename.name,
onInput: text => { },
onResult: text => {
if (layerToRename.name == text) return;
layerToRename.name = text;
this._renderer.updateWith({ symbolArt: this._symbolArt });
HistoryState.shared.pushHistory({ data: this._symbolArt.clone() });
}
});
},
onDeleteTapped: layerUuid => {
let layerToDelete = null;
this._symbolArt.root.depthFirstIterator(layer => {
if (layer.uuid === layerUuid) {
layerToDelete = layer;
return true;
}
});
if (!(layerToDelete instanceof Layer) && layerToDelete.parent) return;
layerToDelete.parent.remove({ sublayer: layerToDelete });
this._renderer.updateWith({ symbolArt: this._symbolArt });
HistoryState.shared.pushHistory({ data: this._symbolArt.clone() });
SymbolControls3D.shared.attach({ toSymbol3D: this._renderer.selectionGroup });
ContainerControls3D.shared.attach({ toContainer3D: this._renderer.selectionGroup });
HelperImageControls3D.shared.attach({ toHelperImage: null });
}
});
_helperImageSettings = new UIHelperImageSettings({
Expand Down Expand Up @@ -139,7 +182,10 @@ class UIApplication {
_renderer = (() => {
let renderer = new Renderer();
renderer.onSymbolArtChanged = () => {
this._containerPicker.updateWith({ containers: this._symbolArt.root.containers });
this._layerPicker.updateWith({ container: this._symbolArt.root });
setTimeout(_ => {
this._layerPicker.select({ layerWithUuid: this._renderer.selectionUuid });
}, 10);
};
renderer.onSelectionChanged = (selectionUuid) => {
let selectionLayer = this._symbolArt.findLayer({ withUuidString: selectionUuid });
Expand All @@ -149,6 +195,7 @@ class UIApplication {
this._actionBar.setNorthEastButton({ enabled: selectedLayer, forViewMode: ViewMode.symbolEditorMode });
this._actionBar.setEastButton({ enabled: selectedLayer, forViewMode: ViewMode.symbolEditorMode });
this._assetPicker.assetSelectionEnabled = selectedSymbol;
this._layerPicker.select({ layerWithUuid: selectionUuid });
if (!selectedLayer) return;
if (selectedSymbol) {
this._assetPicker.update({
Expand Down Expand Up @@ -246,7 +293,7 @@ class UIApplication {
if (!this.loaded) return;
let $body = $('body');
this._copyrightView.append({ to: $body });
this._containerPicker.append({ to: $body });
this._layerPicker.append({ to: $body });
this._menu.append({ to: $body });
this._actionBar.append({ to: $body });
this._colorPicker.append({ to: $body });
Expand Down
34 changes: 26 additions & 8 deletions src/components/InputDevice.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,22 @@ class InputDevice {
_tapDuration = 500;
_tapTimeout = null;

_longTapDuration = 750;
_longTapDuration = 600;
_longTapTimeout = null;

_longStart = false;
get longStart() { return this._longStart }

_longTouchesWithoutDelay = false;
get longTouchesWithoutDelay() {
return this._longTouchesWithoutDelay;
}
set longTouchesWithoutDelay(value) {
if (typeof value === 'boolean') {
this._longTouchesWithoutDelay = value;
}
}

_previousPinchLength = -1;

_minimumNumberOfPointsToTriggerMotion = 10;
Expand Down Expand Up @@ -89,7 +99,7 @@ class InputDevice {
this._longTapTimeout = null;
this._longStart = true;
this.longTouchBegan(longEvent);
}, this._longTapDuration);
}, this._longTouchesWithoutDelay ? 25 : this._longTapDuration);
}
this.touchBegan(event, this._activeTouchEvents.length);
}
Expand Down Expand Up @@ -147,6 +157,19 @@ class InputDevice {

_interactionEnded(event) {
if (!UIApplication.shared.loaded) return;
let longStart = this._longStart;
if (this._longTapTimeout !== null) {
if (this._longTouchesWithoutDelay) {
setTimeout(_ => {
this._interactionEnded(event);
});
return;
} else {
clearTimeout(this._longTapTimeout);
this._longTapTimeout = null;
this._longStart = false;
}
}
if (event && event.type === 'blur') {
this._activeTouchEvents = [];
}
Expand All @@ -165,16 +188,11 @@ class InputDevice {
}
this._activeEventState = 0;
this._originalTouchEvent = null;
if (this._longStart) {
if (longStart) {
this.longTouchEnded(event);
} else {
this.touchEnded(event);
}
if (this._longTapTimeout !== null) {
clearTimeout(this._longTapTimeout);
this._longTapTimeout = null;
this._longStart = false;
}
}

_scrolled(event) {
Expand Down
1 change: 0 additions & 1 deletion src/components/ui/UIAssetPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,6 @@ class UIAssetPicker extends UIView {
this._assetPreview.attr('src', '');
return;
}
this._assetSelected({ uiAsset: this._catalog[asset.filePath].uiAsset });
}

updateState() {
Expand Down
1 change: 1 addition & 0 deletions src/components/ui/UIColorPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ class UIColorPicker extends UIView {
}
});
this._colorPaletteList.empty();
this._colorPalette.forEach(a => a.remove());
this._colorPalette = [];
Object.values(occurrences).forEach(a => {
let subview = new UIColorPreview({
Expand Down
86 changes: 0 additions & 86 deletions src/components/ui/UIContainer.js

This file was deleted.

Loading

0 comments on commit 97398eb

Please sign in to comment.