Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Layers: Layers are currently anonymous and cannot be identified by name/slug/id #24

Closed
kanarelo opened this issue Oct 11, 2021 · 4 comments
Labels
question Further information is requested wontfix This will not be worked on

Comments

@kanarelo
Copy link

kanarelo commented Oct 11, 2021

It would be lovely if Layers had a name or id to uniquely identify it. This would be handy when naming the layer inside the Canvas Editor.

Maybe create a LayerModel or something...

pikaso/src/Board/index.ts

Lines 28 to 297 in 48d0abd

public readonly layer: Konva.Layer
/**
* The html container element which the editor renders into that
*/
public readonly container: HTMLDivElement
/**
* The settings
*/
public readonly settings: Settings
/**
* The background of main layer that contains image and overlay
*
* @remark
* Background component is a not selectable shape that represents Image and Rect nodes.
* The nodes are accessible with `background.image` and `background.overlay` APIs
* @see [[https://konvajs.org/api/Konva.Image.html | Image]] and [[ https://konvajs.org/api/Konva.Rect.html | Rect]]
*
* @example
* ```ts
* editor.board.background.setImageFromUrl('<url>')
* ```
*
* @example
* ```ts
* editor.board.background.fill('rgba(0, 0, 0, 0.5)')
* ```
*
* @example
* ```ts
* editor.board.background.filter({
* name: 'Blur',
* options: {
* blurRadius: 20
* }
* })
* ```
*/
public readonly background: Background
/**
* The selection manager components that lets select and manage shapes with UI or API
*
* @example
* Selects all shapes
* ```ts
* editor.board.selection.selectAll()
* ```
*
* @example
* Deselects all shapes
* ```ts
* editor.board.selection.deselectAll()
* ```
*/
public readonly selection: Selection
/**
* Demonstrates the current active drawing. it's a string value or `null`.
*
* This property is managing by [[ShapeDrawer]] directly
*/
public activeDrawing: string | null = null
/**
* @see [[Events]]
*/
public readonly events: Events
/**
* @see [[History]]
*/
public readonly history: History
/**
* The array that contains all created shapes including active and deleted items. this property is managing by [[ShapeDrawer]] and [[Selection]]
*
* @see [[Board.addShape]] and [[Board.setShapes]]
*
*/
private shapesList: Array<ShapeModel> = []
/**
* Creates a new stage, layer, background and selection instance
*
* @param settings The [[Settings]]
* @param events The [[Events]]
* @param history The [[History]]
*/
constructor(settings: Settings, events: Events, history: History) {
this.settings = settings
this.history = history
this.events = events
const width = this.settings.width || this.settings.container.clientWidth
const height = this.settings.height || this.settings.container.clientHeight
this.stage = new Konva.Stage({
container: this.settings.container,
width,
height
})
// rename class name
this.stage.content.className = this.settings.containerClassName!
// set container position to center-center
Object.assign(this.stage.content.style, {
position: 'relative',
top: '50%',
left: '50%',
transform: 'translate(-50%,-50%)'
})
this.stage.on('widthChange', this.rescale.bind(this))
this.stage.on('heightChange', this.rescale.bind(this))
// disable context menu
if (this.settings.disableCanvasContextMenu) {
this.settings.container.addEventListener('contextmenu', (e: MouseEvent) =>
e.preventDefault()
)
}
this.layer = new Konva.Layer()
this.stage.add(this.layer)
this.background = new Background(this)
this.selection = new Selection(this)
this.container = this.settings.container
}
/**
* Calculates the board dimensions based on different components
*
* @returns [[Dimension]]
*/
public getDimensions() {
return {
width:
this.background.image.node.width() ||
this.background.overlay.node.width() ||
this.stage.width() ||
this.settings.width!,
height:
this.background.image.node.height() ||
this.background.overlay.node.height() ||
this.stage.height() ||
this.settings.height!
}
}
/**
* Returns all nodes in the main layer including background nodes
*
* @returns array of [[ShapeModel.node]]
*/
public getNodes() {
return [
...this.background.nodes,
...this.shapesList.map(shape => shape.node)
]
}
/**
* Returns all created shapes
*
* @see [[ShapeModel]]
*/
public get shapes() {
return this.shapesList
}
/**
* Returns all created shapes except deleted and hidden shpaes
*
* @see [[ShapeModel]]
*/
public get activeShapes() {
return this.shapesList.filter(shape => shape.isActive)
}
/**
* Add a new shape to the list of the shapes
*/
public addShape(shape: ShapeModel) {
this.shapesList.push(shape)
}
/**
* Updates list of the shapes
*/
public setShapes(shapes: ShapeModel[]) {
this.shapesList = shapes
}
/**
* Rescales the container based on its width and height
*/
public rescale() {
const transform = this.getContainerTransform()
if (this.stage.content.style.transform === transform) {
return
}
this.stage.content.style.transform = transform
this.events.emit('board:rescale', {
data: {
transform
}
})
}
/**
* Changes the active drawing mode
*
* @param drawType The drawing type string
*/
public setActiveDrawing(drawType: string | null) {
if (drawType) {
this.selection.transformer.hide()
this.draw()
}
if (drawType !== this.activeDrawing) {
this.events.emit('board:change-active-drawing', {
data: {
type: drawType
}
})
}
this.activeDrawing = drawType
}
/**
* Calculates the CSS transformations of board based on stage width and height
*
* @returns transform style of the container
*/
public getContainerTransform() {
const size = this.getDimensions()
let scale =
this.container.clientWidth < this.container.clientHeight
? this.stage.width() / size.width
: this.stage.height() / size.height
if (scale * this.stage.width() > this.container.clientWidth) {
scale = this.container.clientWidth / this.stage.width()
}
if (scale * this.stage.height() > this.container.clientHeight) {
scale = this.container.clientHeight / this.stage.height()
}
return `translate(-50%, -50%) scale(${scale.toFixed(6)})`
}
/**
* Redraws the main layer
*/
public draw() {
this.layer.batchDraw()
}

@kanarelo
Copy link
Author

kanarelo commented Oct 11, 2021

@raminious Sorry, this is confusing. Instead of editing above, let me expound. I noticed ShapeModel in Pikaso is the equivalent of a Layer in Konva.js.

So, I think we need to add a name or id to ShapeModel, to identify the Shape in the method. Although two shapes can have the same name? You decide.

public get shapes() {
    return this.shapesList
}

@raminious
Copy link
Contributor

@kanarelo actually, ShapeModel isn't equivalent to Layers in Konva.

This is architecture of Pikaso vs Konva

Konva Pikaso
Stage and Layer Board
Shape Shape Model and Shape Drawer

Konva suggests to not using many layers and I tried to follow it.
https://konvajs.org/docs/performance/Layer_Management.html#:~:text=Note%3A%20Do%20not%20create%20too,Usually%203%2D5%20is%20max.

Also you can pass name to shape when you creating that, like:

const rect = editor.shapes.rect.insert({
   name: '<name>',
   // rest config
})

and access that through

console.log(rect.node.name())

or change the name

rect.node.name('<new name>')

ps: IMO, it's better to use groups instead of having more layers although Pikaso doesn't support that yet, but I'm planning to work on its structure

@raminious raminious added the question Further information is requested label Oct 11, 2021
@raminious
Copy link
Contributor

#25

@kanarelo
Copy link
Author

Nice, I think this is much better than adding the name field. I need to read up on Konva.js deeper.

Just seen the #25. I think it's safe to close this issue.

@raminious raminious added the wontfix This will not be worked on label Oct 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

2 participants