1. Select multiple modules to combine and disgroup
1, combination
Composition is to combine selected modules into a group
Selected module:
card.getActiveObject()
Copy the code
Group:
// group and re-render
card.getActiveObject().toGroup()
card.renderAll()
Copy the code
2. Split and combine
// Get the selected combination module, split the combination and re-render
card.getActiveObject().toActiveSelection();
card.renderAll()
Copy the code
The left and top child elements are not correct
Problem: Loading SVG using loadSVGFromString results in incorrect left and top submodules after rendering
Reason: This is because the SVG loaded by loadSVGFromString is formed into a combination, and the child elements in the combination are left and top based on the base point of the combination, which is the center point, not the vertex position of our usual canvas
So you can combine them first and then split them
fabric.loadSVGFromString(svgContext, (objects) = > {
// Group first
const group1 = new fabric.Group(objects, {
left: 0.top: 0
})
// Add the combination to card
card.add(group1)
// Set the combination to selected
card.setActiveObject(group1)
// Divide the selected group into groups
card.getActiveObject().toActiveSelection();
// Uncheck each separated module
card.discardActiveObject()
// re-render
card.renderAll()
})
Copy the code
3. Load the Canvas canvas grid transparent background of fabric.js
Problem: The canvas needs to load the grid transparent background when initializing, so that the user can feel it as a transparent layer, so that they can operate on it
You can load a RECT of a custom type and fill the RECT with a 100 * 100 grid
Let’s say I have a 100 by 100 grid
// Initialize a rect, set width, height, left, top, custom type, and unselectable (most importantly, this background is not selectable)
const shapeBg = new fabric.Rect({
width: card.width,
height: card.height,
left: 0.top: 0.fill: 'rgba(0, 0, 0, 0)'.myFabricType: 'bg'.selectable: false // Disable the check
})
card.add(shapeBg)
const url = 'Address of grid map'
// Load the grid diagram
fabric.util.loadImage(url, function(img) {
// Fill the rect with images and set repeat to repeat
shapeBg.set('fill'.new fabric.Pattern({
source: img,
repeat: 'repeat'
}))
/ / rendering
card.renderAll();
});
Copy the code
At this point card will render with a grid background
This recT must be loaded before rendering other modules. It is best to load this RECt when creating cards, otherwise there will be hierarchy problems
Write the blurred grid as an SVG and import it according to loadSVGFromString
Selectable: false is also required for imported SVG
Fabric.js loadSVGFromString Uncaught TypeError: Cannot set property ‘crossOrigin’ of undefined
In the fabric.js project, the SVG code generated by canvas.tosvg () is rendered by loadSVGFromString, causing an error
Error content
fabric.js:4477 Uncaught TypeError: Cannot set property 'crossOrigin' of undefined
at Object.fabric.parseSVGDocument (fabric.js:4477)
at Object.loadSVGFromString (fabric.js:4856)
at testFabric4.html:225
Copy the code
Cause: The generated SVG content header introduces the HTTP: link. Change it to HTTPS:
svgContext = svgContext.replace(/http:\/\//g.'https://')
fabric.loadSVGFromString(svgContext, () = > {
// ...
})
Copy the code
Fabric.js reverses, restores, and saves each step
const state = {
saveLen: 0.deleLen: 0.operIndex: -1
}
window.saveOperateList = []
window.deleteOperateList = []
const getters = {
}
const mutations = {
// Manipulate the saved data
OPERATE_OPERATE_DATA (state) {
const json = window.card.toDatalessJSON()
if (state.deleLen > 0) {
window.deleteOperateList.some(item= > {
window.saveOperateList[item].del = true
})
window.saveOperateList = window.saveOperateList.filter(item= > {
return! item.del })window.deleteOperateList = []
window.saveOperateList.push(json)
state.operIndex = window.saveOperateList.length - 1
} else {
window.saveOperateList.push(json)
state.operIndex += 1
}
state.saveLen = window.saveOperateList.length
state.deleLen = window.deleteOperateList.length
},
// Last step
PREV_STEP_OPERATE (state) {
if (state.operIndex > 0) {
window.card.loadFromJSON(window.saveOperateList[state.operIndex - 1]).renderAll()
if (window.deleteOperateList.includes(state.operIndex - 1)) {}else {
window.deleteOperateList.push(state.operIndex)
state.operIndex -= 1
}
}
state.saveLen = window.saveOperateList.length
state.deleLen = window.deleteOperateList.length
},
// Next step
NEXT_STEP_OPERATE (state) {
if (state.operIndex + 1> =window.saveOperateList.length) {
return
}
window.card.loadFromJSON(window.saveOperateList[state.operIndex + 1]).renderAll()
if (window.deleteOperateList.includes(state.operIndex + 1)) {
const index = window.deleteOperateList.indexOf(state.operIndex + 1)
window.deleteOperateList.splice(index, 1)}else {
}
state.operIndex = state.operIndex + 1
state.saveLen = window.saveOperateList.length
state.deleLen = window.deleteOperateList.length
}
}
const actions = {
}
export default { state, getters, mutations, actions }
Copy the code
Field Description:
saveLen
: Saves the data for each stepsaveOperateList
The length of thedeleLen
: The data of each step needs to be deleteddeleteOperateList
The length of theoperIndex
: Indicates the Index value of the operationwindow.saveOperateList
: Saved data. The saved value is the JSON data of each stepwindow.deleteOperateList
: The data list to be deleted in each step is saved assaveOperateList
Every step of the wayindex
The value of the
Ideas:
- Save operation records:
deleLen <= 0
That is, no operation record needs to be deleted- define
json
:const json = window.card.toDatalessJSON()
- to
saveOperateList
Push data in:window.saveOperateList.push(json)
operIndex
Increment the value of:state.operIndex += 1
- define
deleLen > 0
When, that is, there is data to delete operation records- traverse
deleteOperateList
An array,saveOperateList[item]
Plus one for each objectdel
Property (value to be deleted) filter``saveOperateList
Array, there aredel
Attribute filteringdeleteOperateList
The assignment for[]
saveOperateList
Add new data- Set up the
operIndex
The value of the
- traverse
- Set up the
saveLen
和deleLen
The value of the
- Undo/Previous Step:
- if
operIndex > 0
- Load last saved data:
window.card.loadFromJSON(window.saveOperateList[state.operIndex - 1]).renderAll()
- if
deleteOperateList
Contains the currentoperIndex - 1
Do not enter any operation, otherwise theoperIndex
push
进deleteOperateList
In the - Then put the
operIndex - 1
- Load last saved data:
- if
operIndex <= 0
If no operation is performed, the undo (previous) operation cannot be performed - Set up the
saveLen
和deleLen
The value of the
- if
- Recovery/Next Steps:
- if
operIndex + 1 > saveOperateList.length
If no operation is performed, the recovery cannot be performedreturn
Can be - loading
operIndex + 1
Data:window.card.loadFromJSON(window.saveOperateList[state.operIndex + 1]).renderAll()
- if
deleteOperateList
containsoperIndex + 1
The value of fromdeleteOperateList
Delete this value from; If it is not included, it is not deleted - Set up the
operIndex
The value of the - Set up the
saveLen
和deleLen
The value of the
- if
At this point, a data saving, undo, restore the whole process is completed
Due to the setoperIndex
It’s minus 1, so it needs to becard
Save initialization during initializationjson
Data, called once after initialization is completeOPERATE_OPERATE_DATA
function
Call OPERATE_OPERATE_DATA for each subsequent operation, PREV_STEP_OPERATE for each undo, and NEXT_STEP_OPERATE for each restore
Denver annual essay | 2020 technical way with me The campaign is under way…