move was not properly handling when a transform was already on the element

This commit is contained in:
JFH
2022-01-01 09:27:35 -03:00
parent 91294e9933
commit b10f4be943

View File

@@ -34,7 +34,7 @@ export const init = (canvas) => {
svgCanvas = canvas
}
export const getBsplinePoint = (t) => {
const getBsplinePoint = (t) => {
const spline = { x: 0, y: 0 }
const p0 = { x: svgCanvas.getControllPoint2('x'), y: svgCanvas.getControllPoint2('y') }
const p1 = { x: svgCanvas.getControllPoint1('x'), y: svgCanvas.getControllPoint1('y') }
@@ -70,6 +70,25 @@ export const getBsplinePoint = (t) => {
}
}
// update the dummy transform in our transform list
// to be a translate. We need to check if there was a transformation
// to avoid loosing it
const updateTransformList = (svgRoot, element, dx, dy) => {
const xform = svgRoot.createSVGTransform()
xform.setTranslate(dx, dy)
const tlist = element.transform?.baseVal
if (tlist.numberOfItems) {
const firstItem = tlist.getItem(0)
if (firstItem.type === 2) { // SVG_TRANSFORM_TRANSLATE = 2
tlist.replaceItem(xform, 0)
} else {
tlist.insertItemBefore(xform, 0)
}
} else {
tlist.appendItem(xform)
}
}
/**
*
* @param {MouseEvent} evt
@@ -78,12 +97,16 @@ export const getBsplinePoint = (t) => {
* @returns {void}
*/
export const mouseMoveEvent = (evt) => {
// if the mouse is move without dragging an element, just return.
if (!svgCanvas.getStarted()) { return }
if (evt.button === 1 || svgCanvas.spaceKey) { return }
evt.preventDefault()
const selectedElements = svgCanvas.getSelectedElements()
const zoom = svgCanvas.getZoom()
const svgRoot = svgCanvas.getSvgRoot()
if (!svgCanvas.getStarted()) { return }
if (evt.button === 1 || svgCanvas.spaceKey) { return }
const selected = selectedElements[0]
let i
let xya
@@ -94,7 +117,7 @@ export const mouseMoveEvent = (evt) => {
let len
let angle
let box
let selected = selectedElements[0]
const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm())
const mouseX = pt.x * zoom
const mouseY = pt.y * zoom
@@ -110,14 +133,13 @@ export const mouseMoveEvent = (evt) => {
y = snapToGrid(y)
}
evt.preventDefault()
let tlist
switch (svgCanvas.getCurrentMode()) {
case 'select': {
// we temporarily use a translate on the element(s) being dragged
// this transform is removed upon mousing up and the element is
// relocated to the new location
if (selectedElements[0] !== null) {
if (selected) {
dx = x - svgCanvas.getStartX()
dy = y - svgCanvas.getStartY()
if (svgCanvas.getCurConfig().gridSnapping) {
@@ -125,35 +147,20 @@ export const mouseMoveEvent = (evt) => {
dy = snapToGrid(dy)
}
if (dx !== 0 || dy !== 0) {
len = selectedElements.length
for (i = 0; i < len; ++i) {
selected = selectedElements[i]
if (isNullish(selected)) { break }
// update the dummy transform in our transform list
// to be a translate
const xform = svgRoot.createSVGTransform()
tlist = selected.transform?.baseVal
// Note that if Webkit and there's no ID for this
// element, the dummy transform may have gotten lost.
// This results in unexpected behaviour
xform.setTranslate(dx, dy)
if (tlist.numberOfItems) {
tlist.replaceItem(xform, 0)
} else {
tlist.appendItem(xform)
}
if (dx || dy) {
selectedElements.forEach((el) => {
if (el) {
updateTransformList(svgRoot, el, dx, dy)
// update our internal bbox that we're tracking while dragging
svgCanvas.selectorManager.requestSelector(selected).resize()
svgCanvas.selectorManager.requestSelector(el).resize()
}
})
svgCanvas.call('transition', selectedElements)
}
}
break
} case 'multiselect': {
}
case 'multiselect': {
realX *= zoom
realY *= zoom
assignAttributes(svgCanvas.getRubberBox(), {
@@ -194,7 +201,8 @@ export const mouseMoveEvent = (evt) => {
}
break
} case 'resize': {
}
case 'resize': {
// we track the resize bounding box and translate/scale the selected element
// while the mouse is down, when mouse goes up, we use this to recalculate
// the shape's coordinates
@@ -285,7 +293,8 @@ export const mouseMoveEvent = (evt) => {
svgCanvas.call('transition', selectedElements)
break
} case 'zoom': {
}
case 'zoom': {
realX *= zoom
realY *= zoom
assignAttributes(svgCanvas.getRubberBox(), {
@@ -295,13 +304,15 @@ export const mouseMoveEvent = (evt) => {
height: Math.abs(realY - svgCanvas.getRStartY() * zoom)
}, 100)
break
} case 'text': {
}
case 'text': {
assignAttributes(shape, {
x,
y
}, 1000)
break
} case 'line': {
}
case 'line': {
if (svgCanvas.getCurConfig().gridSnapping) {
x = snapToGrid(x)
y = snapToGrid(y)
@@ -319,12 +330,10 @@ export const mouseMoveEvent = (evt) => {
shape.setAttribute('x2', x2)
shape.setAttribute('y2', y2)
break
} case 'foreignObject':
// fall through
}
case 'foreignObject': // fall through
case 'square':
// fall through
case 'rect':
// fall through
case 'image': {
const square = (svgCanvas.getCurrentMode() === 'square') || evt.shiftKey
let
@@ -355,7 +364,8 @@ export const mouseMoveEvent = (evt) => {
}, 1000)
break
} case 'circle': {
}
case 'circle': {
cx = Number(shape.getAttribute('cx'))
cy = Number(shape.getAttribute('cy'))
let rad = Math.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))
@@ -364,7 +374,8 @@ export const mouseMoveEvent = (evt) => {
}
shape.setAttribute('r', rad)
break
} case 'ellipse': {
}
case 'ellipse': {
cx = Number(shape.getAttribute('cx'))
cy = Number(shape.getAttribute('cy'))
if (svgCanvas.getCurConfig().gridSnapping) {
@@ -422,8 +433,8 @@ export const mouseMoveEvent = (evt) => {
svgCanvas.setStart({ x: svgCanvas.getEnd('x'), y: svgCanvas.getEnd('y') })
break
// update path stretch line coordinates
} case 'path':
// fall through
}
case 'path': // fall through
case 'pathedit': {
x *= zoom
y *= zoom
@@ -461,7 +472,8 @@ export const mouseMoveEvent = (evt) => {
svgCanvas.pathActions.mouseMove(x, y)
break
} case 'textedit': {
}
case 'textedit': {
x *= zoom
y *= zoom
// if (svgCanvas.getRubberBox() && svgCanvas.getRubberBox().getAttribute('display') !== 'none') {
@@ -476,7 +488,8 @@ export const mouseMoveEvent = (evt) => {
svgCanvas.textActions.mouseMove(mouseX, mouseY)
break
} case 'rotate': {
}
case 'rotate': {
box = getBBox(selected)
cx = box.x + box.width / 2
cy = box.y + box.height / 2
@@ -496,7 +509,9 @@ export const mouseMoveEvent = (evt) => {
svgCanvas.setRotationAngle(angle < -180 ? (360 + angle) : angle, true)
svgCanvas.call('transition', selectedElements)
break
} default:
}
default:
console.error(`unknown mode=${svgCanvas.getCurrentMode()}`)
break
}
@@ -543,12 +558,13 @@ export const mouseOutEvent = () => {
* @returns {void}
*/
export const mouseUpEvent = (evt) => {
if (evt.button === 2) { return }
if (!svgCanvas.getStarted()) { return }
const selectedElements = svgCanvas.getSelectedElements()
const zoom = svgCanvas.getZoom()
if (evt.button === 2) { return }
const tempJustSelected = svgCanvas.getJustSelected()
svgCanvas.setJustSelected(null)
if (!svgCanvas.getStarted()) { return }
const pt = transformPoint(evt.clientX, evt.clientY, svgCanvas.getrootSctm())
const mouseX = pt.x * zoom
const mouseY = pt.y * zoom
@@ -587,6 +603,10 @@ export const mouseUpEvent = (evt) => {
case 'image':
case 'foreignObject':
break
case 'text':
svgCanvas.setCurText('font_size', selected.getAttribute('font-size'))
svgCanvas.setCurText('font_family', selected.getAttribute('font-family'))
// fallthrough
default:
svgCanvas.setCurProperties('fill', selected.getAttribute('fill'))
svgCanvas.setCurProperties('fill_opacity', selected.getAttribute('fill-opacity'))
@@ -597,11 +617,6 @@ export const mouseUpEvent = (evt) => {
svgCanvas.setCurProperties('stroke_linejoin', selected.getAttribute('stroke-linejoin'))
svgCanvas.setCurProperties('stroke_linecap', selected.getAttribute('stroke-linecap'))
}
if (selected.tagName === 'text') {
svgCanvas.setCurText('font_size', selected.getAttribute('font-size'))
svgCanvas.setCurText('font_family', selected.getAttribute('font-family'))
}
svgCanvas.selectorManager.requestSelector(selected).showGrips(true)
}
// always recalculate dimensions to strip off stray identity transforms
@@ -786,7 +801,7 @@ export const mouseUpEvent = (evt) => {
mouse_y: mouseY
}, true)
extResult.forEach(function (r) {
extResult.forEach((r) => {
if (r) {
keep = r.keep || keep;
({ element } = r)
@@ -847,7 +862,7 @@ export const mouseUpEvent = (evt) => {
// Ideally this would be done on the endEvent of the animation,
// but that doesn't seem to be supported in Webkit
setTimeout(function () {
setTimeout(() => {
if (cAni) { cAni.remove() }
element.setAttribute('opacity', curShape.opacity)
element.setAttribute('style', 'pointer-events:inherit')