mirror of
https://github.com/rubickCenter/rubick
synced 2025-12-16 07:36:30 +08:00
feat: 支持截屏,下载方式调整
This commit is contained in:
411
static/plugins/capture/capture-editor.js
Normal file
411
static/plugins/capture/capture-editor.js
Normal file
@@ -0,0 +1,411 @@
|
||||
const Event = require('events')
|
||||
const { getCurrentScreen } = require('./utils')
|
||||
|
||||
const CREATE_RECT = 1
|
||||
const MOVING_RECT = 2
|
||||
const RESIZE = 3
|
||||
|
||||
const ANCHORS = [
|
||||
{ row: 'x', col: 'y', cursor: 'nwse-resize' },
|
||||
{ row: '', col: 'y', cursor: 'ns-resize' },
|
||||
{ row: 'r', col: 'y', cursor: 'nesw-resize' },
|
||||
|
||||
{ row: 'x', col: '', cursor: 'ew-resize' },
|
||||
{ row: 'r', col: '', cursor: 'ew-resize' },
|
||||
|
||||
{ row: 'x', col: 'b', cursor: 'nesw-resize' },
|
||||
{ row: '', col: 'b', cursor: 'ns-resize' },
|
||||
{ row: 'r', col: 'b', cursor: 'nwse-resize' },
|
||||
]
|
||||
|
||||
class CaptureEditor extends Event {
|
||||
|
||||
constructor($canvas, $bg, imageSrc) {
|
||||
super()
|
||||
this.$canvas = $canvas
|
||||
this.imageSrc = imageSrc
|
||||
this.disabled = false
|
||||
let currentScreen;
|
||||
|
||||
(async () => {
|
||||
currentScreen = await getCurrentScreen();
|
||||
this.scaleFactor = currentScreen.scaleFactor
|
||||
this.screenWidth = currentScreen.bounds.width
|
||||
this.screenHeight = currentScreen.bounds.height
|
||||
this.init().then(() => {
|
||||
// console.log('init')
|
||||
})
|
||||
})();
|
||||
this.$bg = $bg
|
||||
this.ctx = $canvas.getContext('2d')
|
||||
|
||||
this.onMouseDown = this.onMouseDown.bind(this)
|
||||
this.onMouseMove = this.onMouseMove.bind(this)
|
||||
this.onMouseUp = this.onMouseUp.bind(this)
|
||||
}
|
||||
|
||||
async init() {
|
||||
this.$bg.style.backgroundImage = `url(${this.imageSrc})`
|
||||
this.$bg.style.backgroundSize = `${this.screenWidth}px ${this.screenHeight}px`
|
||||
let canvas = document.createElement('canvas')
|
||||
let ctx = canvas.getContext('2d')
|
||||
let img = await new Promise((resolve) => {
|
||||
let img = new Image()
|
||||
img.src = this.imageSrc
|
||||
if (img.complete) {
|
||||
resolve(img)
|
||||
} else {
|
||||
img.onload = () => resolve(img)
|
||||
}
|
||||
})
|
||||
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
ctx.drawImage(img, 0, 0)
|
||||
this.bgCtx = ctx
|
||||
|
||||
document.addEventListener('mousedown', this.onMouseDown)
|
||||
document.addEventListener('mousemove', this.onMouseMove)
|
||||
document.addEventListener('mouseup', this.onMouseUp)
|
||||
}
|
||||
|
||||
onMouseDown(e) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
this.mouseDown = true
|
||||
const { pageX, pageY } = e
|
||||
if (this.selectRect) {
|
||||
const {
|
||||
w, h, x, y, r, b,
|
||||
} = this.selectRect
|
||||
if (this.selectAnchorIndex !== -1) {
|
||||
this.startPoint = {
|
||||
x: pageX,
|
||||
y: pageY,
|
||||
moved: false,
|
||||
selectRect: {
|
||||
w, h, x, y, r, b,
|
||||
},
|
||||
rawRect: {
|
||||
w, h, x, y, r, b,
|
||||
},
|
||||
}
|
||||
this.action = RESIZE
|
||||
return
|
||||
}
|
||||
this.startPoint = {
|
||||
x: e.pageX,
|
||||
y: e.pageY,
|
||||
moved: false,
|
||||
}
|
||||
if (pageX > x && pageX < r && pageY > y && pageY < b) {
|
||||
this.action = MOVING_RECT
|
||||
this.startDragRect = {
|
||||
x: pageX,
|
||||
y: pageY,
|
||||
selectRect: {
|
||||
x, y, w, h, r, b,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
this.action = CREATE_RECT
|
||||
}
|
||||
} else {
|
||||
this.action = CREATE_RECT
|
||||
this.startPoint = {
|
||||
x: e.pageX,
|
||||
y: e.pageY,
|
||||
moved: false,
|
||||
}
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
onMouseDrag(e) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
|
||||
const { pageX, pageY } = e
|
||||
let startDragging
|
||||
let selectRect = this.selectRect
|
||||
if (!this.startPoint.moved) {
|
||||
if (Math.abs(this.startPoint.x - pageX) > 10 || Math.abs(this.startPoint.y - pageY) > 10) {
|
||||
this.startPoint.moved = true
|
||||
startDragging = true
|
||||
}
|
||||
}
|
||||
if (!this.startPoint.moved) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.action === MOVING_RECT) {
|
||||
// 移动选区
|
||||
if (startDragging) {
|
||||
this.emit('start-dragging', selectRect)
|
||||
}
|
||||
this.emit('dragging', selectRect)
|
||||
const { w, h } = selectRect
|
||||
const { x: startX, y: startY } = this.startPoint
|
||||
let newX = this.startDragRect.selectRect.x + pageX - startX
|
||||
let newY = this.startDragRect.selectRect.y + pageY - startY
|
||||
let newR = newX + w
|
||||
let newB = newY + h
|
||||
if (newX < 0) {
|
||||
newX = 0
|
||||
newR = w
|
||||
} else if (newR > this.screenWidth) {
|
||||
newR = this.screenWidth
|
||||
newX = newR - w
|
||||
}
|
||||
if (newY < 0) {
|
||||
newY = 0
|
||||
newB = h
|
||||
} else if (newB > this.screenHeight) {
|
||||
newB = this.screenHeight
|
||||
newY = newB - h
|
||||
}
|
||||
this.selectRect = {
|
||||
w,
|
||||
h,
|
||||
x: newX,
|
||||
y: newY,
|
||||
r: newR,
|
||||
b: newB,
|
||||
}
|
||||
this.drawRect()
|
||||
} else if (this.action === RESIZE) {
|
||||
this.emit('dragging', selectRect)
|
||||
let { row, col } = ANCHORS[this.selectAnchorIndex]
|
||||
if (row) {
|
||||
this.startPoint.rawRect[row] = this.startPoint.selectRect[row] + pageX - this.startPoint.x
|
||||
selectRect.x = this.startPoint.rawRect.x
|
||||
selectRect.r = this.startPoint.rawRect.r
|
||||
if (selectRect.x > selectRect.r) {
|
||||
let x = selectRect.r
|
||||
selectRect.r = selectRect.x
|
||||
selectRect.x = x
|
||||
}
|
||||
selectRect.w = selectRect.r - selectRect.x
|
||||
this.startPoint.rawRect.w = selectRect.w
|
||||
}
|
||||
if (col) {
|
||||
this.startPoint.rawRect[col] = this.startPoint.selectRect[col] + pageY - this.startPoint.y
|
||||
selectRect.y = this.startPoint.rawRect.y
|
||||
selectRect.b = this.startPoint.rawRect.b
|
||||
|
||||
if (selectRect.y > selectRect.b) {
|
||||
let y = selectRect.b
|
||||
selectRect.b = selectRect.y
|
||||
selectRect.y = y
|
||||
}
|
||||
selectRect.h = selectRect.b - selectRect.y
|
||||
this.startPoint.rawRect.h = selectRect.h
|
||||
}
|
||||
this.drawRect()
|
||||
} else {
|
||||
// 生成选区
|
||||
const { pageX, pageY } = e
|
||||
let x, y, w, h, r, b
|
||||
if (this.startPoint.x > pageX) {
|
||||
x = pageX
|
||||
r = this.startPoint.x
|
||||
} else {
|
||||
r = pageX
|
||||
x = this.startPoint.x
|
||||
}
|
||||
if (this.startPoint.y > pageY) {
|
||||
y = pageY
|
||||
b = this.startPoint.y
|
||||
} else {
|
||||
b = pageY
|
||||
y = this.startPoint.y
|
||||
}
|
||||
w = r - x
|
||||
h = b - y
|
||||
|
||||
|
||||
this.selectRect = {
|
||||
x, y, w, h, r, b,
|
||||
}
|
||||
selectRect = this.selectRect
|
||||
if (startDragging) {
|
||||
this.emit('start-dragging', selectRect)
|
||||
}
|
||||
this.emit('dragging', selectRect)
|
||||
this.drawRect(x, y, w, h)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
drawRect() {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (!this.selectRect) {
|
||||
this.$canvas.style.display = 'none'
|
||||
return
|
||||
}
|
||||
const {
|
||||
x, y, w, h,
|
||||
} = this.selectRect
|
||||
|
||||
const scaleFactor = this.scaleFactor
|
||||
let margin = 7
|
||||
let radius = 5
|
||||
this.$canvas.style.left = `${x - margin}px`
|
||||
this.$canvas.style.top = `${y - margin}px`
|
||||
this.$canvas.style.width = `${w + margin * 2}px`
|
||||
this.$canvas.style.height = `${h + margin * 2}px`
|
||||
this.$canvas.style.display = 'block'
|
||||
this.$canvas.width = (w + margin * 2) * scaleFactor
|
||||
this.$canvas.height = (h + margin * 2) * scaleFactor
|
||||
|
||||
if (w && h) {
|
||||
let imageData = this.bgCtx.getImageData(x * scaleFactor, y * scaleFactor, w * scaleFactor, h * scaleFactor)
|
||||
this.ctx.putImageData(imageData, margin * scaleFactor, margin * scaleFactor)
|
||||
}
|
||||
this.ctx.fillStyle = '#ffffff'
|
||||
this.ctx.strokeStyle = '#67bade'
|
||||
this.ctx.lineWidth = 2 * this.scaleFactor
|
||||
|
||||
this.ctx.strokeRect(margin * scaleFactor, margin * scaleFactor, w * scaleFactor, h * scaleFactor)
|
||||
this.drawAnchors(w, h, margin, scaleFactor, radius)
|
||||
}
|
||||
|
||||
drawAnchors(w, h, margin, scaleFactor, radius) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (this.mouseDown && this.action === CREATE_RECT) {
|
||||
this.anchors = null
|
||||
return
|
||||
}
|
||||
this.ctx.beginPath()
|
||||
let anchors = [
|
||||
[0, 0],
|
||||
[w * this.scaleFactor / 2, 0],
|
||||
[w * this.scaleFactor, 0],
|
||||
|
||||
[0, h * this.scaleFactor / 2],
|
||||
[w * this.scaleFactor, h * this.scaleFactor / 2],
|
||||
|
||||
[0, h * this.scaleFactor],
|
||||
[w * this.scaleFactor / 2, h * this.scaleFactor],
|
||||
[w * this.scaleFactor, h * this.scaleFactor],
|
||||
]
|
||||
this.anchors = anchors.map(([x, y]) => [this.selectRect.x + x / scaleFactor, this.selectRect.y + y / scaleFactor])
|
||||
anchors.forEach(([x, y], i) => {
|
||||
this.ctx.arc(x + margin * scaleFactor, y + margin * scaleFactor, radius * scaleFactor, 0, 2 * Math.PI)
|
||||
let next = anchors[(i + 1) % anchors.length]
|
||||
this.ctx.moveTo(next[0] + margin * scaleFactor + radius * scaleFactor, next[1] + margin * scaleFactor)
|
||||
})
|
||||
this.ctx.closePath()
|
||||
this.ctx.fill()
|
||||
this.ctx.stroke()
|
||||
}
|
||||
|
||||
onMouseMove(e) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (this.mouseDown) {
|
||||
this.onMouseDrag(e)
|
||||
return
|
||||
}
|
||||
this.selectAnchorIndex = -1
|
||||
if (this.selectRect) {
|
||||
const { pageX, pageY } = e
|
||||
const {
|
||||
x, y, r, b,
|
||||
} = this.selectRect
|
||||
let selectAnchor, selectIndex = -1
|
||||
if (this.anchors) {
|
||||
this.anchors.forEach(([x, y], i) => {
|
||||
if (Math.abs(pageX - x) <= 10 && Math.abs(pageY - y) <= 10) {
|
||||
selectAnchor = [x, y]
|
||||
selectIndex = i
|
||||
}
|
||||
})
|
||||
}
|
||||
if (selectAnchor) {
|
||||
this.selectAnchorIndex = selectIndex
|
||||
document.body.style.cursor = ANCHORS[selectIndex].cursor
|
||||
this.emit('moving')
|
||||
return
|
||||
}
|
||||
if (pageX > x && pageX < r && pageY > y && pageY < b) {
|
||||
document.body.style.cursor = 'move'
|
||||
} else {
|
||||
document.body.style.cursor = 'auto'
|
||||
}
|
||||
this.emit('moving')
|
||||
}
|
||||
}
|
||||
|
||||
onMouseUp(e) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (!this.mouseDown) {
|
||||
return
|
||||
}
|
||||
this.mouseDown = false
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
this.emit('mouse-up')
|
||||
if (!this.startPoint.moved) {
|
||||
this.emit('end-moving')
|
||||
return
|
||||
}
|
||||
this.emit('end-dragging')
|
||||
this.drawRect()
|
||||
this.startPoint = null
|
||||
}
|
||||
|
||||
getImageUrl() {
|
||||
const scaleFactor = this.scaleFactor
|
||||
const {
|
||||
x, y, w, h,
|
||||
} = this.selectRect
|
||||
if (w && h) {
|
||||
let imageData = this.bgCtx.getImageData(x * scaleFactor, y * scaleFactor, w * scaleFactor, h * scaleFactor)
|
||||
let canvas = document.createElement('canvas')
|
||||
canvas.width = w
|
||||
canvas.height = h
|
||||
let ctx = canvas.getContext('2d')
|
||||
ctx.putImageData(imageData, 0, 0)
|
||||
return canvas.toDataURL()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
disable() {
|
||||
this.disabled = true
|
||||
}
|
||||
|
||||
enable() {
|
||||
this.disabled = false
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.anchors = null
|
||||
this.startPoint = null
|
||||
this.selectRect = null
|
||||
this.startDragRect = null
|
||||
this.selectAnchorIndex = -1
|
||||
this.drawRect()
|
||||
this.emit('reset')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exports.CaptureEditor = CaptureEditor
|
||||
exports.CREATE_RECT = CREATE_RECT
|
||||
exports.MOVING_RECT = MOVING_RECT
|
||||
exports.RESIZE = RESIZE
|
||||
Reference in New Issue
Block a user