Skip to content

Commit

Permalink
feat(painter): hand tool
Browse files Browse the repository at this point in the history
  • Loading branch information
surunzi committed Jan 24, 2024
1 parent bff34b6 commit eb9fb75
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 10 deletions.
68 changes: 64 additions & 4 deletions src/painter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import Component, { IComponentOptions } from '../share/Component'
import stripIndent from 'licia/stripIndent'
import $ from 'licia/$'
import each from 'licia/each'
import { exportCjs, drag } from '../share/util'
import ResizeSensor from 'licia/ResizeSensor'
import { exportCjs, drag, measuredScrollbarWidth } from '../share/util'
import { Brush, Pencil, Hand, Tool } from './tools'

const $document = $(document as any)
Expand All @@ -28,6 +29,8 @@ export default class Painter extends Component<IOptions> {
private $tools: $.$
private $canvas: $.$
private $viewport: $.$
private viewport: HTMLDivElement
private $body: $.$
private canvas: HTMLCanvasElement
private ctx: CanvasRenderingContext2D
private layers: Layer[] = []
Expand All @@ -36,6 +39,7 @@ export default class Painter extends Component<IOptions> {
private pencil: Pencil
private hand: Hand
private activeLayer: Layer
private resizeSensor: ResizeSensor
constructor(container: HTMLElement, options: IOptions = {}) {
super(container, { compName: 'painter' }, options)

Expand All @@ -50,9 +54,16 @@ export default class Painter extends Component<IOptions> {
this.$tools = this.find('.tools')
this.$canvas = this.find('.main-canvas')
this.$viewport = this.find('.viewport')
this.viewport = this.$viewport.get(0) as HTMLDivElement
this.$body = this.find('.body')
this.canvas = this.$canvas.get(0) as HTMLCanvasElement
this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D

this.resizeSensor = new ResizeSensor(container)

this.resetViewport()
this.centerCanvas()

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

Expand All @@ -64,6 +75,10 @@ export default class Painter extends Component<IOptions> {

this.useTool(this.options.tool)
}
destroy() {
super.destroy()
this.resizeSensor.destroy()
}
/** Add layer. */
addLayer() {
const { width, height } = this.options
Expand Down Expand Up @@ -125,9 +140,11 @@ export default class Painter extends Component<IOptions> {
</div>
</div>
<div class="viewport">
<div class="canvas-wrapper">
<div class="canvas-container">
<canvas class="main-canvas" width="${width}" height="${height}"></canvas>
<div class="body">
<div class="canvas-wrapper">
<div class="canvas-container">
<canvas class="main-canvas" width="${width}" height="${height}"></canvas>
</div>
</div>
</div>
</div>
Expand All @@ -144,6 +161,8 @@ export default class Painter extends Component<IOptions> {
const $this = $(this)
self.useTool($this.data('tool'))
})

this.resizeSensor.addListener(this.onResize)
}
private onViewportDragStart = (e: any) => {
this.currentTool.onDragStart(e.origEvent)
Expand All @@ -158,6 +177,47 @@ export default class Painter extends Component<IOptions> {
$document.off(drag('move'), this.onViewportDragMove)
$document.off(drag('end'), this.onViewportDragEnd)
}
private onResize = () => {
this.resetViewport()

const { $canvas } = this
const { width: canvasWidth, height: canvasHeight } = $canvas.offset()
const { width: viewportWidth, height: viewportHeight } =
this.getViewportSize()
if (canvasWidth < viewportWidth && canvasHeight < viewportHeight) {
this.centerCanvas()
}
}
private resetViewport() {
const { $body, $canvas } = this
const { width: canvasWidth, height: canvasHeight } = $canvas.offset()
const { width: viewportWidth, height: viewportHeight } =
this.getViewportSize()
const width = (viewportWidth - Math.min(canvasWidth, 100)) * 2 + canvasWidth
const height =
(viewportHeight - Math.min(canvasHeight, 100)) * 2 + canvasHeight
$body.css({
width,
height,
})
}
private centerCanvas() {
const { viewport } = this
const { width: viewportWidth, height: viewportHeight } =
this.getViewportSize()
viewport.scrollLeft = (viewport.scrollWidth - viewportWidth) / 2
viewport.scrollTop = (viewport.scrollHeight - viewportHeight) / 2
}
private getViewportSize() {
let { width, height } = this.$viewport.offset()
const scrollbarSize = measuredScrollbarWidth()
width -= scrollbarSize
height -= scrollbarSize
return {
width,
height,
}
}
}

class Layer {
Expand Down
19 changes: 17 additions & 2 deletions src/painter/story.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'luna-painter.css'
import Painter from 'luna-painter.js'
import story from '../share/story'
import readme from './README.md'
import { number } from '@storybook/addon-knobs'
import $ from 'licia/$'

const def = story(
Expand All @@ -14,9 +15,23 @@ const def = story(
margin: '0 auto',
})

const width = number('Width', 512, {
range: true,
min: 128,
max: 2048,
step: 2,
})

const height = number('Height', 512, {
range: true,
min: 128,
max: 2048,
step: 2,
})

const painter = new Painter(container, {
width: 512,
height: 512,
width,
height,
tool: 'pencil',
})

Expand Down
5 changes: 5 additions & 0 deletions src/painter/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,12 @@
height: 100%;
overflow: auto;
background: $color-text-secondary;
}

.body {
display: flex;
width: 100%;
height: 100%;
}

.canvas-wrapper {
Expand Down
33 changes: 29 additions & 4 deletions src/painter/tools.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Painter from './index'
import $ from 'licia/$'
import types from 'licia/types'
import { eventPage } from '../share/util'
import { eventPage, eventClient } from '../share/util'

export class Tool {
protected painter: Painter
Expand Down Expand Up @@ -29,8 +29,8 @@ export class Tool {
const pageX = eventPage('x', e)
const pageY = eventPage('y', e)

let x = Math.floor(((pageX - offset.left) / offset.width) * canvas.width)
let y = Math.floor(((pageY - offset.top) / offset.height) * canvas.height)
const x = Math.floor(((pageX - offset.left) / offset.width) * canvas.width)
const y = Math.floor(((pageY - offset.top) / offset.height) * canvas.height)

this.lastX = this.x
this.x = x
Expand Down Expand Up @@ -85,7 +85,32 @@ export class Pencil extends Tool {
}

export class Hand extends Tool {
private $viewport: $.$
private viewport: HTMLDivElement
private startX = 0
private startY = 0
private startScrollLeft = 0
private startScrollTop = 0
constructor(painter: Painter) {
super(painter)

this.$viewport = painter.$container.find(painter.c('.viewport'))
this.viewport = this.$viewport.get(0) as HTMLDivElement
}
onDragStart(e: any) {
const { viewport } = this

this.startX = eventClient('x', e)
this.startY = eventClient('y', e)
this.startScrollLeft = viewport.scrollLeft
this.startScrollTop = viewport.scrollTop
}
onDragMove(e: any) {
super.onDragMove(e)
const { viewport } = this

const deltaX = eventClient('x', e) - this.startX
const deltaY = eventClient('y', e) - this.startY
viewport.scrollLeft = this.startScrollLeft - deltaX
viewport.scrollTop = this.startScrollTop - deltaY
}
}

0 comments on commit eb9fb75

Please sign in to comment.