prev 2021-07-19Movidea Development Diary
The problem around the mouse event, the last time I did Regroup, I was not able to understand it properly because I became aware of it after it became quite complicated, but this time I was able to understand it.
The preferred, natural, "meaning chunk" for humans is the one on the left.
In reality, however, the browser specifications
At the time of Regroup, everything started mousedown, partly because everything was operated on the Canvas element.
Therefore, these
Looks good at first glance, but no.
With that in mind, how do we sort this situation out this time around?
What to do this time in light of this
Implement "Move Selection" and "Move Stickies Out of Group" and write a test case before refactoring.
2021-07-21 What I noticed after a night's sleep
Condition should be subject to testing
Now the local variable has state, but make it global before ts
let isDragging = false;
export const onMouseDown = (...) => {
isDragging = true;
...
};
export const onMouseMove = (...) => {
if (isDragging) {
...
}
};
export const onMouseUp = (...) => {
if (isDragging) {
...
isDragging = false;
}
};
after ts
export const onMouseDown = (...) => {
updateGlobal((g) => {
...
g.mouseState = "selecting";
});
};
export const onMouseMove = (...) => {
const g = getGlobal();
if (g.mouseState === "selecting") {
...
}
};
export const onMouseUp = (...) => {
const g = getGlobal();
if (g.mouseState === "selecting") {
updateGlobal((g) => {
...
g.mouseState = "selecting"; // intentional bug, should be ""
});
}
};
test test.ts
cy.get("#canvas").trigger("mousedown", 50, 100);
cy.getGlobal((g) => g.mouseState).should("to.eql", "selecting");
cy.get("#canvas").trigger("mouseup", 300, 400);
cy.getGlobal((g) => g.mouseState).should("to.eql", ""); // intentional fail
Now we can detect when we're in a strange state.
Yesterday's "I didn't realize that mousedown comes before dragstart" was verified with a test case. test.ts
cy.testid("1").trigger("dragstart", "center");
cy.getGlobal((g) => g.mouseState).should("to.eql", "");
cy.get("#canvas").trigger("drop", 250, 250);
I thought this would fail, but it doesn't. I see.
If you test this as if it were a real event, it would look like this test.ts
it("is not selecting", () => {
cy.testid("1").trigger("mousedown", "center");
cy.testid("1").trigger("mousemove", "center");
cy.testid("1").trigger("dragstart", "center");
cy.getGlobal((g) => g.mouseState).should("to.eql", "");
cy.get("#canvas").trigger("drop", 250, 250);
});
This fails as expected. And then stopPropagation and confirm that it works as expecteddone
So far, so good. Next, we'll discuss the "post-selection" condition I noticed this morning.
Decided to highlight the selected ones by lowering the opacity of the "not selected ones."
Oh, no, if dragging the "Show Selection" and the div that wraps the selected object are separated, then dragging the "Show Selection" won't move the selected object...
I was able to get to the point where I could select multiple items and drag them around, but the "Show Selection" is not moving.
It's done.
After writing the test case, it became clear that the position was off by only 2 pixels vertically from the expected position.
cy.getGlobal((g) => g.selected_items).should("to.eql", items);
cy.getGlobal((g) => items.map((id) => g.itemStore[id].position)).should(
"to.eql",
[
[0, 0],
[0, 200],
[200, 0],
[200, 200],
]
);
cy.get("#selection-view").trigger("dragstart", 0, 2); // misterious 2px
cy.get("#canvas").trigger("drop", 100, 100);
cy.getGlobal((g) => items.map((id) => g.itemStore[id].position)).should(
"to.eql",
[
[-50, -50],
[-50, 150],
[150, -50],
[150, 150],
]
);
This page is auto-translated from /nishio/2021-07-20Movidea開発日記 using DeepL. If you looks something interesting but the auto-translated English is not good enough to understand it, feel free to let me know at @nishio_en. I'm very happy to spread my thought to non-Japanese readers.