Bottom panel styling, more adaptive palette, shortcuts (#937)
This commit is contained in:
3
.github/workflows/onpullrequest.yml
vendored
3
.github/workflows/onpullrequest.yml
vendored
@@ -1,6 +1,9 @@
|
||||
name: Node CI
|
||||
|
||||
on: [pull_request]
|
||||
# To be able to write in the PR, we need write permission.
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -71,49 +71,240 @@ class Editor extends EditorStartup {
|
||||
this.docprops = false
|
||||
this.configObj.preferences = false
|
||||
this.canvMenu = null
|
||||
this.goodLangs = ['ar', 'cs', 'de', 'en', 'es', 'fa', 'fr', 'fy', 'hi', 'it', 'ja', 'nl', 'pl', 'pt-BR', 'ro', 'ru', 'sk', 'sl', 'sv', 'tr', 'uk', 'zh-CN', 'zh-TW']
|
||||
const modKey = (isMac() ? 'meta+' : 'ctrl+')
|
||||
this.goodLangs = [
|
||||
'ar',
|
||||
'cs',
|
||||
'de',
|
||||
'en',
|
||||
'es',
|
||||
'fa',
|
||||
'fr',
|
||||
'fy',
|
||||
'hi',
|
||||
'it',
|
||||
'ja',
|
||||
'nl',
|
||||
'pl',
|
||||
'pt-BR',
|
||||
'ro',
|
||||
'ru',
|
||||
'sk',
|
||||
'sl',
|
||||
'sv',
|
||||
'tr',
|
||||
'uk',
|
||||
'zh-CN',
|
||||
'zh-TW'
|
||||
]
|
||||
const modKey = isMac() ? 'meta+' : 'ctrl+'
|
||||
this.shortcuts = [
|
||||
// Shortcuts not associated with buttons
|
||||
{ key: 'ctrl+arrowleft', fn: () => { this.rotateSelected(0, 1) } },
|
||||
{ key: 'ctrl+arrowright', fn: () => { this.rotateSelected(1, 1) } },
|
||||
{ key: 'ctrl+shift+arrowleft', fn: () => { this.rotateSelected(0, 5) } },
|
||||
{ key: 'ctrl+shift+arrowright', fn: () => { this.rotateSelected(1, 5) } },
|
||||
{ key: 'shift+o', fn: () => { this.svgCanvas.cycleElement(0) } },
|
||||
{ key: 'shift+p', fn: () => { this.svgCanvas.cycleElement(1) } },
|
||||
{ key: 'tab', fn: () => { this.svgCanvas.cycleElement(0) } },
|
||||
{ key: 'shift+tab', fn: () => { this.svgCanvas.cycleElement(1) } },
|
||||
{ key: [modKey + 'arrowup', true], fn: () => { this.zoomImage(2) } },
|
||||
{ key: [modKey + 'arrowdown', true], fn: () => { this.zoomImage(0.5) } },
|
||||
{ key: [modKey + ']', true], fn: () => { this.moveUpDownSelected('Up') } },
|
||||
{ key: [modKey + '[', true], fn: () => { this.moveUpDownSelected('Down') } },
|
||||
{ key: ['arrowup', true], fn: () => { this.moveSelected(0, -1) } },
|
||||
{ key: ['arrowdown', true], fn: () => { this.moveSelected(0, 1) } },
|
||||
{ key: ['arrowleft', true], fn: () => { this.moveSelected(-1, 0) } },
|
||||
{ key: ['arrowright', true], fn: () => { this.moveSelected(1, 0) } },
|
||||
{ key: 'shift+arrowup', fn: () => { this.moveSelected(0, -10) } },
|
||||
{ key: 'shift+arrowdown', fn: () => { this.moveSelected(0, 10) } },
|
||||
{ key: 'shift+arrowleft', fn: () => { this.moveSelected(-10, 0) } },
|
||||
{ key: 'shift+arrowright', fn: () => { this.moveSelected(10, 0) } },
|
||||
{ key: ['alt+arrowup', true], fn: () => { this.svgCanvas.cloneSelectedElements(0, -1) } },
|
||||
{ key: ['alt+arrowdown', true], fn: () => { this.svgCanvas.cloneSelectedElements(0, 1) } },
|
||||
{ key: ['alt+arrowleft', true], fn: () => { this.svgCanvas.cloneSelectedElements(-1, 0) } },
|
||||
{ key: ['alt+arrowright', true], fn: () => { this.svgCanvas.cloneSelectedElements(1, 0) } },
|
||||
{ key: ['alt+shift+arrowup', true], fn: () => { this.svgCanvas.cloneSelectedElements(0, -10) } },
|
||||
{ key: ['alt+shift+arrowdown', true], fn: () => { this.svgCanvas.cloneSelectedElements(0, 10) } },
|
||||
{ key: ['alt+shift+arrowleft', true], fn: () => { this.svgCanvas.cloneSelectedElements(-10, 0) } },
|
||||
{ key: ['alt+shift+arrowright', true], fn: () => { this.svgCanvas.cloneSelectedElements(10, 0) } },
|
||||
{
|
||||
key: ['ctrl+arrowleft', true],
|
||||
fn: () => {
|
||||
this.rotateSelected(0, 1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'ctrl+arrowright',
|
||||
fn: () => {
|
||||
this.rotateSelected(1, 1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['ctrl+shift+arrowleft', true],
|
||||
fn: () => {
|
||||
this.rotateSelected(0, 5)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'ctrl+shift+arrowright',
|
||||
fn: () => {
|
||||
this.rotateSelected(1, 5)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+o',
|
||||
fn: () => {
|
||||
this.svgCanvas.cycleElement(0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+p',
|
||||
fn: () => {
|
||||
this.svgCanvas.cycleElement(1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'tab',
|
||||
fn: () => {
|
||||
this.svgCanvas.cycleElement(0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+tab',
|
||||
fn: () => {
|
||||
this.svgCanvas.cycleElement(1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: [modKey + 'arrowup', true],
|
||||
fn: () => {
|
||||
this.zoomImage(2)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: [modKey + 'arrowdown', true],
|
||||
fn: () => {
|
||||
this.zoomImage(0.5)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: [modKey + ']', true],
|
||||
fn: () => {
|
||||
this.moveUpDownSelected('Up')
|
||||
}
|
||||
},
|
||||
{
|
||||
key: [modKey + '[', true],
|
||||
fn: () => {
|
||||
this.moveUpDownSelected('Down')
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['arrowup', true],
|
||||
fn: () => {
|
||||
this.moveSelected(0, -1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['arrowdown', true],
|
||||
fn: () => {
|
||||
this.moveSelected(0, 1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['arrowleft', true],
|
||||
fn: () => {
|
||||
this.moveSelected(-1, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['arrowright', true],
|
||||
fn: () => {
|
||||
this.moveSelected(1, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+arrowup',
|
||||
fn: () => {
|
||||
this.moveSelected(0, -10)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+arrowdown',
|
||||
fn: () => {
|
||||
this.moveSelected(0, 10)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+arrowleft',
|
||||
fn: () => {
|
||||
this.moveSelected(-10, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'shift+arrowright',
|
||||
fn: () => {
|
||||
this.moveSelected(10, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+arrowup', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(0, -1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+arrowdown', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(0, 1)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+arrowleft', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(-1, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+arrowright', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(1, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+shift+arrowup', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(0, -10)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+shift+arrowdown', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(0, 10)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+shift+arrowleft', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(-10, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['alt+shift+arrowright', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.cloneSelectedElements(10, 0)
|
||||
}
|
||||
},
|
||||
{
|
||||
key: ['delete/backspace', true],
|
||||
fn: () => {
|
||||
if (this.selectedElement || this.multiselected) { this.svgCanvas.deleteSelectedElements() }
|
||||
if (this.selectedElement || this.multiselected) {
|
||||
this.svgCanvas.deleteSelectedElements()
|
||||
}
|
||||
}
|
||||
},
|
||||
{ key: 'a', fn: () => { this.svgCanvas.selectAllInCurrentLayer() } },
|
||||
{ key: modKey + 'a', fn: () => { this.svgCanvas.selectAllInCurrentLayer() } },
|
||||
{ key: modKey + 'x', fn: () => { this.cutSelected() } },
|
||||
{ key: modKey + 'c', fn: () => { this.copySelected() } },
|
||||
{ key: modKey + 'v', fn: () => { this.pasteInCenter() } }
|
||||
{
|
||||
key: 'a',
|
||||
fn: () => {
|
||||
this.svgCanvas.selectAllInCurrentLayer()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: [modKey + 'a', true],
|
||||
fn: () => {
|
||||
this.svgCanvas.selectAllInCurrentLayer()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: modKey + 'x',
|
||||
fn: () => {
|
||||
this.cutSelected()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: modKey + 'c',
|
||||
fn: () => {
|
||||
this.copySelected()
|
||||
}
|
||||
},
|
||||
{
|
||||
key: modKey + 'v',
|
||||
fn: () => {
|
||||
this.pasteInCenter()
|
||||
}
|
||||
}
|
||||
]
|
||||
this.leftPanel = new LeftPanel(this)
|
||||
this.bottomPanel = new BottomPanel(this)
|
||||
@@ -204,7 +395,7 @@ class Editor extends EditorStartup {
|
||||
setAll () {
|
||||
const keyHandler = {} // will contain the action for each pressed key
|
||||
|
||||
this.shortcuts.forEach(shortcut => {
|
||||
this.shortcuts.forEach((shortcut) => {
|
||||
// Bind function to shortcut key
|
||||
if (shortcut.key) {
|
||||
// Set shortcut based on options
|
||||
@@ -218,14 +409,14 @@ class Editor extends EditorStartup {
|
||||
}
|
||||
keyval = String(keyval)
|
||||
const { fn } = shortcut
|
||||
keyval.split('/').forEach(key => {
|
||||
keyval.split('/').forEach((key) => {
|
||||
keyHandler[key] = { fn, pd }
|
||||
})
|
||||
}
|
||||
return true
|
||||
})
|
||||
// register the keydown event
|
||||
document.addEventListener('keydown', e => {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// only track keyboard shortcuts for the body containing the SVG-Editor
|
||||
if (e.target.nodeName !== 'BODY') return
|
||||
// normalize key
|
||||
@@ -282,7 +473,7 @@ class Editor extends EditorStartup {
|
||||
* @returns {module:SVGthis.ToolButton}
|
||||
*/
|
||||
getButtonData (sel) {
|
||||
return Object.values(this.shortcuts).find(btn => {
|
||||
return Object.values(this.shortcuts).find((btn) => {
|
||||
return btn.sel === sel
|
||||
})
|
||||
}
|
||||
@@ -350,7 +541,9 @@ class Editor extends EditorStartup {
|
||||
const { workarea } = this
|
||||
const cnvs = $id('svgcanvas')
|
||||
|
||||
let w = parseFloat(getComputedStyle(workarea, null).width.replace('px', ''))
|
||||
let w = parseFloat(
|
||||
getComputedStyle(workarea, null).width.replace('px', '')
|
||||
)
|
||||
let h = parseFloat(
|
||||
getComputedStyle(workarea, null).height.replace('px', '')
|
||||
)
|
||||
@@ -444,9 +637,8 @@ class Editor extends EditorStartup {
|
||||
}
|
||||
`
|
||||
if (document.querySelectorAll('#wireframe_rules').length > 0) {
|
||||
document.querySelector(
|
||||
'#wireframe_rules'
|
||||
).textContent = this.workarea.classList.contains('wireframe') ? rule : ''
|
||||
document.querySelector('#wireframe_rules').textContent =
|
||||
this.workarea.classList.contains('wireframe') ? rule : ''
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,7 +730,7 @@ class Editor extends EditorStartup {
|
||||
this.leftPanel.clickSelect()
|
||||
}
|
||||
|
||||
elems.forEach(elem => {
|
||||
elems.forEach((elem) => {
|
||||
const isSvgElem = elem?.tagName === 'svg'
|
||||
if (isSvgElem || this.svgCanvas.isLayer(elem)) {
|
||||
this.layersPanel.populateLayers()
|
||||
@@ -593,18 +785,14 @@ class Editor extends EditorStartup {
|
||||
* @returns {void}
|
||||
*/
|
||||
afterClear (win) {
|
||||
this.svgCanvas.runExtensions(
|
||||
'afterClear'
|
||||
)
|
||||
this.svgCanvas.runExtensions('afterClear')
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
*/
|
||||
beforeClear (win) {
|
||||
this.svgCanvas.runExtensions(
|
||||
'beforeClear'
|
||||
)
|
||||
this.svgCanvas.runExtensions('beforeClear')
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1135,7 +1323,7 @@ class Editor extends EditorStartup {
|
||||
return this.ready(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(url, { cache: cache ? 'force-cache' : 'no-cache' })
|
||||
.then(response => {
|
||||
.then((response) => {
|
||||
if (!response.ok) {
|
||||
if (noAlert) {
|
||||
reject(new Error('URLLoadFail'))
|
||||
@@ -1146,16 +1334,18 @@ class Editor extends EditorStartup {
|
||||
}
|
||||
return response.text()
|
||||
})
|
||||
.then(str => {
|
||||
.then((str) => {
|
||||
this.loadSvgString(str, { noAlert })
|
||||
return str
|
||||
})
|
||||
.catch(error => {
|
||||
.catch((error) => {
|
||||
if (noAlert) {
|
||||
reject(new Error('URLLoadFail'))
|
||||
return
|
||||
}
|
||||
seAlert(this.i18next.t('notification.URLLoadFail') + ': \n' + error)
|
||||
seAlert(
|
||||
this.i18next.t('notification.URLLoadFail') + ': \n' + error
|
||||
)
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
@@ -634,7 +634,7 @@ div.jGraduate_Slider img {
|
||||
}
|
||||
#color_picker {
|
||||
z-index: 1000;
|
||||
top: 60%;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
<div id="picker">
|
||||
@@ -651,8 +651,8 @@ div.jGraduate_Slider img {
|
||||
*/
|
||||
export class SeColorPicker extends HTMLElement {
|
||||
/**
|
||||
* @function constructor
|
||||
*/
|
||||
* @function constructor
|
||||
*/
|
||||
constructor () {
|
||||
super()
|
||||
// create the shadowDom and insert the template
|
||||
|
||||
@@ -2,16 +2,48 @@
|
||||
/* eslint-disable max-len */
|
||||
const palette = [
|
||||
// Todo: Make into configuration item?
|
||||
'none', '#000000', '#3f3f3f', '#7f7f7f', '#bfbfbf', '#ffffff',
|
||||
'#ff0000', '#ff7f00', '#ffff00', '#7fff00',
|
||||
'#00ff00', '#00ff7f', '#00ffff', '#007fff',
|
||||
'#0000ff', '#7f00ff', '#ff00ff', '#ff007f',
|
||||
'#7f0000', '#7f3f00', '#7f7f00', '#3f7f00',
|
||||
'#007f00', '#007f3f', '#007f7f', '#003f7f',
|
||||
'#00007f', '#3f007f', '#7f007f', '#7f003f',
|
||||
'#ffaaaa', '#ffd4aa', '#ffffaa', '#d4ffaa',
|
||||
'#aaffaa', '#aaffd4', '#aaffff', '#aad4ff',
|
||||
'#aaaaff', '#d4aaff', '#ffaaff', '#ffaad4'
|
||||
'none',
|
||||
'#000000',
|
||||
'#3f3f3f',
|
||||
'#7f7f7f',
|
||||
'#bfbfbf',
|
||||
'#ffffff',
|
||||
'#ff0000',
|
||||
'#ff7f00',
|
||||
'#ffff00',
|
||||
'#7fff00',
|
||||
'#00ff00',
|
||||
'#00ff7f',
|
||||
'#00ffff',
|
||||
'#007fff',
|
||||
'#0000ff',
|
||||
'#7f00ff',
|
||||
'#ff00ff',
|
||||
'#ff007f',
|
||||
'#7f0000',
|
||||
'#7f3f00',
|
||||
'#7f7f00',
|
||||
'#3f7f00',
|
||||
'#007f00',
|
||||
'#007f3f',
|
||||
'#007f7f',
|
||||
'#003f7f',
|
||||
'#00007f',
|
||||
'#3f007f',
|
||||
'#7f007f',
|
||||
'#7f003f',
|
||||
'#ffaaaa',
|
||||
'#ffd4aa',
|
||||
'#ffffaa',
|
||||
'#d4ffaa',
|
||||
'#aaffaa',
|
||||
'#aaffd4',
|
||||
'#aaffff',
|
||||
'#aad4ff',
|
||||
'#aaaaff',
|
||||
'#d4aaff',
|
||||
'#ffaaff',
|
||||
'#ffaad4'
|
||||
]
|
||||
|
||||
const template = document.createElement('template')
|
||||
@@ -32,8 +64,9 @@ template.innerHTML = `
|
||||
|
||||
#js-se-palette {
|
||||
float: left;
|
||||
width: 632px;
|
||||
height: 16px;
|
||||
min-width: 30px;
|
||||
height: 15px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.palette_item {
|
||||
@@ -45,12 +78,40 @@ template.innerHTML = `
|
||||
div.palette_item:first-child {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.palette_expand_btn {
|
||||
background: none;
|
||||
border: none;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
user-select:none;
|
||||
}
|
||||
|
||||
#palette_popup {
|
||||
padding: 4px;
|
||||
margin-left: 24px;
|
||||
background: white;
|
||||
min-width: 180px;
|
||||
max-width: 360px;
|
||||
min-height: 14px;
|
||||
flex-wrap: wrap;
|
||||
border-radius: 4px;
|
||||
|
||||
position: absolute;
|
||||
bottom: 36px;
|
||||
right: 30px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<div id="palette_holder" title="">
|
||||
<div id="js-se-palette">
|
||||
</div>
|
||||
</div>
|
||||
<button class="palette_expand_btn" title="Show whole palette">▼</button>
|
||||
<!-- hidden div -->
|
||||
<div id="palette_popup" style="display:none"/>
|
||||
`
|
||||
|
||||
/**
|
||||
@@ -58,20 +119,38 @@ template.innerHTML = `
|
||||
*/
|
||||
export class SEPalette extends HTMLElement {
|
||||
/**
|
||||
* @function constructor
|
||||
*/
|
||||
* @function constructor
|
||||
*/
|
||||
constructor () {
|
||||
super()
|
||||
// create the shadowDom and insert the template
|
||||
this._shadowRoot = this.attachShadow({ mode: 'open' })
|
||||
this._shadowRoot.append(template.content.cloneNode(true))
|
||||
this.$strip = this._shadowRoot.querySelector('#js-se-palette')
|
||||
this.expand_btn = this._shadowRoot.querySelector(
|
||||
'button.palette_expand_btn'
|
||||
)
|
||||
this.popUp = this._shadowRoot.getElementById('palette_popup')
|
||||
svgEditor.$click(this.expand_btn, (e) => {
|
||||
e.stopPropagation()
|
||||
const { display } = this.popUp.style
|
||||
if (display === 'none') {
|
||||
this.showPopUp()
|
||||
} else {
|
||||
this.hidePopUp()
|
||||
}
|
||||
})
|
||||
svgEditor.svgCanvas.container.addEventListener('click', () =>
|
||||
this.hidePopUp()
|
||||
)
|
||||
|
||||
palette.forEach((rgb) => {
|
||||
const newDiv = document.createElement('div')
|
||||
newDiv.classList.add('square')
|
||||
if (rgb === 'none') {
|
||||
const img = document.createElement('img')
|
||||
img.src = 'data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgY2xhc3M9InN2Z19pY29uIj48c3ZnIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+CiAgICA8bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiNkNDAwMDAiIGlkPSJzdmdfOTAiIHkyPSIyNCIgeDI9IjI0IiB5MT0iMCIgeDE9IjAiLz4KICAgIDxsaW5lIGlkPSJzdmdfOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2Q0MDAwMCIgeTI9IjI0IiB4Mj0iMCIgeTE9IjAiIHgxPSIyNCIvPgogIDwvc3ZnPjwvc3ZnPg=='
|
||||
img.src =
|
||||
'data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0IiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgY2xhc3M9InN2Z19pY29uIj48c3ZnIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+CiAgICA8bGluZSBmaWxsPSJub25lIiBzdHJva2U9IiNkNDAwMDAiIGlkPSJzdmdfOTAiIHkyPSIyNCIgeDI9IjI0IiB5MT0iMCIgeDE9IjAiLz4KICAgIDxsaW5lIGlkPSJzdmdfOTIiIGZpbGw9Im5vbmUiIHN0cm9rZT0iI2Q0MDAwMCIgeTI9IjI0IiB4Mj0iMCIgeTE9IjAiIHgxPSIyNCIvPgogIDwvc3ZnPjwvc3ZnPg=='
|
||||
img.style.width = '15px'
|
||||
img.style.height = '15px'
|
||||
newDiv.append(img)
|
||||
@@ -79,19 +158,31 @@ export class SEPalette extends HTMLElement {
|
||||
newDiv.style.backgroundColor = rgb
|
||||
}
|
||||
newDiv.dataset.rgb = rgb
|
||||
svgEditor.$click(newDiv, (evt) => {
|
||||
const clickCb = (evt) => {
|
||||
evt.preventDefault()
|
||||
// shift key or right click for stroke
|
||||
const picker = evt.shiftKey || evt.button === 2 ? 'stroke' : 'fill'
|
||||
let color = newDiv.dataset.rgb
|
||||
// Webkit-based browsers returned 'initial' here for no stroke
|
||||
if (color === 'none' || color === 'transparent' || color === 'initial') {
|
||||
if (
|
||||
color === 'none' ||
|
||||
color === 'transparent' ||
|
||||
color === 'initial'
|
||||
) {
|
||||
color = 'none'
|
||||
}
|
||||
const paletteEvent = new CustomEvent('change', { detail: { picker, color }, bubbles: false })
|
||||
const paletteEvent = new CustomEvent('change', {
|
||||
detail: { picker, color },
|
||||
bubbles: false
|
||||
})
|
||||
this.dispatchEvent(paletteEvent)
|
||||
})
|
||||
}
|
||||
svgEditor.$click(newDiv, clickCb)
|
||||
this.$strip.append(newDiv)
|
||||
|
||||
const divDialog = newDiv.cloneNode(true)
|
||||
svgEditor.$click(divDialog, clickCb)
|
||||
this.popUp.append(divDialog)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -131,7 +222,21 @@ export class SEPalette extends HTMLElement {
|
||||
* @function connectedCallback
|
||||
* @returns {void}
|
||||
*/
|
||||
connectedCallback () {
|
||||
connectedCallback () {}
|
||||
|
||||
/**
|
||||
* Shows popUp window with the whole palette
|
||||
*/
|
||||
showPopUp () {
|
||||
this.popUp.style.display = 'flex'
|
||||
this.expand_btn.textContent = '▲'
|
||||
this.expand_btn.setAttribute('title', 'Hide palette window')
|
||||
}
|
||||
|
||||
hidePopUp () {
|
||||
this.popUp.style.display = 'none'
|
||||
this.expand_btn.textContent = '▼'
|
||||
this.expand_btn.setAttribute('title', 'Show palette window')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ const { $id } = SvgCanvas
|
||||
* register actions for left panel
|
||||
*/
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
class BottomPanel {
|
||||
/**
|
||||
* @param {PlainObject} editor svgedit handler
|
||||
*/
|
||||
*/
|
||||
constructor (editor) {
|
||||
this.editor = editor
|
||||
}
|
||||
@@ -26,26 +26,30 @@ class BottomPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
get multiselected () {
|
||||
return this.editor.multiselected
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
changeStrokeWidth (e) {
|
||||
let val = e.target.value
|
||||
if (val === 0 && this.editor.selectedElement && ['line', 'polyline'].includes(this.editor.selectedElement.nodeName)) {
|
||||
if (
|
||||
val === 0 &&
|
||||
this.editor.selectedElement &&
|
||||
['line', 'polyline'].includes(this.editor.selectedElement.nodeName)
|
||||
) {
|
||||
val = 1
|
||||
}
|
||||
this.editor.svgCanvas.setStrokeWidth(val)
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
changeZoom (value) {
|
||||
switch (value) {
|
||||
case 'canvas':
|
||||
@@ -54,34 +58,51 @@ class BottomPanel {
|
||||
case 'content':
|
||||
this.editor.zoomChanged(window, value)
|
||||
break
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
const zoomlevel = Number(value) > 0.1 ? Number(value) * 0.01 : 0.1
|
||||
const zoom = this.editor.svgCanvas.getZoom()
|
||||
const { workarea } = this.editor
|
||||
this.editor.zoomChanged(window, {
|
||||
width: 0,
|
||||
height: 0,
|
||||
// center pt of scroll position
|
||||
x: (workarea.scrollLeft + parseFloat(getComputedStyle(workarea, null).width.replace('px', '')) / 2) / zoom,
|
||||
y: (workarea.scrollTop + parseFloat(getComputedStyle(workarea, null).height.replace('px', '')) / 2) / zoom,
|
||||
zoom: zoomlevel
|
||||
}, true)
|
||||
this.editor.zoomChanged(
|
||||
window,
|
||||
{
|
||||
width: 0,
|
||||
height: 0,
|
||||
// center pt of scroll position
|
||||
x:
|
||||
(workarea.scrollLeft +
|
||||
parseFloat(
|
||||
getComputedStyle(workarea, null).width.replace('px', '')
|
||||
) /
|
||||
2) /
|
||||
zoom,
|
||||
y:
|
||||
(workarea.scrollTop +
|
||||
parseFloat(
|
||||
getComputedStyle(workarea, null).height.replace('px', '')
|
||||
) /
|
||||
2) /
|
||||
zoom,
|
||||
zoom: zoomlevel
|
||||
},
|
||||
true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @fires module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate
|
||||
* @returns {void}
|
||||
*/
|
||||
* @fires module:svgcanvas.SvgCanvas#event:ext_toolButtonStateUpdate
|
||||
* @returns {void}
|
||||
*/
|
||||
updateToolButtonState () {
|
||||
const bNoFill = (this.editor.svgCanvas.getColor('fill') === 'none')
|
||||
const bNoStroke = (this.editor.svgCanvas.getColor('stroke') === 'none')
|
||||
const bNoFill = this.editor.svgCanvas.getColor('fill') === 'none'
|
||||
const bNoStroke = this.editor.svgCanvas.getColor('stroke') === 'none'
|
||||
const buttonsNeedingStroke = ['tool_fhpath', 'tool_line']
|
||||
const buttonsNeedingFillAndStroke = [
|
||||
'tools_rect', 'tools_ellipse',
|
||||
'tool_text', 'tool_path'
|
||||
'tools_rect',
|
||||
'tools_ellipse',
|
||||
'tool_text',
|
||||
'tool_path'
|
||||
]
|
||||
|
||||
if (bNoStroke) {
|
||||
@@ -120,8 +141,8 @@ class BottomPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
handleColorPicker (type, evt) {
|
||||
const { paint } = evt.detail
|
||||
this.editor.svgCanvas.setPaint(type, paint)
|
||||
@@ -129,44 +150,50 @@ class BottomPanel {
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
handleStrokeAttr (type, evt) {
|
||||
this.editor.svgCanvas.setStrokeAttr(type, evt.detail.value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
handleOpacity (evt) {
|
||||
const val = Number.parseInt(evt.currentTarget.value.split('%')[0])
|
||||
this.editor.svgCanvas.setOpacity(val / 100)
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
handlePalette (e) {
|
||||
e.preventDefault()
|
||||
// shift key or right click for stroke
|
||||
const { picker, color } = e.detail
|
||||
// Webkit-based browsers returned 'initial' here for no stroke
|
||||
const paint = color === 'none' ? new jGraduate.Paint() : new jGraduate.Paint({ alpha: 100, solidColor: color.substr(1) })
|
||||
const paint =
|
||||
color === 'none'
|
||||
? new jGraduate.Paint()
|
||||
: new jGraduate.Paint({ alpha: 100, solidColor: color.substr(1) })
|
||||
if (picker === 'fill') {
|
||||
$id('fill_color').setPaint(paint)
|
||||
} else {
|
||||
$id('stroke_color').setPaint(paint)
|
||||
}
|
||||
this.editor.svgCanvas.setColor(picker, color)
|
||||
if (color !== 'none' && this.editor.svgCanvas.getPaintOpacity(picker) !== 1) {
|
||||
if (
|
||||
color !== 'none' &&
|
||||
this.editor.svgCanvas.getPaintOpacity(picker) !== 1
|
||||
) {
|
||||
this.editor.svgCanvas.setPaintOpacity(picker, 1.0)
|
||||
}
|
||||
this.updateToolButtonState()
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
init () {
|
||||
// register actions for Bottom panel
|
||||
const template = document.createElement('template')
|
||||
@@ -177,26 +204,56 @@ class BottomPanel {
|
||||
$id('palette').addEventListener('change', this.handlePalette.bind(this))
|
||||
$id('palette').init(i18next)
|
||||
const { curConfig } = this.editor.configObj
|
||||
$id('fill_color').setPaint(new jGraduate.Paint({ alpha: 100, solidColor: curConfig.initFill.color }))
|
||||
$id('stroke_color').setPaint(new jGraduate.Paint({ alpha: 100, solidColor: curConfig.initStroke.color }))
|
||||
$id('zoom').addEventListener('change', (e) => this.changeZoom.bind(this)(e.detail.value))
|
||||
$id('stroke_color').addEventListener('change', (evt) => this.handleColorPicker.bind(this)('stroke', evt))
|
||||
$id('fill_color').addEventListener('change', (evt) => this.handleColorPicker.bind(this)('fill', evt))
|
||||
$id('stroke_width').addEventListener('change', this.changeStrokeWidth.bind(this))
|
||||
$id('stroke_style').addEventListener('change', (evt) => this.handleStrokeAttr.bind(this)('stroke-dasharray', evt))
|
||||
$id('stroke_linejoin').addEventListener('change', (evt) => this.handleStrokeAttr.bind(this)('stroke-linejoin', evt))
|
||||
$id('stroke_linecap').addEventListener('change', (evt) => this.handleStrokeAttr.bind(this)('stroke-linecap', evt))
|
||||
$id('fill_color').setPaint(
|
||||
new jGraduate.Paint({ alpha: 100, solidColor: curConfig.initFill.color })
|
||||
)
|
||||
$id('stroke_color').setPaint(
|
||||
new jGraduate.Paint({
|
||||
alpha: 100,
|
||||
solidColor: curConfig.initStroke.color
|
||||
})
|
||||
)
|
||||
$id('zoom').addEventListener('change', (e) =>
|
||||
this.changeZoom.bind(this)(e.detail.value)
|
||||
)
|
||||
$id('stroke_color').addEventListener('change', (evt) =>
|
||||
this.handleColorPicker.bind(this)('stroke', evt)
|
||||
)
|
||||
$id('fill_color').addEventListener('change', (evt) =>
|
||||
this.handleColorPicker.bind(this)('fill', evt)
|
||||
)
|
||||
$id('stroke_width').addEventListener(
|
||||
'change',
|
||||
this.changeStrokeWidth.bind(this)
|
||||
)
|
||||
$id('stroke_style').addEventListener('change', (evt) =>
|
||||
this.handleStrokeAttr.bind(this)('stroke-dasharray', evt)
|
||||
)
|
||||
$id('stroke_linejoin').addEventListener('change', (evt) =>
|
||||
this.handleStrokeAttr.bind(this)('stroke-linejoin', evt)
|
||||
)
|
||||
$id('stroke_linecap').addEventListener('change', (evt) =>
|
||||
this.handleStrokeAttr.bind(this)('stroke-linecap', evt)
|
||||
)
|
||||
$id('opacity').addEventListener('change', this.handleOpacity.bind(this))
|
||||
$id('fill_color').init(i18next)
|
||||
$id('stroke_color').init(i18next)
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {module}
|
||||
*/
|
||||
* @type {module}
|
||||
*/
|
||||
updateColorpickers (apply) {
|
||||
$id('fill_color').update(this.editor.svgCanvas, this.editor.selectedElement, apply)
|
||||
$id('stroke_color').update(this.editor.svgCanvas, this.editor.selectedElement, apply)
|
||||
$id('fill_color').update(
|
||||
this.editor.svgCanvas,
|
||||
this.editor.selectedElement,
|
||||
apply
|
||||
)
|
||||
$id('stroke_color').update(
|
||||
this.editor.svgCanvas,
|
||||
this.editor.selectedElement,
|
||||
apply
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -323,14 +323,16 @@ hr {
|
||||
|
||||
#tools_bottom {
|
||||
grid-area: bottom;
|
||||
overflow: auto;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
scrollbar-width: thin; /* Firefox */
|
||||
}
|
||||
|
||||
#tools_bottom ::-webkit-scrollbar { /* Chrome, Edge, and Safari */
|
||||
#tools_bottom::-webkit-scrollbar { /* Chrome, Edge, and Safari */
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
#tools_bottom se-list, #tools_bottom se-select {
|
||||
@@ -358,11 +360,11 @@ hr {
|
||||
width: 3px;
|
||||
}
|
||||
|
||||
#tools_left::-webkit-scrollbar-track {
|
||||
#tools_left::-webkit-scrollbar-track, #tools_bottom::-webkit-scrollbar-track{
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
#tools_left::-webkit-scrollbar-thumb {
|
||||
#tools_left::-webkit-scrollbar-thumb, #tools_bottom::-webkit-scrollbar-thumb {
|
||||
background-color:rgb(70, 70, 70);
|
||||
}
|
||||
|
||||
@@ -530,6 +532,9 @@ input[type=text] {
|
||||
|
||||
#palette {
|
||||
margin-left: auto;
|
||||
margin-right: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#stroke_expand {
|
||||
|
||||
Reference in New Issue
Block a user