Cursors, Esc to cancel active tool (#946)
* basic drawing cursors * Esc to cancel tool, I shortcut bug fix * panel btns hover animation * minor changes * Linter fix * update packages * remove NYC coverage causing build errors would be nice to find out a replacement or a fix --------- Co-authored-by: JFH <20402845+jfhenon@users.noreply.github.com>
This commit is contained in:
@@ -96,6 +96,7 @@ class Editor extends EditorStartup {
|
||||
'zh-CN',
|
||||
'zh-TW'
|
||||
]
|
||||
|
||||
const modKey = isMac() ? 'meta+' : 'ctrl+'
|
||||
this.shortcuts = [
|
||||
// Shortcuts not associated with buttons
|
||||
@@ -304,6 +305,14 @@ class Editor extends EditorStartup {
|
||||
fn: () => {
|
||||
this.pasteInCenter()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'escape',
|
||||
fn: () => {
|
||||
if (this.enableToolCancel) {
|
||||
this.cancelTool()
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
this.leftPanel = new LeftPanel(this)
|
||||
|
||||
@@ -122,6 +122,11 @@ class EditorStartup {
|
||||
this.modeEvent = this.svgCanvas.modeEvent
|
||||
document.addEventListener('modeChange', (evt) => this.modeListener(evt))
|
||||
|
||||
/** if true - selected tool can be cancelled with Esc key
|
||||
* disables on dragging (mousedown) to avoid changing mode in the middle of drawing
|
||||
*/
|
||||
this.enableToolCancel = true
|
||||
|
||||
this.leftPanel.init()
|
||||
this.bottomPanel.init()
|
||||
this.topPanel.init()
|
||||
@@ -309,6 +314,7 @@ class EditorStartup {
|
||||
return false
|
||||
})
|
||||
$id('svgcanvas').addEventListener('mousedown', (evt) => {
|
||||
this.enableToolCancel = false
|
||||
if (evt.button === 1 || keypan === true) {
|
||||
// prDefault to avoid firing of browser's panning on mousewheel
|
||||
evt.preventDefault()
|
||||
@@ -331,6 +337,7 @@ class EditorStartup {
|
||||
})
|
||||
|
||||
window.addEventListener('mouseup', (evt) => {
|
||||
this.enableToolCancel = true
|
||||
if (evt.button === 1) {
|
||||
this.svgCanvas.setMode(previousMode ?? 'select')
|
||||
}
|
||||
@@ -747,12 +754,36 @@ class EditorStartup {
|
||||
case 'zoom':
|
||||
cs = 'crosshair'
|
||||
break
|
||||
case 'circle':
|
||||
case 'ellipse':
|
||||
case 'rect':
|
||||
case 'square':
|
||||
case 'star':
|
||||
case 'polygon':
|
||||
cs = `url("./images/cursors/${mode}_cursor.svg"), crosshair`
|
||||
break
|
||||
case 'text':
|
||||
// #TODO: Cursor should be changed back to default after text element was created
|
||||
cs = 'text'
|
||||
break
|
||||
default:
|
||||
cs = 'auto'
|
||||
}
|
||||
|
||||
this.workarea.style.cursor = cs
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for Esc key to be pressed to cancel active mode, sets mode to Select
|
||||
*/
|
||||
cancelTool () {
|
||||
const mode = this.svgCanvas.getMode()
|
||||
// list of modes that are currently save to cancel
|
||||
const modesToCancel = ['zoom', 'rect', 'square', 'circle', 'ellipse', 'line', 'text', 'star', 'polygon', 'eyedropper']
|
||||
if (modesToCancel.includes(mode)) {
|
||||
this.leftPanel.clickSelect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default EditorStartup
|
||||
|
||||
@@ -3,9 +3,18 @@ import { t } from '../locale.js'
|
||||
const template = document.createElement('template')
|
||||
template.innerHTML = `
|
||||
<style>
|
||||
@keyframes btnHover {
|
||||
from {
|
||||
background-color: var(--main-bg-color);
|
||||
}
|
||||
|
||||
to {
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
}
|
||||
}
|
||||
:host(:hover) :not(.disabled)
|
||||
{
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
animation: btnHover 0.2s forwards;
|
||||
}
|
||||
div
|
||||
{
|
||||
|
||||
@@ -39,9 +39,17 @@ export class FlyingButton extends HTMLElement {
|
||||
:host {
|
||||
position:relative;
|
||||
}
|
||||
.overall:hover *
|
||||
{
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
@keyframes btnHover {
|
||||
from {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
to {
|
||||
background-color: var(--icon-bg-color-hover);
|
||||
}
|
||||
}
|
||||
.overall .menu-button:hover {
|
||||
animation: btnHover 0.2s forwards;
|
||||
}
|
||||
img {
|
||||
border: none;
|
||||
|
||||
@@ -44,6 +44,23 @@ template.innerHTML = `
|
||||
margin-top: 2px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
#arrow-up, #arrow-down {
|
||||
user-select: none;
|
||||
}
|
||||
@keyframes hover-arrows {
|
||||
from {
|
||||
background: transparent;
|
||||
color: var(--icon-bg-color-hover);
|
||||
}
|
||||
|
||||
to {
|
||||
background: var(--icon-bg-color-hover);
|
||||
color: var(--orange-color);
|
||||
}
|
||||
}
|
||||
#arrow-up:hover, #arrow-down:hover {
|
||||
animation: hover-arrows 0.2s forwards;
|
||||
}
|
||||
#down{
|
||||
width:18px;
|
||||
height:23px;
|
||||
|
||||
@@ -83,6 +83,7 @@ export default {
|
||||
callback () {
|
||||
// Add the button and its handler(s)
|
||||
const title = `${name}:buttons.0.title`
|
||||
// #TODO: Come up with another shortcut (?) because 'I' is reserved for italic
|
||||
const key = `${name}:buttons.0.key`
|
||||
const buttonTemplate = `
|
||||
<se-button id="tool_eyedropper" title="${title}" src="eye_dropper.svg" shortcut=${key}></se-button>
|
||||
|
||||
14
src/editor/images/cursors/circle_cursor.svg
Normal file
14
src/editor/images/cursors/circle_cursor.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g id="layer2">
|
||||
<path d="m0.1,7.76l7.7,-7.66l-7.7,0l0,7.66z" fill="#2b3c45" id="path9" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="0.19" />
|
||||
</g>
|
||||
|
||||
<circle cx="9.44" cy="9.06" display="inline" fill="#ffffff" id="path10" r="5.98" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="1" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 599 B |
14
src/editor/images/cursors/ellipse_cursor.svg
Normal file
14
src/editor/images/cursors/ellipse_cursor.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g class="layer" id="svg_2">
|
||||
<g id="layer2">
|
||||
<path d="m0.1,6.37l6.3,-6.27l-6.3,0l0,6.27z" fill="#2b3c45" id="path9" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="0.2" />
|
||||
</g>
|
||||
<ellipse cx="11.0" cy="7" fill="#ffffff" id="svg_1" rx="7.5" ry="3.43" stroke="#2b3c45" stroke-width="1" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 623 B |
14
src/editor/images/cursors/rect_cursor.svg
Normal file
14
src/editor/images/cursors/rect_cursor.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g class="layer" id="svg_2">
|
||||
|
||||
<path d="m0.1,6.37l6.3,-6.27l-6.3,0l0,6.27z" fill="#2b3c45" id="path9" stroke="#2b3c45"
|
||||
stroke-dashoffset="0" stroke-width="0.2" />
|
||||
|
||||
</g>
|
||||
<rect fill="#ffffff" height="6.4" id="svg_3" stroke="#2b3c45" width="13.6" x="4.54" y="4.53" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 556 B |
13
src/editor/images/cursors/square_cursor.svg
Normal file
13
src/editor/images/cursors/square_cursor.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="20" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" version="1.1">
|
||||
<title>circle_cursor</title>
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<g class="layer" id="svg_2">
|
||||
<g id="layer2">
|
||||
<path d="m0.1,6.37l6.3,-6.27l-6.3,0l0,6.27z" fill="#2b3c45" id="path9" stroke="#2b3c45" stroke-dashoffset="0" stroke-width="0.2"/>
|
||||
</g>
|
||||
</g>
|
||||
<rect fill="#ffffff" height="8" id="svg_3" stroke="#2b3c45" width="8" x="5.04" y="4.43"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 517 B |
@@ -764,14 +764,25 @@ class TopPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there are currently selected text elements to avoid firing of bold,italic when no text selected
|
||||
* @returns {boolean}
|
||||
*/
|
||||
get anyTextSelected () {
|
||||
const selected = this.editor.svgCanvas.getSelectedElements()
|
||||
return selected.filter(el => el.tagName === 'text').length > 0
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {false}
|
||||
*/
|
||||
clickBold () {
|
||||
this.editor.svgCanvas.setBold(!this.editor.svgCanvas.getBold())
|
||||
this.updateContextPanel()
|
||||
return false
|
||||
if (this.anyTextSelected) {
|
||||
this.editor.svgCanvas.setBold(!this.editor.svgCanvas.getBold())
|
||||
this.updateContextPanel()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,9 +790,11 @@ class TopPanel {
|
||||
* @returns {false}
|
||||
*/
|
||||
clickItalic () {
|
||||
this.editor.svgCanvas.setItalic(!this.editor.svgCanvas.getItalic())
|
||||
this.updateContextPanel()
|
||||
return false
|
||||
if (this.anyTextSelected) {
|
||||
this.editor.svgCanvas.setItalic(!this.editor.svgCanvas.getItalic())
|
||||
this.updateContextPanel()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
--icon-bg-color: #72797A;
|
||||
--icon-bg-color-hover: #2B3C45;
|
||||
--input-color: #B2B2B2;
|
||||
--orange-color: #f9bc01;
|
||||
--global-se-spin-input-width: 82px;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user