Skip to content

Commit

Permalink
feat(painter): brush cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
surunzi committed Feb 16, 2024
1 parent c445ef4 commit de0ceeb
Show file tree
Hide file tree
Showing 9 changed files with 150 additions and 36 deletions.
23 changes: 13 additions & 10 deletions src/painter/icon.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@font-face {
font-family: 'luna-painter-icon';
src: url('data:application/x-font-woff;charset=utf-8;base64,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')
src: url('data:application/x-font-woff;charset=utf-8;base64,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')
format('woff');
}

Expand All @@ -17,30 +17,33 @@
.icon-brush:before {
content: '\f101';
}
.icon-eraser:before {
.icon-crosshair:before {
content: '\f102';
}
.icon-hand:before {
.icon-eraser:before {
content: '\f103';
}
.icon-paint-bucket:before {
.icon-hand:before {
content: '\f104';
}
.icon-pencil:before {
.icon-paint-bucket:before {
content: '\f105';
}
.icon-reset-color:before {
.icon-pencil:before {
content: '\f106';
}
.icon-swap:before {
.icon-reset-color:before {
content: '\f107';
}
.icon-zoom-in:before {
.icon-swap:before {
content: '\f108';
}
.icon-zoom-out:before {
.icon-zoom-in:before {
content: '\f109';
}
.icon-zoom:before {
.icon-zoom-out:before {
content: '\f10a';
}
.icon-zoom:before {
content: '\f10b';
}
6 changes: 6 additions & 0 deletions src/painter/icon/crosshair.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 7 additions & 6 deletions src/painter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export default class Painter extends Component<IOptions> {
private eraser: Eraser
private activeLayer: Layer
private resizeSensor: ResizeSensor
private canvasResizeSenor: ResizeSensor
private $foregroundColor: $.$
private $backgroundColor: $.$
constructor(container: HTMLElement, options: IOptions = {}) {
Expand Down Expand Up @@ -72,20 +71,19 @@ export default class Painter extends Component<IOptions> {
this.ctx = this.canvas.getContext('2d')!

this.resizeSensor = new ResizeSensor(container)
this.canvasResizeSenor = new ResizeSensor(this.canvas)

this.addLayer()
this.activeLayer = this.layers[0]

this.bindEvent()

this.brush = new Brush(this)
this.pencil = new Pencil(this)
this.hand = new Hand(this)
this.zoom = new Zoom(this)
this.paintBucket = new PaintBucket(this)
this.eraser = new Eraser(this)

this.bindEvent()

this.resetViewport()
this.hand.centerCanvas()

Expand All @@ -94,7 +92,6 @@ export default class Painter extends Component<IOptions> {
destroy() {
super.destroy()
this.resizeSensor.destroy()
this.canvasResizeSenor.destroy()
}
/** Add layer. */
addLayer() {
Expand Down Expand Up @@ -239,7 +236,11 @@ export default class Painter extends Component<IOptions> {
})

this.resizeSensor.addListener(this.onResize)
this.canvasResizeSenor.addListener(this.resetViewport)

this.zoom.on('change', () => {
this.currentTool.onZoom()
this.resetViewport()
})
}
private onViewportMouseEnter = (e: any) => {
this.currentTool.onMouseEnter(e.origEvent)
Expand Down
1 change: 1 addition & 0 deletions src/painter/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@
opacity: 0;
left: 0;
top: 0;
transform: translate(-50%, -50%);
.icon {
color: #000;
text-shadow: -1px -1px 0 $color-white, 1px -1px 0 $color-white,
Expand Down
29 changes: 23 additions & 6 deletions src/painter/tools/Brush.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import Painter, { Layer } from '../'
import defaults from 'licia/defaults'
import Tool from './Tool'
import nextTick from 'licia/nextTick'
import { CursorCircle } from './Pencil'

export default class Brush extends Tool {
private drawCtx: CanvasRenderingContext2D
private drawCanvas: HTMLCanvasElement
private brushCavnas: HTMLCanvasElement
private brushCtx: CanvasRenderingContext2D
private isDrawing = false
private cursorCircle: CursorCircle
private drawOptions: Required<IDrawOptions> = {
color: 'rgb(0,0,0)',
size: 4,
Expand All @@ -24,12 +26,24 @@ export default class Brush extends Tool {
hardness: 100,
}

this.cursorCircle = new CursorCircle(
this.cursor,
painter,
this.options.size
)

this.drawCanvas = document.createElement('canvas')
this.drawCtx = this.drawCanvas.getContext('2d')!

this.brushCavnas = document.createElement('canvas')
this.brushCtx = this.brushCavnas.getContext('2d')!
}
setOption(name: string, val: any, renderToolbar?: boolean) {
super.setOption(name, val, renderToolbar)
if (name === 'size') {
this.cursorCircle.setSize(val)
}
}
onDragStart(e: any, drawOptions: IDrawOptions = {}) {
super.onDragStart(e)

Expand Down Expand Up @@ -95,17 +109,20 @@ export default class Brush extends Tool {
this.commitDraw(this.ctx)
}
}
onZoom() {
this.cursorCircle.render()
}
private draw(x: number, y: number) {
const { canvas, drawCtx } = this
const { size } = this.options
const { size } = this.drawOptions

if (x < 0 || x > canvas.width || y < 0 || y > canvas.height) {
return
}

const centerX = size > 1 ? x - Math.floor((size - 1) / 2) : x
const centerY = size > 1 ? y - Math.floor((size - 1) / 2) : y
drawCtx.drawImage(this.brushCavnas, centerX, centerY)
const startX = size > 1 ? Math.round(x - size / 2) : x
const startY = size > 1 ? Math.round(y - size / 2) : y
drawCtx.drawImage(this.brushCavnas, startX, startY)
this.painter.renderCanvas()
}
protected renderToolbar() {
Expand Down Expand Up @@ -152,8 +169,8 @@ export default class Brush extends Tool {
brushCtx.clearRect(0, 0, size, size)
brushCtx.fillStyle = color === 'transparent' ? 'black' : color

const center = size / 2
let radius = size / 2
const center = Math.round(size / 2)
let radius = Math.round(size / 2)
const opacityStep = 1 / radius / ((105 - hardness) / 25)
let opacity = opacityStep
for (; radius > 0; radius--) {
Expand Down
17 changes: 17 additions & 0 deletions src/painter/tools/Eraser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import Tool from './Tool'
import Brush from './Brush'
import Pencil from './Pencil'
import Painter, { Layer } from '../'
import { CursorCircle } from './Pencil'

export default class Eraser extends Tool {
private cursorCircle: CursorCircle
constructor(painter: Painter) {
super(painter)

Expand All @@ -13,6 +15,18 @@ export default class Eraser extends Tool {
opacity: 100,
hardness: 100,
}

this.cursorCircle = new CursorCircle(
this.cursor,
painter,
this.options.size
)
}
setOption(name: string, val: any, renderToolbar?: boolean) {
super.setOption(name, val, renderToolbar)
if (name === 'size') {
this.cursorCircle.setSize(val)
}
}
onDragStart(e: any) {
this.getTool().onDragStart(e, this.getOptions())
Expand All @@ -26,6 +40,9 @@ export default class Eraser extends Tool {
onAfterRenderLayer(layer: Layer) {
this.getTool().onAfterRenderLayer(layer)
}
onZoom() {
this.cursorCircle.render()
}
private getTool(): Brush | Pencil {
return this.painter.getTool(this.options.mode) as any
}
Expand Down
65 changes: 62 additions & 3 deletions src/painter/tools/Pencil.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import Painter, { Layer } from '../'
import Tool from './Tool'
import $ from 'licia/$'
import Zoom from './Zoom'
import defaults from 'licia/defaults'
import nextTick from 'licia/nextTick'

export default class Pencil extends Tool {
private drawCtx: CanvasRenderingContext2D
private drawCanvas: HTMLCanvasElement
private isDrawing = false
private cursorCircle: CursorCircle
private drawOptions: Required<IDrawOptions> = {
color: 'rgb(0,0,0)',
size: 1,
Expand All @@ -20,9 +23,21 @@ export default class Pencil extends Tool {
opacity: 100,
}

this.cursorCircle = new CursorCircle(
this.cursor,
painter,
this.options.size
)

this.drawCanvas = document.createElement('canvas')
this.drawCtx = this.drawCanvas.getContext('2d')!
}
setOption(name: string, val: any, renderToolbar?: boolean) {
super.setOption(name, val, renderToolbar)
if (name === 'size') {
this.cursorCircle.setSize(val)
}
}
onDragStart(e: any, drawOptions: IDrawOptions = {}) {
super.onDragStart(e)

Expand Down Expand Up @@ -85,6 +100,9 @@ export default class Pencil extends Tool {
this.commitDraw(this.ctx)
}
}
onZoom() {
this.cursorCircle.render()
}
protected renderToolbar() {
super.renderToolbar()
const { toolbar, options } = this
Expand All @@ -111,9 +129,9 @@ export default class Pencil extends Tool {

const { size, color } = this.drawOptions
drawCtx.fillStyle = color === 'transparent' ? 'black' : color
const centerX = size > 1 ? x - Math.floor((size - 1) / 2) : x
const centerY = size > 1 ? y - Math.floor((size - 1) / 2) : y
drawCtx.fillRect(centerX, centerY, size, size)
const startX = size > 1 ? Math.round(x - size / 2) : x
const startY = size > 1 ? Math.round(y - size / 2) : y
drawCtx.fillRect(startX, startY, size, size)
this.painter.renderCanvas()
}
private commitDraw(ctx: CanvasRenderingContext2D) {
Expand All @@ -129,6 +147,47 @@ export default class Pencil extends Tool {
}
}

export class CursorCircle {
private $container: $.$
private painter: Painter
private size = 1
constructor(container: HTMLDivElement, painter: Painter, size: number) {
this.$container = $(container)
this.painter = painter

this.setSize(size)
}
setSize(size: number) {
this.size = size
this.render()
}
render = () => {
const { painter } = this
const zoom = painter.getTool('zoom') as Zoom
let { size } = this
if (zoom) {
size *= Math.round(zoom.getRatio())
}
let html = ''
if (size > 1) {
const viewportSize = size + 8
const circle = (r: number, color: string) => {
return `<circle cx="${viewportSize / 2}" cy="${
viewportSize / 2
}" r="${r}" style="fill:none;stroke:${color};stroke-width:1px;"/>`
}
html = `<svg width="${viewportSize}" height="${viewportSize}" viewBox="0 0 ${viewportSize} ${viewportSize}">
${circle(size / 2, '#000')}
${circle(size / 2 + 1, '#fff')}
${circle(size / 2 - 1, '#fff')}
</svg>`
} else {
html = painter.c('<span class="icon icon-crosshair"></span>')
}
this.$container.html(html)
}
}

interface IDrawOptions {
color?: string
size?: number
Expand Down
Loading

0 comments on commit de0ceeb

Please sign in to comment.