diff --git a/src/painter/icon.css b/src/painter/icon.css
index 2747e44..1647a62 100644
--- a/src/painter/icon.css
+++ b/src/painter/icon.css
@@ -1,6 +1,6 @@
@font-face {
font-family: 'luna-painter-icon';
- src: url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAiQAAsAAAAADegAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAAL0AAAEsJb0pWk9TLzIAAAHIAAAAQAAAAFZLyUlJY21hcAAAAggAAAElAAADPhTycVRnbHlmAAADMAAAAuMAAARAp2VqGGhlYWQAAAYUAAAANAAAADZzrb5AaGhlYQAABkgAAAAeAAAAJAGRAOdobXR4AAAGaAAAABkAAAB8B9H//WxvY2EAAAaEAAAAIQAAAEAacBuIbWF4cAAABqgAAAAfAAAAIAEtAEluYW1lAAAGyAAAASkAAAIWm5e+CnBvc3QAAAf0AAAAmQAAANgGS5KleJxNjs0OATEUhb/6m2EG9TeGIhZWVp5ALMRKrCxtZiWSiZXH8VAeyWmFaHPbfvfcnnsxQIsNWyr7w/FMpywed6bU+Cyv/79NebsWxF+SVgt3rHgRMWTFjhMX7jyDbqiT0qZDN3CDBCuyZIzJcermVOG1SDGjJxdPVUWPPoNAFf1Mxf5nGmiprM+MVOO9EnXJmQTnunSrfC51KqdY55qmbqe9ULVTdSaOfhnv05Lnh42URP5+bquJ5m9G0A5aAAAAeJxjYGRwZJzAwMrAwFDH0AMkZaB0AgMngzEDAxMDKzMDVhCQ5prCcIBB9yMXwwkgV4jhNAMLkGYEyQEAaFgIoHiczdLbTsJAEMbxf6GcyrmcQbnkCh4KlUSCB4ISDM/hA3nl+/QJ8Jvu3BgTE++c5NdJp9vubHeBElCUpcQQfRJh8aFqlNeLJHk95l33KR1VCqzYsGXPkRPnLLlc9GzFmnt2HPJalNe+R6T3U6ZcsdCXl/msI7rUGdPTl9sMmOj5XKNm9GnQYkhT46/1bkEzx+q4TIUqtbyv8o85fo/RH8dbdOvjXgfa6m06T2dqqzW0ntTUv4iGXaI3v5tjOxHYateuKzeuLrduLHeuJxunFWs3g7Zs3UB2biIPbiqPznp4cqk8u5nsXV8Ozlbw4lry6oZydE05Of17zk6bkEWBndisEGC5GNgJz+LATnlWCuz0Z+UAy5UAy9UAy7UAy0lA8gWi2zmpAAAAeJyNk0Fv0zAUgP0cx04TN1naNG5p0kK7JtrWbWraNBulq4Y0JBASgmknhMQBblwQcAGEtBu3XcZPQOLAFSHQEEJCMMRfQoyXbExwgry8l+fn5/izn00oIUc/yDeUMmkTkgneWYVoNINx4nvChngD4jTaoL5qgce/blFG60BvUsbuelld2pomXKVKXIgPtyltUB0uA9Nf1oyyVitTWa9wbvJK1SX40NyQA/KOCCIJmUEs1DBdgjhT4vHFycPRkzveQr+/MN2cPEpl7hECR0fFmEOyjnSjqMND5OhEUzj2Y7ReG1owgWQDfkf/zMj99L5hCqYzYYk6K5f0vjznGpWz1dMo07UDXQj9Bi6MbumGod/zdbPMFmUZ067ngf5p11buIZVWrOcLyjxJyHnkGydtKIyvUGyI0gh3cgbFrq4ArjgaKaF8z4E8IlR2wp81ucOrJa3MrlGwAIRlANV0gFvMYpsM2HKNXzLOUADKaePC5s1nlGnU4x+5XjF1dpVSx7EsEDrVOGf6tsZmODCr6nOmiUWhQGn98uz6NmiMVg2kZgX7IQrDaljEyWtfG2YiVSnWYwZK7O+P9g968oosy548fDHcf97rJdjsoZzU8j2KhieHZGm3plCHtS7avd3Xob3jrO/uLj1wduwQM6HI/0w+kQpmx6MVWIJUqDRL/BC6KnsFbkNOhsnAkK3xYC2rNOxGstoEyxgMBqd7/Ya8JU2ySi7gP7rpaAk6OBjVm0ANNZnCEHWk8NSuUJu26DhTPs4R29jewDZ/qkBCHfCVoOg4lMIMoig0zaA77wS0BMtWu+0bhl/Y+02AJmaefG4Eznw3MM0wigJTyBCg1LV+56L9i9PC+9TPOY/5/sU1BZj+mwch/o+DHv0s6vuduKSFFL4SMY+jeAWK6fICdGzwWvmt2YuqlbV2J6hYXAa9Xttltht2AtcNOqF7Jaq6azVDqLmo17SEihYDN3SxP5ybC8kva6h8LgB4nGNgZGBgAOLeVMb58fw2Xxm4GU4ABaI4H+9rgNH///3/w3CS4TRQJQcDE5BkAAB08A6neJxjYGRgYDjBAAIn/v/7/5/hJAMjAyqQBwCUsQZ2AAB4nGNgAIITMPz/P4KNjv//Y6AyAACR+QvMAAAAeJxjYAACM4YAhnkMfxhlGE0YQxhXML5hUiAWAgAUewcoAAAAeJxjYGRgYJBnsGVgYQABJiDmAkIGhv9gPgMAEeABdwB4nGWQPW7CQBSEx2BIAlKCFCkps1UKIpmfkgNAT0GXwpi1MbK91npBossJcoQcIaeIcoIcKGPzaGAtP38zb97uygAG+IWHenm4bWq9WrihOnGb9CDsk5+FO+jjRbhLfyjcwxumwn084p07eP4dnQFK4Rbu8SHcpv8p7JO/hDt4wrdwl/6PcA8r/An38eoN08gUsSncUif7LLRnef6utK1SU6hJMD5bC11oGzq9Ueujqg7J1LlYxdbkas6uzjKjSmt2OnLB1rlyNhrF4geRyZEigkGBuKkOS2gk2CNDCHvVvdQrpi0q+rVWmCDA+Cq1YKpokiGVxobJNY6sFQ48bUrXMa34Ws7kpLnMat4kIyv+77q3oxPRD7BtpkrMMOITX+SD5g75Pz0RXqgAAAB4nF3GWQ6CMAAA0Q4CbrjvuxfgUAWbQMSWtCUknt6o8cf5eSMC8e3nfxcCOoRExHTp0WfAkIQRYyZMmTFnwZIVazZs2bHnwJETZy5cRZTZxhWxstIpGxZS35JaltqnWZPflY9rpfOyGlrllE9zUxkbulbW3acxj7TUvY+m8eF7yLA0OAoUEs2NmhJPSs6dCkPLk4cQL8LFJmsAAAA=')
+ src: url('data:application/x-font-woff;charset=utf-8;base64,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')
format('woff');
}
@@ -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';
+}
diff --git a/src/painter/icon/crosshair.svg b/src/painter/icon/crosshair.svg
new file mode 100644
index 0000000..37ffd37
--- /dev/null
+++ b/src/painter/icon/crosshair.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/src/painter/index.ts b/src/painter/index.ts
index 3b8b5f0..50dcc1a 100644
--- a/src/painter/index.ts
+++ b/src/painter/index.ts
@@ -43,7 +43,6 @@ export default class Painter extends Component {
private eraser: Eraser
private activeLayer: Layer
private resizeSensor: ResizeSensor
- private canvasResizeSenor: ResizeSensor
private $foregroundColor: $.$
private $backgroundColor: $.$
constructor(container: HTMLElement, options: IOptions = {}) {
@@ -72,13 +71,10 @@ export default class Painter extends Component {
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)
@@ -86,6 +82,8 @@ export default class Painter extends Component {
this.paintBucket = new PaintBucket(this)
this.eraser = new Eraser(this)
+ this.bindEvent()
+
this.resetViewport()
this.hand.centerCanvas()
@@ -94,7 +92,6 @@ export default class Painter extends Component {
destroy() {
super.destroy()
this.resizeSensor.destroy()
- this.canvasResizeSenor.destroy()
}
/** Add layer. */
addLayer() {
@@ -239,7 +236,11 @@ export default class Painter extends Component {
})
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)
diff --git a/src/painter/style.scss b/src/painter/style.scss
index 7954295..2749440 100644
--- a/src/painter/style.scss
+++ b/src/painter/style.scss
@@ -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,
diff --git a/src/painter/tools/Brush.ts b/src/painter/tools/Brush.ts
index fb08e3d..b682cc4 100644
--- a/src/painter/tools/Brush.ts
+++ b/src/painter/tools/Brush.ts
@@ -2,6 +2,7 @@ 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
@@ -9,6 +10,7 @@ export default class Brush extends Tool {
private brushCavnas: HTMLCanvasElement
private brushCtx: CanvasRenderingContext2D
private isDrawing = false
+ private cursorCircle: CursorCircle
private drawOptions: Required = {
color: 'rgb(0,0,0)',
size: 4,
@@ -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)
@@ -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() {
@@ -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--) {
diff --git a/src/painter/tools/Eraser.ts b/src/painter/tools/Eraser.ts
index 4424dff..e22f485 100644
--- a/src/painter/tools/Eraser.ts
+++ b/src/painter/tools/Eraser.ts
@@ -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)
@@ -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())
@@ -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
}
diff --git a/src/painter/tools/Pencil.ts b/src/painter/tools/Pencil.ts
index b2e8e4d..5d80c49 100644
--- a/src/painter/tools/Pencil.ts
+++ b/src/painter/tools/Pencil.ts
@@ -1,5 +1,7 @@
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'
@@ -7,6 +9,7 @@ export default class Pencil extends Tool {
private drawCtx: CanvasRenderingContext2D
private drawCanvas: HTMLCanvasElement
private isDrawing = false
+ private cursorCircle: CursorCircle
private drawOptions: Required = {
color: 'rgb(0,0,0)',
size: 1,
@@ -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)
@@ -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
@@ -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) {
@@ -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 ``
+ }
+ html = ``
+ } else {
+ html = painter.c('')
+ }
+ this.$container.html(html)
+ }
+}
+
interface IDrawOptions {
color?: string
size?: number
diff --git a/src/painter/tools/Tool.ts b/src/painter/tools/Tool.ts
index 6d3cdcd..1afc51a 100644
--- a/src/painter/tools/Tool.ts
+++ b/src/painter/tools/Tool.ts
@@ -1,11 +1,12 @@
import Painter, { Layer } from '../'
import $ from 'licia/$'
import h from 'licia/h'
+import Emitter from 'licia/Emitter'
import types from 'licia/types'
import { eventPage } from '../../share/util'
import LunaToolbar from 'luna-toolbar'
-export default class Tool {
+export default class Tool extends Emitter {
protected painter: Painter
protected x = -1
protected lastX = -1
@@ -24,6 +25,7 @@ export default class Tool {
protected options: types.PlainObj = {}
protected isUsing = false
constructor(painter: Painter) {
+ super()
this.painter = painter
this.viewport = painter.$container
@@ -43,17 +45,19 @@ export default class Tool {
const toolbar = new LunaToolbar(h('div'))
this.toolbar = toolbar
toolbar.on('change', (key, val) => {
- this.options[key] = val
+ this.setOption(key, val, false)
})
painter.addSubComponent(toolbar)
this.cursor = h(`div.${painter.c('cursor')}`) as HTMLDivElement
this.$cursor = $(this.cursor)
}
- setOption(name: string, val: any) {
+ setOption(name: string, val: any, renderToolbar = true) {
this.options[name] = val
- this.renderToolbar()
+ if (renderToolbar) {
+ this.renderToolbar()
+ }
}
onDragStart(e: any) {
this.getXY(e)
@@ -82,7 +86,6 @@ export default class Tool {
onMouseMove(e: any) {
const { $cursor, $viewportOverlay } = this
const overlayOffset = $viewportOverlay.offset()
- const offset = $cursor.offset()
const x = eventPage('x', e) - overlayOffset.left
const y = eventPage('y', e) - overlayOffset.top
@@ -93,8 +96,8 @@ export default class Tool {
})
} else {
$cursor.css({
- left: x - offset.width / 2,
- top: y - offset.height / 2,
+ left: x,
+ top: y,
opacity: 1,
})
}
@@ -111,6 +114,7 @@ export default class Tool {
})
}
onAfterRenderLayer(layer: Layer) {}
+ onZoom() {}
protected renderToolbar() {
this.toolbar.clear()
}
@@ -120,8 +124,8 @@ export default class Tool {
const pageX = eventPage('x', e)
const pageY = eventPage('y', e)
- const x = Math.floor(((pageX - offset.left) / offset.width) * canvas.width)
- const y = Math.floor(((pageY - offset.top) / offset.height) * canvas.height)
+ const x = Math.round(((pageX - offset.left) / offset.width) * canvas.width)
+ const y = Math.round(((pageY - offset.top) / offset.height) * canvas.height)
this.lastX = this.x
this.x = x
diff --git a/src/painter/tools/Zoom.ts b/src/painter/tools/Zoom.ts
index 1325f11..eee1130 100644
--- a/src/painter/tools/Zoom.ts
+++ b/src/painter/tools/Zoom.ts
@@ -11,6 +11,7 @@ interface IPivot {
export default class Zoom extends Tool {
private isZooming = false
private isAltDown = false
+ private ratio = 1
constructor(painter: Painter) {
super(painter)
@@ -49,11 +50,15 @@ export default class Zoom extends Tool {
const offset = this.$canvas.offset()
this.zoomTo((offset.width * ratio) / this.canvas.width, pivot)
}
+ getRatio() {
+ return this.ratio
+ }
zoomTo(ratio: number, pivot?: IPivot) {
if (this.isZooming) {
return
}
this.isZooming = true
+ this.ratio = ratio
const { canvas, viewport, $canvas } = this
@@ -104,6 +109,7 @@ export default class Zoom extends Tool {
})
viewport.scrollLeft = target.scrollLeft
viewport.scrollTop = target.scrollTop
+ this.emit('change')
})
.on('end', () => {
this.isZooming = false
@@ -122,8 +128,8 @@ export default class Zoom extends Tool {
)
.play()
}
- setOption(name: string, val: any) {
- super.setOption(name, val)
+ setOption(name: string, val: any, renderToolbar?: boolean) {
+ super.setOption(name, val, renderToolbar)
if (name === 'mode') {
const { c } = this.painter
const $icon = this.$cursor.find(c('.icon'))