This article has participated in the third session of the Denver Nuggets Creator camp. For details, see: Digg Project | Creator Camp third session is ongoing, “write” to make a personal impact.
preface
Last article we realized the auxiliary line of the picture editor, most tool types of software support undo and redo, strike while the iron is hot, our picture editor undo redo function to realize, enrich our picture editor function.
demo
Demo address
The implementation process
The principle of interpretation
Through the above demonstration, we analyze three types of operations: push,undo, and redo
1. Record the status during the operationpush
We can see from the flow chart that the normal operation can be directly recorded.
2. Cancel the operation during the operationundo
Through the flow chart we can see inCancel the 1
After the operation, the current state is displayed2 operation
In the state. Click furtherCancel the 2
Will come back toOperation 1
The state of the
3. Perform a redo operation during the operationrudo
Through the flow chart we can see the operationRedo 1
After that, the picture will go back to2 operation
In the state.
4. Record the status during the operationagain push
Note: at this point we can have two operations, one is to continue to click redo, the image will return to operation 3 state. We’re not going to draw a flowchart for that. The other can operate directly on the elements in the image, removing the state record of operation 3. The flow chart is as follows:
Code implementation
The general idea is that we use the state management library, through the way of snapshot, in the process of state changes recorded in the array, when undo through the index to show the state, when redo is also through the index to return to the previous state. Some state may be deleted as you continue
Define the data structure that holds the record
UndoRedoData: {activeSnapshot: null, snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshots snapshotsCopy the code
Updating Snapshot Data
- We defined the type of operation
type
, respectively,push
.undo
.redo
/ / operation type export type UndoRedoActionType = {type: 'push' | 'undo' | 'redo'; data: DatModelItem | null; };Copy the code
- perform
push
The operation code content is
If (type === 'push') {// Deep copy record to save const newData = _. CloneDeep (data); if (current === -1) { newUndoRedoData.snapshots = [...snapshots, newData]; } else {/ / current has withdrawn, again when you need to cancel some records newUndoRedoData. Snapshots = snapshots. Slice (0, current). The concat ([newData]); } / / reset the active data and index newUndoRedoData activeSnapshot = null; newUndoRedoData.current = -1; }Copy the code
Note: Since we are using the Flooks state library, it does not currently support immutable data, so we are using deep copy when reporting records, where there is a performance impact. If you don’t copy deeply, objects are passed, which can cause bugs. We will then modify the Flooks to support immutable data.
- perform
undo
The operation code content is
If (type === 'undo') {if (current === -1) {newundoredodata.mosnapshots. } else {newundoredodata. current = current-1; } / / set the current active snapshot data newUndoRedoData. ActiveSnapshot = snapshots [newUndoRedoData. Current]; }Copy the code
- perform
redo
The operation code content is
If (type === 'redo') {// If (current! = -1) { newUndoRedoData.current = current + 1; } / / redo operation has been to the final step, reset the activation index of state and the if (current = = = snapshots. The length of 1) {newUndoRedoData. ActiveSnapshot = null; newUndoRedoData.current = -1; } else { newUndoRedoData.activeSnapshot = snapshots[newUndoRedoData.current]; }}Copy the code
Set the threshold to prevent memory overflow
We have been adding records to the array, without making a judgment, the operation may cause memory burst. Set a threshold to determine when records go online. The following code
// Let threshold = 100; If (newUndoRedoData? .snapshots? .length > threshold) {/ / keep the last 100 data newUndoRedoData snapshots. = newUndoRedoData snapshots. The splice (threshold); }Copy the code
Here we use the Array splice method, and the negative values are taken from back to front.
Page logic
- Undo the rollback button
< Tooltip placement = "bottom" title = "undo" > < Button onClick = {undo} disabled = {undoRedoData. Snapshots. Length = = = 0 | | Undoredodata. current === 0} icon={<UndoOutlined />} /> <Tooltip placement="bottom" title=" rework "> <Button disabled={undoRedoData.current === -1} onClick={redo} icon={<RedoOutlined />} /> </Tooltip>Copy the code
The main attention here is to disable the judgment conditions.
- Home page rendering
Const getJsx = () = > {/ / have activated a snapshot of the data on how undo or redo operation const data = undoRedoData. ActiveSnapshot | | nodes; return data.map((item: DatModelItem) => { return getJsxItem(item); }); };Copy the code
address
- Demo address
- The code address
communication
Established a wechat communication group, if you need to communicate and discuss, please join.
The QR code has expired, please add wechat id Q1454763497, note image Editor, I will pull you into the group
conclusion
Above we have implemented the editor undo and redo, need to note that we had better use immutable data, using deep copy performance is not good, better use immer, we will change later. The general code introduction of the functional part has been described above. For more details, please go to the fast-image-editor. If you think it is helpful, please help star on Github.
Article history
- (Open source) Two weekends to write a picture editor
- (open source) added helper lines to the image editor